/* * convert selection statement into tuple $$.tuple = tuple_selection_statement( $3.tuple, $5.tuple, 0); $$.tuple = tuple_selection_statement( $3.tuple, $5.tuple, $7.tuple); */ TUPLE *tuple_selection_statement( TUPLE *expr, TUPLE *statement1, TUPLE *statement2) { char buffer1[ 32]; int length1; char buffer2[ 32]; int length2; TUPLE *tuple; length1 = next_label( buffer1); tuple = end_tuple_list( expr); tuple->next = new_tuple( I_BTFSC, 0x02, 0x03, MASK_ADDRESS | MASK_VALUE, 0, 0); tuple->next->next = new_tuple( I_GOTO, 0, 0, MASK_LABEL, buffer1, length1); tuple_tail_to_head( tuple, statement1); tuple = end_tuple_list( statement1); if( ! statement2) tuple->next = new_tuple( I_LABEL, length1, 0, MASK_LABEL, buffer1, length1); else { length2 = next_label( buffer2); tuple->next = new_tuple( I_GOTO, 0, 0, MASK_LABEL, buffer2, length2); tuple->next->next = new_tuple( I_LABEL, length1, 0, MASK_LABEL, buffer1, length1); tuple_tail_to_head( tuple, statement2); tuple = end_tuple_list( statement2); tuple->next = new_tuple( I_LABEL, length2, 0, MASK_LABEL, buffer2, length2); } return( expr); }
// pops a matrix that is on the stack, into the variable contained in node static void pop_into_whole_matrix(ClmExpNode *node) { // TODO case where matrix on stack is actually a pointer char index_str[64]; ClmSymbol *var = clm_scope_find(data.scope, node->indExp.id); char cmp_label[LABEL_SIZE]; char end_label[LABEL_SIZE]; next_label(cmp_label); next_label(end_label); asm_pop(EAX); // pop type asm_pop(ECX); // pop rows asm_pop(EBX); // pop cols; // todo assert rows == A.rows && cols == A.cols asm_imul(ECX, EBX); // ecx now contains rows * cols asm_dec(ECX); asm_label(cmp_label); asm_cmp(ECX, "0"); asm_jmp_l(end_label); asm_mov(EAX, ECX); asm_imul(EAX, "4"); load_var_location(var, index_str, 12, EAX); asm_pop(index_str); asm_dec(ECX); asm_jmp(cmp_label); asm_label(end_label); }
/* * allocate a quad5 function $$.quad = new_quad5( IFTRUE, $3.quad, $5.quad, 0); // if $$.quad = new_quad5( IFTRUE, $3.quad, $5.quad, $7.quad); // if else */ QUAD *new_quad5( int operator, QUAD *q1, QUAD *q2, QUAD *q3) { QUAD *me; QUAD *last1 = end_quad_list( q1); QUAD *last2 = end_quad_list( q2); QUAD *label1 = new_quad( LABEL, TYPE_LABEL, next_label(), 0,0, 0,0); QUAD *last3; QUAD *label2; QUAD *theGoto; if ( q3 == 0){ me = new_quad( operator, last1->dst_type, last1->dst_index, label1->dst_type, label1->dst_index, 0, 0); } else { last3 = end_quad_list( q3); label2 = new_quad( LABEL, TYPE_LABEL, next_label(), 0,0, 0,0); theGoto = new_quad( GOTO, TYPE_LABEL, label2->dst_index, 0,0, 0,0); me = new_quad( operator, last1->dst_type, last1->dst_index, label1->dst_type, label1->dst_index, label2->dst_type, label2->dst_index); } last1->next = me; me->next = q2; if ( q3 != 0){ last2->next = theGoto; theGoto->next= label1; label1->next = q3; last3->next = label2; } else { last2->next = label1; } return q1; }
// operator = IF // q1 = if (bla) // q2 = then bla // q3 = else bla QUAD *new_quad5E(int operator, QUAD *q1, QUAD *q2, QUAD *q3) { int if_goto = next_label(); int then_goto = next_label(); QUAD *ifstatement, *thenstatement, *elsestatement; ifstatement = end_quad_list(q1); ifstatement->next = new_quad(operator, ifstatement->dst_type, ifstatement->dst_index, TYPE_LABEL, if_goto, 0, 0); ifstatement->next->next = q2; thenstatement = end_quad_list(ifstatement); thenstatement->next = new_quad(GOTO, TYPE_LABEL, then_goto, 0, 0, 0, 0); thenstatement->next->next = new_quad(LABEL, TYPE_LABEL, if_goto, 0, 0, 0, 0); thenstatement->next->next->next = q3; end_quad_list(q3)->next = new_quad(LABEL, TYPE_LABEL, then_goto, 0, 0, 0, 0); return q1; }
DnsQuestions ParseQuestions(const uint8_t* dns, unsigned length) { DnsQuestions result; if(dns_isquery(dns, length)) { unsigned nq = dns_numQuestions(dns, length); dns += 12; length -= 12; for(unsigned i=0; i < nq; ++i) { std::string name; while(true) { std::string label = next_label(dns, length); // updates dns, length to new values. if(label.empty()) break; name += label; name += "."; } DnsQuestion q(name); result.push_back(std::move(q)); } } else printf("Not query\n"); return result; }
static void write_cond(tree *cond) { char *end_label = NULL; /* else doesn't have a condition */ if (cond->value.cond.cond != NULL) { end_label = next_label(); fprintf(state.output.f, ";#CSRC %s %d\n", state.srcfilename, cond->value.cond.cond->line_number); temp_number = 0; write_test(cond->value.cond.cond, end_label); if (temp_number > max_temp_number) max_temp_number = temp_number; } /* write the body of the code */ write_statements(cond->value.cond.body); /* if there is a condition generate a label at the end of the body */ if (cond->value.cond.cond != NULL) { write_label(end_label); if (end_label) free(end_label); } /* generate next conditional block, if there is one */ if (cond->value.cond.next != NULL) write_cond(cond->value.cond.next); }
static void gen_while_loop(ClmStmtNode *node) { char cmp_label[LABEL_SIZE]; char end_label[LABEL_SIZE]; next_label(cmp_label); next_label(end_label); asm_label(cmp_label); // don't need to store this - just evaulate every loop push_expression(node->whileLoopStmt.condition); pop_int_into(EAX); asm_cmp(EAX, "0"); asm_jmp_eq(end_label); gen_statements(node->whileLoopStmt.body); asm_jmp(cmp_label); asm_label(end_label); }
// operator = IF // q1 = if (bla) // q2 = then bla QUAD *new_quad5(int operator, QUAD *q1, QUAD *q2) { int goto_label = next_label(); QUAD *ifstatement, *thenstatement; ifstatement = end_quad_list(q1); ifstatement->next = new_quad(operator, ifstatement->dst_type, ifstatement->dst_index, TYPE_LABEL, goto_label, 0, 0); ifstatement->next->next = q2; thenstatement = end_quad_list(ifstatement); thenstatement->next = new_quad(LABEL, TYPE_LABEL, goto_label, 0, 0, 0, 0); return q1; }
static void gen_conditional(ClmStmtNode *node) { push_expression(node->conditionStmt.condition); if (node->conditionStmt.falseBody == NULL) { char end_label[LABEL_SIZE]; next_label(end_label); ClmScope *trueScope = clm_scope_find_child(data.scope, node->conditionStmt.trueBody); asm_pop(EAX); asm_cmp(EAX, "1"); asm_jmp_neq(end_label); data.scope = trueScope; gen_statements(node->conditionStmt.trueBody); asm_label(end_label); data.scope = trueScope->parent; } else { char end_label[LABEL_SIZE]; char false_label[LABEL_SIZE]; next_label(end_label); next_label(false_label); ClmScope *trueScope = clm_scope_find_child(data.scope, node->conditionStmt.trueBody); ClmScope *falseScope = clm_scope_find_child(data.scope, node->conditionStmt.falseBody); asm_pop(EAX); asm_cmp(EAX, "1"); asm_jmp_neq(false_label); data.scope = trueScope; gen_statements(node->conditionStmt.trueBody); asm_jmp(end_label); asm_label(false_label); data.scope = falseScope; gen_statements(node->conditionStmt.falseBody); asm_label(end_label); data.scope = falseScope->parent; } }
static void gen_for_loop(ClmStmtNode *node) { char cmp_label[LABEL_SIZE]; char end_label[LABEL_SIZE]; next_label(cmp_label); next_label(end_label); ClmSymbol *var = clm_scope_find(data.scope, node->forLoopStmt.varId); char loop_var[32]; load_var_location(var, loop_var, 4, NULL); // don't need to store this - just evaluate and put into loop var push_expression(node->forLoopStmt.start); pop_int_into(loop_var); asm_label(cmp_label); // don't need to store this - just evaulate every loop push_expression(node->forLoopStmt.end); pop_int_into(EAX); asm_cmp(loop_var, EAX); asm_jmp_g(end_label); gen_statements(node->forLoopStmt.body); if (node->forLoopStmt.delta->type == EXP_TYPE_INT && node->forLoopStmt.delta->ival == 1) { asm_inc(loop_var); } else if (node->forLoopStmt.delta->type == EXP_TYPE_INT && node->forLoopStmt.delta->ival == -1) { asm_dec(loop_var); } else if (node->forLoopStmt.delta->type == EXP_TYPE_INT) { asm_add_i(loop_var, node->forLoopStmt.delta->ival); } else { push_expression(node->forLoopStmt.delta); asm_pop(EAX); asm_add(loop_var, EAX); } asm_jmp(cmp_label); asm_label(end_label); }
// pushes a matrix identified by the node onto the stack static void push_whole_matrix(ClmExpNode *node) { // TODO case where matrix on stack is actually a pointer char index_str[64]; ClmSymbol *var = clm_scope_find(data.scope, node->indExp.id); char cmp_label[LABEL_SIZE]; char end_label[LABEL_SIZE]; next_label(cmp_label); next_label(end_label); LOAD_COLS(var, index_str); asm_mov(EDX, index_str); // edx = cols LOAD_ROWS(var, index_str); asm_mov(EBX, index_str); // ebx = rows asm_mov(ECX, EBX); asm_imul(ECX, EDX); asm_dec(ECX); // ecx = rows * cols - 1 asm_label(cmp_label); asm_cmp(ECX, "0"); asm_jmp_l(end_label); asm_mov(EAX, ECX); asm_imul(EAX, "4"); load_var_location(var, index_str, 12, EAX); asm_push(index_str); asm_dec(ECX); asm_jmp(cmp_label); asm_label(end_label); // push type info asm_push(EDX); // cols asm_push(EBX); // rows asm_push_const_i((int)CLM_TYPE_MATRIX); }
/* * iteration selection statement into tuple $$.tuple = tuple_iteration_statement( $3.tuple, $5.tuple); */ TUPLE *tuple_iteration_statement( TUPLE *expr, TUPLE *statement) { char buffer1[ 32]; int length1; char buffer2[ 32]; int length2; TUPLE *tuple; TUPLE *tuple2; /* * create the next temporary label */ length1 = next_label( buffer1); length2 = next_label( buffer2); tuple = new_tuple( I_LABEL, length1, 0, MASK_LABEL, buffer1, length1); tuple->next = expr; tuple2 = end_tuple_list( expr); tuple2->next = new_tuple( I_BTFSC, 0x02, 0x03, MASK_ADDRESS | MASK_VALUE, 0, 0); tuple2->next->next = new_tuple( I_GOTO, 0, 0, MASK_LABEL, buffer2, length2); tuple_tail_to_head( tuple2, statement); tuple2 = end_tuple_list( statement); tuple2->next = new_tuple( I_GOTO, 0, 0, MASK_LABEL, buffer1, length1); tuple2->next->next = new_tuple( I_LABEL, length2, 0, MASK_LABEL, buffer2, length2); return( tuple); }
/* ******************************* * * Generate the next permutation * * ******************************* */ int next_sample(int *L) { if(local_perm_count >= local_perm_size) return 0; // Note: local_pa.B == 0 => complete permutations // local_pa.B > 0 => random permutations if(local_pa.B > 0) { get_permu(&local_pa, local_perm_count, L); } else { next_label(local_pa.n, local_pa.k, local_pa.nk, local_L); memcpy(L, local_L, sizeof(int) * local_pa.n); } local_perm_count++; return 1; }
static void write_loop(tree *loop) { char *start_label = NULL; /* write out initalization code */ if (loop->value.loop.init != NULL) { write_statements(loop->value.loop.init); } start_label = next_label(); write_label(start_label); /* write the body of the loop */ if (loop->value.loop.body != NULL) write_statements(loop->value.loop.body); /* write the increment statements */ if (loop->value.loop.incr != NULL) write_statements(loop->value.loop.incr); /* write the exit statements */ if (loop->value.loop.exit != NULL) { fprintf(state.output.f, ";#CSRC %s %d\n", state.srcfilename, loop->value.loop.exit->line_number); temp_number = 0; write_test(loop->value.loop.exit, start_label); if (temp_number > max_temp_number) max_temp_number = temp_number; } else { write_asm_line("goto %s", start_label); } if (start_label) free(start_label); }
// pops a matrix from the stack into a row or column of a matrix identified by // node static void pop_into_row_or_col(ClmExpNode *node) { // TODO case where matrix on stack is actually a pointer char index_str[64]; ClmSymbol *var = clm_scope_find(data.scope, node->indExp.id); char cmp_label[LABEL_SIZE]; char end_label[LABEL_SIZE]; next_label(cmp_label); next_label(end_label); // put index value into EDX if(node->indExp.rowIndex != NULL){ gen_index_into(EDX, node->indExp.rowIndex); }else{ gen_index_into(EDX, node->indExp.colIndex); } asm_pop(EAX); // pop type asm_pop(EAX); // pop rows asm_pop(EBX); // pop cols // todo assert rows == A.rows or cols == A.cols asm_mov(ECX, "0"); if (node->indExp.rowIndex != NULL) { /* A[x,] for i in 1..A.cols do A[x * A.cols + i] = pop end */ LOAD_COLS(var, index_str); asm_imul(EDX, index_str); asm_label(cmp_label); asm_cmp(ECX, index_str); asm_jmp_eq(end_label); asm_mov(EAX, EDX); asm_add(EAX, ECX); // eax now contains rowIndex * A.cols + i asm_imul(EAX, "4"); load_var_location(var, index_str, 12, EAX); asm_pop(index_str); } else { /* A[,y] for i in 1..A.rows do A[i * A.cols + y] = pop end */ LOAD_ROWS(var, index_str); asm_label(cmp_label); asm_cmp(ECX, index_str); asm_jmp_eq(end_label); asm_mov(EAX, ECX); asm_imul(EAX, index_str); asm_add(EAX, EDX); asm_imul(EAX, "4"); load_var_location(var, index_str, 12, EAX); asm_pop(index_str); } asm_inc(ECX); asm_jmp(cmp_label); asm_label(end_label); }
/* ******************************************************** * * Create the sampling structure and initialize all values * * ******************************************************** */ void create_sampling(int n, int *L, int B, int generator_flag, int initial_count) { int *ordern, *permun, *myL; int i; // Set the local size of permutations local_perm_size = B; local_perm_count = 1; // Allocate and initialize local L to original L local_L = (int *)R_alloc(n, sizeof(int)); // To check random or complete if( generator_flag == 1 ) { // Initialize the permutation array (struct) // Sets the B in the struct equal to 0 to be // able to identify the generator later on init_permu_array(&local_pa, L, n, 0); // * ================================================================= * // * Forwarding logic * // * ---------------- * // * For parallel executions all processes, appart from the one with * // * rank == 0, should forward their random generators in order to * // * be able to reproduce the exact same random permutations as the * // * serial version of the code (or a version with only one thread) * // * * // * The code below uses the initial_count variable to "burn" the * // * cycles from the random generator * // * ================================================================= * // All processes apart from process with rank == 0 (translates to // initial_count == 0) will perform this forward if ( initial_count != 0 ) { // Initialize label init_label(local_pa.n, local_pa.k, local_pa.nk, local_L); // Burn the cycles // We *must* use L in order to initialize it in the proper permutation // L is given as the starting position for the next permutation for(i=0; i < initial_count; i++) { next_label(local_pa.n, local_pa.k, local_pa.nk, local_L); } } // * ================================================================= * // * ================================================================= * } else { // Intiailize the permu_array (struct) init_permu_array(&local_pa, L, n, B); permun = (int *)R_alloc(local_pa.n, sizeof(int)); ordern = (int*)R_alloc(local_pa.n, sizeof(int)); myL = (int *)R_alloc(local_pa.n, sizeof(int)); // * ================================================================= * // * Forwarding logic * // * ---------------- * // * For parallel executions all processes, appart from the one with * // * rank == 0, should forward their random generators in order to * // * be able to reproduce the exact same random permutations as the * // * serial version of the code (or a version with only one thread) * // * * // * The code below uses the initial_count variable to "burn" the * // * cycles from the random generator * // * ================================================================= * // Set initial seed set_seed(g_random_seed); // Burn the cycles // ("permun" is a safe scratch space for this) for(i=0; i < initial_count; i++) { sample(permun, n); } // * ================================================================= * // * ================================================================= * for(i=0; i<n; i++){ ordern[i]=i; } // Allocate and assign the values for l_first_sample set_permu(&local_pa, 0, L); for(i=1; i<B; i++) { memcpy(permun, ordern, sizeof(int)*n); sample(permun, n); // Change to labbeling sample2label(n, local_pa.k, local_pa.nk, permun, myL); set_permu(&local_pa, i, myL); } } }
// pushes a row or col of the matrix identified by node onto the stack static void push_row_or_col(ClmExpNode *node) { // TODO case where matrix on stack is actually a pointer char index_str[64]; ClmSymbol *var = clm_scope_find(data.scope, node->indExp.id); char cmp_label[LABEL_SIZE]; char end_label[LABEL_SIZE]; next_label(cmp_label); next_label(end_label); // put index value into EDX if(node->indExp.rowIndex != NULL){ gen_index_into(EDX, node->indExp.rowIndex); }else{ gen_index_into(EDX, node->indExp.colIndex); } if (node->indExp.rowIndex != NULL) { /* push A[x,] for i in A.cols,-1..1 do push A[x * A.cols + i] end */ LOAD_COLS(var, index_str); asm_mov(ECX, index_str); asm_imul(EDX, ECX); asm_dec(ECX); asm_label(cmp_label); asm_cmp(ECX, "0"); asm_jmp_l(end_label); asm_mov(EAX, EDX); asm_add(EAX, ECX); // eax = rowIndex * A.cols + i asm_imul(EAX, "4"); load_var_location(var, index_str, 12, EAX); asm_push(index_str); } else { /* push A[,y] for i in A.rows,-1..1 do push A[i * A.cols + y] end */ LOAD_ROWS(var, index_str); asm_mov(ECX, index_str); asm_dec(ECX); asm_label(cmp_label); asm_cmp(ECX, "0"); asm_jmp_l(end_label); asm_mov(EAX, ECX); asm_imul(EAX, index_str); asm_add(EAX, EDX); // eax = i * A.cols + y asm_imul(EAX, "4"); load_var_location(var, index_str, 12, EAX); asm_push(index_str); } asm_inc(ECX); asm_jmp(cmp_label); asm_label(end_label); }
// stack should look like this: // val // type static void push_expression(ClmExpNode *node) { if (node == NULL) return; ClmType expression_type = clm_type_of_exp(node, data.scope); switch (node->type) { case EXP_TYPE_INT: asm_push_const_i(node->ival); asm_push_const_i((int)expression_type); break; case EXP_TYPE_FLOAT: asm_push_const_f(node->fval); asm_push_const_i((int)expression_type); break; case EXP_TYPE_STRING: // TODO push a string onto the stack break; case EXP_TYPE_ARITH: { ClmType right_type = clm_type_of_exp(node->arithExp.right, data.scope); ClmType left_type = clm_type_of_exp(node->arithExp.left, data.scope); if (left_type == CLM_TYPE_MATRIX && clm_type_is_number(right_type)) { // here the only ops are mul & div... we are scaling matrix // gen left and then right here... if we don't then we have // int val // int type // matrix // cols // rows // matrix type // and we have to pop the int after we generate the value... which is hard // and since we are multiplying the matrix in place, it would be easiest // to // gen the matrix first and then the int, so we just have to pop two // values // in total push_expression(node->arithExp.left); asm_mov(EDX, ESP); push_expression(node->arithExp.right); gen_arith(node); } else { push_expression(node->arithExp.right); asm_mov(EDX, ESP); push_expression(node->arithExp.left); gen_arith(node); } break; } case EXP_TYPE_BOOL: push_expression(node->boolExp.right); asm_mov(EDX, ESP); push_expression(node->boolExp.left); gen_bool(node); break; case EXP_TYPE_CALL: { // first push everything thats not a matrix... and for matrices push a pointer int tempStartID = data.temporaryID; int i; ClmExpNode *param; char temporary[256]; // first for any matrices that are parameters that will be pushed through // the stack, push them on the stack and save their location into a temporary // global for (i = node->callExp.params->length - 1; i >= 0; i--) { param = node->callExp.params->data[i]; if(param->type == CLM_TYPE_MATRIX){ ClmLocation location = clm_location_of_exp(param, data.scope); switch(location){ case LOCATION_STACK: push_expression(param); next_temporary(temporary); asm_mov(temporary, ESP); break; default: break; } } } // then push every expression.. when we get to a matrix, push the pointer // to its location int tempOffset = 1; char index_str[256]; for (i = node->callExp.params->length - 1; i >= 0; i--) { param = node->callExp.params->data[i]; if(param->type == CLM_TYPE_MATRIX){ ClmLocation location = clm_location_of_exp(param, data.scope); switch(location){ case LOCATION_STACK: sprintf(temporary, "dword [temporary%d]", tempStartID + tempOffset); asm_push(temporary); tempOffset++; break; default: { // the only way its a matrix and not on the stack is if its an // ind exp with no indices ClmSymbol *symbol = clm_scope_find(data.scope, param->indExp.id); load_var_location(symbol, index_str, 0, NULL); asm_push(index_str); break; } } asm_push_const_i((int) CLM_TYPE_MATRIX); }else{ push_expression(param); } } asm_call(node->callExp.name); // TODO pop off arguments from the stack break; } case EXP_TYPE_INDEX: push_index(node); break; case EXP_TYPE_MAT_DEC: { int i; if (node->matDecExp.arr != NULL) { for (i = node->matDecExp.length - 1; i >= 0; i--) { // TODO... push f or push i? asm_push_const_i((int)node->matDecExp.arr[i]); } asm_push_const_i(node->matDecExp.size.cols); asm_push_const_i(node->matDecExp.size.rows); asm_push_const_i((int)CLM_TYPE_MATRIX); } else { // push a matrix onto the stack with all 0s char cmp_label[LABEL_SIZE]; char end_label[LABEL_SIZE]; next_label(cmp_label); next_label(end_label); gen_exp_size(node); asm_pop(EAX); // # rows asm_pop(EBX); // # cols asm_mov(ECX, EAX); asm_imul(ECX, EBX); asm_dec(ECX); asm_label(cmp_label); asm_cmp(ECX, "0"); asm_jmp_l(end_label); asm_push_const_i(0); asm_dec(ECX); asm_jmp(cmp_label); asm_label(end_label); asm_push(EBX); asm_push(EAX); asm_push_const_i((int)CLM_TYPE_MATRIX); } break; } case EXP_TYPE_PARAM: break; case EXP_TYPE_UNARY: push_expression(node->unaryExp.node); gen_unary(node); break; } }
static void gen_func_dec(ClmStmtNode *node) { int i; char func_label[LABEL_SIZE]; sprintf(func_label, "_%s", node->funcDecStmt.name); ClmScope *funcScope = clm_scope_find_child(data.scope, node); asm_label(func_label); asm_push(EBP); asm_mov(EBP, ESP); int local_var_size = 2 * 4 * (funcScope->symbols->length - node->funcDecStmt.parameters->length); char local_var_size_str[32]; sprintf(local_var_size_str, "%d", local_var_size); asm_sub(ESP, local_var_size_str); // each local var has 2 slots on the stack, their type and the value // for matrices, the value is a pointer to the location on the stack // these are all declared below the local variables ClmSymbol *sym; ClmExpNode *dec; char cmp_label[LABEL_SIZE]; char end_label[LABEL_SIZE]; char index_str[32]; for (i = 0; i < funcScope->symbols->length; i++) { sym = funcScope->symbols->data[i]; dec = sym->declaration; if (sym->location == LOCATION_PARAMETER) continue; // setting the type of the local var load_var_location(sym, index_str, 0, NULL); asm_mov_i(index_str, (int)sym->type); // setting the value of the local var load_var_location(sym, index_str, 4, NULL); asm_mov_i(index_str, 0); if (sym->type == CLM_TYPE_MATRIX) { // TODO what does this do? does it work? next_label(cmp_label); next_label(end_label); gen_exp_size(dec); asm_pop(EAX); // eax contains num of rows asm_pop(EBX); // ebx contains num of cols asm_mov(ECX, EAX); asm_imul(ECX, EBX); asm_label(cmp_label); asm_dec(ECX); asm_cmp(ECX, "0"); asm_jmp_eq(end_label); asm_push_const_i(0); asm_jmp(cmp_label); asm_label(end_label); asm_push(EBX); // cols // setting the pointer to point at the rows // note: push changes the value at esp and THEN // decrements it load_var_location(sym, index_str, 4, NULL); asm_mov(index_str, ESP); asm_push(EAX); // rows } } // TODO figure out strings though! data.inFunction = 1; data.scope = funcScope; gen_statements(node->funcDecStmt.body); data.scope = funcScope->parent; data.inFunction = 0; if (node->funcDecStmt.returnSize.rows == -1) { // no return value! asm_mov(ESP, EBP); asm_pop(EBP); } asm_ret(); }