static void gen_modify( qli_nod* node) //, qli_req* org_request) { /************************************** * * g e n _ m o d i f y * ************************************** * * Functional description * Generate a MODIFY statement. * **************************************/ qli_req* request = (qli_req*) node->nod_arg[e_mod_request]; qli_rlb* rlb = CHECK_RLB(request->req_blr); if (node->nod_arg[e_mod_send]) gen_send_receive((qli_msg*) node->nod_arg[e_mod_send], blr_receive); qli_nod** ptr = &node->nod_arg[e_mod_count]; for (const qli_nod* const* const end = ptr + node->nod_count; ptr < end; ptr++) { qli_ctx* context = (qli_ctx*) *ptr; STUFF(blr_modify); STUFF(context->ctx_source->ctx_context); STUFF(context->ctx_context); } STUFF(blr_begin); gen_statement(node->nod_arg[e_mod_statement], request); STUFF(blr_end); }
static void gen_if( qli_nod* node, qli_req* request) { /************************************** * * g e n _ i f * ************************************** * * Functional description * Generate code for an IF statement. Depending * on the environment, this may be either a QLI * context IF or a database context IF. * **************************************/ // If the statement is local to QLI, force the sub- statements/expressions to be local also. // If not local, generate BLR. if (node->nod_flags & NOD_local) { gen_expression(node->nod_arg[e_if_boolean], 0); gen_statement(node->nod_arg[e_if_true], request); if (node->nod_arg[e_if_false]) gen_statement(node->nod_arg[e_if_false], request); } else { // probably the var is irrelevant, but not the function call, // as it makes sure there's enough room. qli_rlb* rlb = CHECK_RLB(request->req_blr); STUFF(blr_if); gen_expression(node->nod_arg[e_if_boolean], request); STUFF(blr_begin); gen_statement(node->nod_arg[e_if_true], request); STUFF(blr_end); if (node->nod_arg[e_if_false]) { STUFF(blr_begin); gen_statement(node->nod_arg[e_if_false], request); STUFF(blr_end); } else STUFF(blr_end); } }
static void gen_functions(ArrayList *statements) { int i; for (i = 0; i < statements->length; i++) { ClmStmtNode *node = statements->data[i]; if (node->type == STMT_TYPE_FUNC_DEC) { gen_statement(node); } } }
static void gen_store( qli_nod* node, qli_req* request) { /************************************** * * g e n _ s t o r e * ************************************** * * Functional description * Generate code for STORE statement. * **************************************/ // If there is a request associated with the statement, prepare to // generate BLR. Otherwise assume that a request is alrealdy initialized. if (node->nod_arg[e_sto_request]) { request = (qli_req*) node->nod_arg[e_sto_request]; gen_request(request); } qli_rlb* rlb = CHECK_RLB(request->req_blr); // If there is a message to be sent, build a receive for it if (node->nod_arg[e_sto_send]) gen_send_receive((qli_msg*) node->nod_arg[e_sto_send], blr_receive); // Generate the STORE statement proper. STUFF(blr_store); qli_ctx* context = (qli_ctx*) node->nod_arg[e_sto_context]; qli_rel* relation = context->ctx_relation; STUFF(blr_rid); STUFF_WORD(relation->rel_id); STUFF(context->ctx_context); // Build the body of the loop. STUFF(blr_begin); gen_statement(node->nod_arg[e_sto_statement], request); STUFF(blr_end); // If this is our request, compile it. if (node->nod_arg[e_sto_request]) gen_compile(request); }
qli_nod* GEN_generate( qli_nod* node) { /************************************** * * G E N _ g e n e r a t e * ************************************** * * Functional description * Generate and compile BLR. * **************************************/ gen_statement(node, 0); return node; }
void gen_statement(tree_t *t) { int local_if_label; int local_while_label; int local_for_label; int num_args; if (t->type == ARRAY || t->right->type == ARRAY || t->left->type == ARRAY) { yyerror("Array access not supported"); } switch(t->type) { case ASSIGNOP: // Generate code for expression gen_label(t->right, 1); gen_expression(t->right); fprintf(yyout, "\tmovl\t%%ebx, %%eax\n"); // If this is actually a return statement, then return with correct value in %eax if(!strcmp(t->left->attribute.variable->name, top_scope->curr->name)) fprintf(yyout, "\tjmp\tsubprog%send\n", top_scope->curr->name); else { // Generate code for assignment gen_assignment(t->left); } break; case IF: local_if_label = if_label++; //Generate code for expression gen_label(t->left, 1); gen_expression(t->left); //Compare and jump accordingly fprintf(yyout, "\tcmpl\t$1, %%ebx\n\tjge\tiftrue%d\n", local_if_label); //Generate code for else first if (t->right->right != NULL) { gen_statement(t->right->right); fprintf(yyout, "\tjmp\tifend%d\n", local_if_label); } //Generate code for true section fprintf(yyout, "iftrue%d:\n", local_if_label); gen_statement(t->right->left); fprintf(yyout, "ifend%d:\n", local_if_label); break; case WHILE: local_while_label = while_label++; //Plant label for beginning of loop fprintf(yyout, "beginwhile%d:\n", local_while_label); //Generate code for expression gen_label(t->left, 1); gen_expression(t->left); //Compare and jump to end if needed fprintf(yyout, "\tcmpl\t$0, %%ebx\n\tje\tendwhile%d\n", local_while_label); //Generate code for statements gen_statement(t->right); fprintf(yyout, "\tjmp\tbeginwhile%d\n", local_while_label); fprintf(yyout, "endwhile%d:\n", local_while_label); break; case PROCEDURE: if (!strcmp(t->left->attribute.variable->name, "read")) gen_read(t->right); else if (!strcmp(t->left->attribute.variable->name, "write")) gen_write(t->right); else if (t->right != NULL) { // push arguments on the stack num_args = gen_expression_list(t->right); fprintf(yyout, "\tcall\tsubprog%s\n", t->left->attribute.variable->name); // move the top of the stack below args fprintf(yyout, "\taddl\t$%d, %%esp\n", 4*num_args); } else { fprintf(yyout, "\tcall\tsubprog%s\n", t->left->attribute.variable->name); } break; case COMMA: // Generate left and right statements if (t->left->type == ARRAY || t->right->type == ARRAY) yyerror("Array access not supported"); else { gen_statement(t->left); gen_statement(t->right); } break; case FOR: local_for_label = for_label++; // Generate assignment gen_statement(t->left->left); //Plant label for beginning fprintf(yyout, "forloop%d:\n", local_for_label); // Generate expression for TO value gen_label(t->left->right, 1); gen_expression(t->left->right); //Compare and jump to end if needed if (t->left->left->left->attribute.variable->local_or_parameter == LOCAL) fprintf(yyout, "\tcmpl\t-%i(%%ebp), %%ebx\n\tjl\tforend%d\n", t->left->left->left->attribute.variable->offset, local_for_label); else fprintf(yyout, "\tcmpl\t-%i(%%ebp), %%ebx\n\tjl\tforend%d\n", t->left->left->left->attribute.variable->offset, local_for_label); //Generate code for statements gen_statement(t->right); //Increment, jump to top then plant end label fprintf(yyout, "\tincl\t-%i(%%ebp)\n\tjmp\tforloop%d\nforend%d:\n", t->left->left->left->attribute.variable->offset, local_for_label, local_for_label); break; default: fprintf(stderr, "TYPE: %d\n", t->type); yywarn("Statement not supported"); break; } }
static void gen_statement( qli_nod* node, qli_req* request) { /************************************** * * g e n _ s t a t e m e n t * ************************************** * * Functional description * Generate BLR for statement. * **************************************/ if (request) CHECK_RLB(request->req_blr); switch (node->nod_type) { case nod_abort: if (node->nod_count) gen_expression(node->nod_arg[0], 0); return; case nod_assign: gen_assignment(node, request); return; case nod_commit_retaining: return; case nod_erase: gen_erase(node, request); return; case nod_for: case nod_report_loop: gen_for(node, request); return; case nod_list: { qli_nod** ptr = node->nod_arg; for (const qli_nod* const* const end = ptr + node->nod_count; ptr < end; ++ptr) { gen_statement(*ptr, request); } return; } case nod_modify: gen_modify(node); //, request); return; case nod_output: gen_statement(node->nod_arg[e_out_statement], request); return; case nod_print: gen_print_list(node->nod_arg[e_prt_list], request); return; case nod_repeat: gen_statement(node->nod_arg[e_rpt_statement], request); return; case nod_report: gen_report(node, request); return; case nod_store: gen_store(node, request); return; case nod_if: gen_if(node, request); return; default: ERRQ_bugcheck(354); // Msg354 gen_statement: not yet implemented } }
static void gen_for( qli_nod* node, qli_req* request) { /************************************** * * g e n _ f o r * ************************************** * * Functional description * Generate BLR for a FOR loop, included synchronization messages. * **************************************/ // If there is a request associated with the statement, prepare to // generate BLR. Otherwise assume that a request is alrealdy initialized. if (node->nod_arg[e_for_request]) { request = (qli_req*) node->nod_arg[e_for_request]; gen_request(request); } qli_rlb* rlb = CHECK_RLB(request->req_blr); // If the statement requires an end of file marker, build a BEGIN/END around // the whole statement. const qli_msg* message = (qli_msg*) node->nod_arg[e_for_receive]; if (message) STUFF(blr_begin); // If there is a message to be sent, build a receive for it if (node->nod_arg[e_for_send]) gen_send_receive((qli_msg*) node->nod_arg[e_for_send], blr_receive); // Generate the FOR loop proper. STUFF(blr_for); gen_rse(node->nod_arg[e_for_rse], request); STUFF(blr_begin); // If data is to be received (included EOF), build a send const qli_par* eof = 0; dsc desc; USHORT value; if (message) { gen_send_receive(message, blr_send); STUFF(blr_begin); // Build assigments for all values referenced. for (const qli_par* parameter = message->msg_parameters; parameter; parameter = parameter->par_next) { if (parameter->par_value) { STUFF(blr_assignment); gen_expression(parameter->par_value, request); gen_parameter(parameter, request); } } // Next, make a FALSE for the end of file parameter eof = (qli_par*) node->nod_arg[e_for_eof]; desc.dsc_dtype = dtype_short; desc.dsc_length = sizeof(SSHORT); desc.dsc_scale = 0; desc.dsc_sub_type = 0; desc.dsc_address = (UCHAR*) &value; QLI_validate_desc(desc); STUFF(blr_assignment); value = FALSE; gen_literal(&desc, request); gen_parameter(eof, request); STUFF(blr_end); } // Build the body of the loop. const qli_msg* continuation = request->req_continue; if (continuation) { STUFF(blr_label); const USHORT label = request->req_label++; STUFF(label); STUFF(blr_loop); STUFF(blr_select); gen_send_receive(continuation, blr_receive); STUFF(blr_leave); STUFF(label); } qli_nod* sub = node->nod_arg[e_for_statement]; gen_statement(sub, request); STUFF(blr_end); if (continuation) STUFF(blr_end); // Finish off by building a SEND to indicate end of file if (message) { gen_send_receive(message, blr_send); STUFF(blr_assignment); value = TRUE; gen_literal(&desc, request); gen_parameter(eof, request); STUFF(blr_end); } // If this is our request, compile it. if (node->nod_arg[e_for_request]) gen_compile(request); }