static void gen_assignment( qli_nod* node, qli_req* request) { /************************************** * * g e n _ a s s i g n m e n t * ************************************** * * Functional description * Generate an assignment statement. * **************************************/ qli_nod* from = node->nod_arg[e_asn_from]; // Handle a local expression locally if (node->nod_flags & NOD_local) { gen_expression(from, 0); return; } // Generate a remote assignment qli_rlb* rlb = CHECK_RLB(request->req_blr); STUFF(blr_assignment); qli_nod* target = node->nod_arg[e_asn_to]; // If we are referencing a parameter of another request, compile // the request first, the make a reference. Otherwise, just compile // the expression in the context of this request const qli_nod* reference = target->nod_arg[e_fld_reference]; if (reference) { gen_expression(from, 0); gen_parameter(reference->nod_import, request); } else gen_expression(from, request); qli_nod* validation = node->nod_arg[e_asn_valid]; if (validation) gen_expression(validation, 0); gen_expression(target, request); }
static void gen_sort( qli_nod* node, qli_req* request, const UCHAR operatr) { /************************************** * * g e n _ s o r t * ************************************** * * Functional description * Generate sort or reduced clause. * **************************************/ qli_rlb* rlb = CHECK_RLB(request->req_blr); STUFF(operatr); STUFF(node->nod_count); request->req_flags |= REQ_project; qli_nod** ptr = node->nod_arg; for (qli_nod** const end = ptr + node->nod_count * 2; ptr < end; ptr += 2) { if (operatr == blr_sort) STUFF(ptr[1] ? blr_descending : blr_ascending); gen_expression(ptr[0], request); } request->req_flags &= ~REQ_project; }
static void gen_map(qli_map* map, qli_req* request) { /************************************** * * g e n _ m a p * ************************************** * * Functional description * Generate a value map for a record selection expression. * **************************************/ qli_map* temp; qli_rlb* rlb = CHECK_RLB(request->req_blr); USHORT count = 0; for (temp = map; temp; temp = temp->map_next) { if (temp->map_node->nod_type != nod_function) temp->map_position = count++; } STUFF(blr_map); STUFF_WORD(count); for (temp = map; temp; temp = temp->map_next) { if (temp->map_node->nod_type != nod_function) { STUFF_WORD(temp->map_position); gen_expression(temp->map_node, request); } } }
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); } }
int gen_expression_list(tree_t *t) { if(t->type == COMMA) { return gen_expression_list(t->left) + gen_expression_list(t->right); } else { gen_label(t, 1); gen_expression(t); fprintf(yyout, "\tpushl\t%s\n", stack_top(registers)); return 1; } }
static void gen_field( qli_nod* node, qli_req* request) { /************************************** * * g e n _ f i e l d * ************************************** * * Functional description * Compile BLR to handle a field reference. Things varying * substantially depend on whether the field reference spans * requests or not. * **************************************/ // If there isn't a request specified, this is a reference. if (!request) return; qli_rlb* rlb = CHECK_RLB(request->req_blr); const qli_fld* field = (qli_fld*) node->nod_arg[e_fld_field]; const qli_ctx* context = (qli_ctx*) node->nod_arg[e_fld_context]; // If the field referenced is in this request, just generate a field reference. if (context->ctx_request == request) { qli_nod* args = node->nod_arg[e_fld_subs]; if (args) STUFF(blr_index); STUFF(blr_fid); STUFF(context->ctx_context); STUFF_WORD(field->fld_id); if (args) { STUFF(args->nod_count); qli_nod** ptr = args->nod_arg; for (const qli_nod* const* const end = ptr + args->nod_count; ptr < end; ++ptr) { gen_expression(*ptr, request); } } return; } // The field is in a different request. Make a parameter reference instead. gen_parameter(node->nod_export, request); }
static void gen_print_list( qli_nod* list, qli_req* request) { /************************************** * * g e n _ p r i n t _ l i s t * ************************************** * * Functional description * Generate BLR for a print list. * **************************************/ qli_nod** ptr = list->nod_arg; for (const qli_nod* const* const end = ptr + list->nod_count; ptr < end; ptr++) { qli_print_item* item = (qli_print_item*) *ptr; if (item->itm_type == item_value) gen_expression(item->itm_value, request); } }
static void gen_control_break( qli_brk* control, qli_req* request) { /************************************** * * g e n _ c o n t r o l _ b r e a k * ************************************** * * Functional description * Process report writer control breaks. * **************************************/ for (; control; control = control->brk_next) { if (control->brk_field) gen_expression((qli_nod*) control->brk_field, request); if (control->brk_line) gen_print_list((qli_nod*) control->brk_line, request); } }
void gen_expression(tree_t *t) { char *reg; // If the tree is actually a function, then take care of it here. if (t->type == FUNCTION) { // Push the arguments on the stack and call the function int num_args = gen_expression_list(t->right); fprintf(yyout, "\tcall\tsubprog%s\n", t->left->attribute.variable->name); // Move the top of the stack back down below the arguments fprintf(yyout, "\taddl\t$%d, %%esp\n", 4*num_args); // Move the answer to the top of the register stack fprintf(yyout, "\tmovl\t%%eax, %s\n", stack_top(registers)); } // Case 0: else if (t->right == NULL && t->left == NULL && t->label == 1) { if (t->type == ID ) { fprintf(yyout, "\tmovl\t%s, %s\n", find_variable(t), stack_top(registers)); } else if (t->type == INUM) { fprintf(yyout, "\tmovl\t$%i, %s\n", t->attribute.ival, stack_top(registers)); } else { yywarn("Type not supported"); } } else { // Case 1: if (t->right->label == 0) { // Go to left gen_expression(t->left); if (t->right->type == ID) { gen_op(t, find_variable(t->right), stack_top(registers)); } else if (t->right->type == INUM) { sprintf(buff1, "$%i", t->right->attribute.ival); gen_op(t, buff1, stack_top(registers)); } else { yywarn("Type not supported"); } } // Case 2: else if (t->left->label >= 1 && t->right->label > t->left->label && t->left->label < NUM_REG) { stack_swap(registers); gen_expression(t->right); reg = pop(registers); gen_expression(t->left); gen_op(t, reg, stack_top(registers)); push(registers, reg); stack_swap(registers); } // Case 3: else if (t->right->label >= 1 && t->left->label >= t->right->label && t->right->label < NUM_REG) { gen_expression(t->left); reg = pop(registers); gen_expression(t->right); gen_op(t, stack_top(registers), reg); push(registers, reg); } // Case 4: else { yywarn("Temporaries not yet implemented"); } } }
static void gen_expression(qli_nod* node, qli_req* request) { /************************************** * * g e n _ e x p r e s s i o n * ************************************** * * Functional description * Generate the BLR for a boolean or value expression. * **************************************/ USHORT operatr = 0; qli_rlb* rlb = 0; if (node->nod_flags & NOD_local) { request = NULL; //return; } else if (request) rlb = CHECK_RLB(request->req_blr); switch (node->nod_type) { case nod_any: gen_any(node, request); return; case nod_unique: if (request) { STUFF(blr_unique); gen_rse(node->nod_arg[e_any_rse], request); } return; case nod_constant: if (request) gen_literal(&node->nod_desc, request); return; case nod_field: gen_field(node, request); return; case nod_format: gen_expression(node->nod_arg[e_fmt_value], request); return; case nod_map: { qli_map* map = (qli_map*) node->nod_arg[e_map_map]; const qli_ctx* context = (qli_ctx*) node->nod_arg[e_map_context]; if (context->ctx_request != request && map->map_node->nod_type == nod_field) { gen_field(map->map_node, request); return; } STUFF(blr_fid); STUFF(context->ctx_context); STUFF_WORD(map->map_position); return; } case nod_eql: operatr = blr_eql; break; case nod_neq: operatr = blr_neq; break; case nod_gtr: operatr = blr_gtr; break; case nod_geq: operatr = blr_geq; break; case nod_leq: operatr = blr_leq; break; case nod_lss: operatr = blr_lss; break; case nod_containing: operatr = blr_containing; break; case nod_matches: operatr = blr_matching; break; case nod_sleuth: operatr = blr_matching2; break; case nod_like: operatr = (node->nod_count == 2) ? blr_like : blr_ansi_like; break; case nod_starts: operatr = blr_starting; break; case nod_missing: operatr = blr_missing; break; case nod_between: operatr = blr_between; break; case nod_and: operatr = blr_and; break; case nod_or: operatr = blr_or; break; case nod_not: operatr = blr_not; break; case nod_add: operatr = blr_add; break; case nod_subtract: operatr = blr_subtract; break; case nod_multiply: operatr = blr_multiply; break; case nod_divide: operatr = blr_divide; break; case nod_negate: operatr = blr_negate; break; case nod_concatenate: operatr = blr_concatenate; break; case nod_substr: operatr = blr_substring; break; case nod_function: gen_function(node, request); return; case nod_agg_average: case nod_agg_count: case nod_agg_max: case nod_agg_min: case nod_agg_total: case nod_average: case nod_count: case nod_max: case nod_min: case nod_total: case nod_from: gen_statistical(node, request); return; case nod_rpt_average: case nod_rpt_count: case nod_rpt_max: case nod_rpt_min: case nod_rpt_total: case nod_running_total: case nod_running_count: if (node->nod_arg[e_stt_value]) gen_expression(node->nod_arg[e_stt_value], request); if (node->nod_export) gen_parameter(node->nod_export, request); request = NULL; break; case nod_prompt: case nod_variable: if (node->nod_export) gen_parameter(node->nod_export, request); return; case nod_edit_blob: case nod_reference: return; case nod_null: operatr = blr_null; break; case nod_user_name: operatr = blr_user_name; break; case nod_upcase: operatr = blr_upcase; break; case nod_lowcase: operatr = blr_lowcase; break; default: if (request && node->nod_export) { gen_parameter(node->nod_export, request); return; } ERRQ_bugcheck(353); // Msg353 gen_expression: not understood } if (request) { rlb = CHECK_RLB(request->req_blr); STUFF(operatr); } qli_nod** ptr = node->nod_arg; for (qli_nod** const end = ptr + node->nod_count; ptr < end; ptr++) gen_expression(*ptr, request); if (!node->nod_desc.dsc_address && node->nod_desc.dsc_length) CMP_alloc_temp(node); }
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); }
void gen_statements(char* method_name, is_node* node, prog_env* prog) { char* expr; char* type; is_node* aux; int glob; int if_else_c; while(node != NULL) { switch (node->type) { case VarDecl: aux = node->child->next; while(aux != NULL) { printf("\t%%%s = alloca %s\n", aux->id, gen_code_type(gen_type[node->child->type])); aux = aux->next; } break; case CompoundStat: break; case IfElse: expr = gen_expression(method_name, node->child, prog); if_else_c = 0; printf("%%if_%d = icmp eq i1 1 , %s\n", if_else_c, expr); printf("br i1 %%if_%d, label %%then_%d, label %%else_%d \n", if_else_c, if_else_c, if_else_c); // then else true false ?? /* %ifcond = icmp eq i32 %v1, %v2 br i1 %ifcond , label %then , label %else then : %calltmp = add i32 %v1, %v2 br label %ifcont else : %calltmp1 = mul i32 %v1, %v2 br label %ifcont ifcont : %iftmp = phi i32 [ %calltmp , %then ] , [ %calltmp1 , %else ] ret i32 %iftmp */ /* contaIfElse++; int tmp = contaIfElse; printf("%%if%d = icmp eq i1 1 , %s\n",tmp,GeraExp(stm->filho,semanticTree,methodName)); printf("br i1 %%if%d, label %%true%d, label %%false%d \n",tmp,tmp,tmp); printf("true%d:\n",tmp); if(stm->filho->next->nodeType!=Null){ GeraStatement(stm->filho->next,semanticTree,methodName); } printf("br label %%count%d\n",tmp); printf("false%d:\n",tmp); if(stm->filho->next->next->nodeType!=Null){ GeraStatement(stm->filho->next->next,semanticTree,methodName); printf("br label %%count%d\n",tmp); } else{ printf("br label %%count%d\n",tmp); } printf("count%d:\n",tmp ); */ break; case Print: // verificar tipo if(node->child->type == Id) type = get_type(node->child->id, prog, method_name); else type = gen_code_type(gen_type[node->child->type]); if(strcmp(type, "i32") == 0) // inteiro { expr = gen_expression(method_name, node->child, prog); counter++; printf("\t%%%d = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([4 x i8]* @str, i32 0, i32 0), i32 %s)\n", counter, expr); } else // boolean { expr = gen_expression(method_name, node->child, prog); if_c++; // comparar o boolean com 1 printf("\t%%ifcond_%d = icmp eq i1 1 , %s\n", if_c, expr); // se true vai para then, caso contrario vai para else printf("\tbr i1 %%ifcond_%d, label %%then_%d, label %%else_%d\n", if_c, if_c, if_c); // se true, imprimir true printf("\tthen_%d:\n", if_c); counter++; printf("\t%%%d = load i8** @.true\n", counter); printf("\t%%%d = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([4 x i8]* @.str2, i32 0, i32 0), i8* %%%d)\n", counter + 1, counter); printf("\tbr label %%ifcount_%d\n", if_c); counter++; // se false, imprimir false printf("\telse_%d:\n", if_c); printf("\t%%%d = load i8** @.false\n", ++counter); printf("\t%%%d = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([4 x i8]* @.str2, i32 0, i32 0), i8* %%%d)\n", counter + 1, counter); printf("\tbr label %%ifcount_%d\n", if_c); counter++; printf("\tifcount_%d:\n", if_c); } break; case Return: break; case Store: glob = verifyGlobal(node->child->id, prog, method_name); type = get_type(node->child->id, prog, method_name); expr = gen_expression(method_name, node->child->next, prog); if (!glob) // global printf("\tstore %s %s, %s* %%%s\n", type, expr, type, node->child->id); else // local printf("\tstore %s %s, %s* @%s\n", type, expr, type, node->child->id); break; case StoreArray: break; case While: break; default: break; } node = node->next; } }
static void gen_rse( qli_nod* node, qli_req* request) { /************************************** * * g e n _ r s e * ************************************** * * Functional description * Generate a record selection expression. * **************************************/ qli_rlb* rlb = CHECK_RLB(request->req_blr); if ((nod_t) (IPTR) node->nod_arg[e_rse_join_type] == nod_nothing) STUFF(blr_rse); else STUFF(blr_rs_stream); STUFF(node->nod_count); // Check for aggregate case qli_nod* list; qli_ctx* context = (qli_ctx*) node->nod_arg[e_rse_count]; if (context->ctx_sub_rse) { STUFF(blr_aggregate); STUFF(context->ctx_context); gen_rse(context->ctx_sub_rse, request); STUFF(blr_group_by); if (list = node->nod_arg[e_rse_group_by]) { request->req_flags |= REQ_group_by; STUFF(list->nod_count); qli_nod** ptr = list->nod_arg; for (const qli_nod* const* const end = ptr + list->nod_count; ptr < end; ++ptr) { gen_expression(*ptr, request); } request->req_flags &= ~REQ_group_by; } else STUFF(0); gen_map(context->ctx_map, request); if (list = node->nod_arg[e_rse_having]) { STUFF(blr_boolean); gen_expression(list, request); } if (list = node->nod_arg[e_rse_sort]) gen_sort(list, request, blr_sort); STUFF(blr_end); return; } // Make relation clauses for all relations qli_nod** ptr = &node->nod_arg[e_rse_count]; for (const qli_nod* const* const end = ptr + node->nod_count; ptr < end; ++ptr) { context = (qli_ctx*) *ptr; if (context->ctx_stream) gen_rse(context->ctx_stream, request); else { const qli_rel* relation = context->ctx_relation; STUFF(blr_rid); STUFF_WORD(relation->rel_id); STUFF(context->ctx_context); } } // Handle various clauses if (list = node->nod_arg[e_rse_first]) { STUFF(blr_first); gen_expression(list, request); } if (list = node->nod_arg[e_rse_boolean]) { STUFF(blr_boolean); gen_expression(list, request); } if (list = node->nod_arg[e_rse_sort]) gen_sort(list, request, blr_sort); if (list = node->nod_arg[e_rse_reduced]) gen_sort(list, request, blr_project); const nod_t join_type = (nod_t) (IPTR) node->nod_arg[e_rse_join_type]; if (join_type != nod_nothing && join_type != nod_join_inner) { STUFF(blr_join_type); switch (join_type) { case nod_join_left: STUFF(blr_left); break; case nod_join_right: STUFF(blr_right); break; default: STUFF(blr_full); } } STUFF(blr_end); }
static void gen_function( qli_nod* node, qli_req* request) { /************************************** * * g e n _ f u n c t i o n * ************************************** * * Functional description * Generate blr for a function reference. * **************************************/ qli_req* new_request; qli_rlb* rlb; // If there is a request associated with the statement, prepare to // generate BLR. Otherwise assume that a request is already initialized. if (request && (request->req_flags & (REQ_project | REQ_group_by))) { new_request = NULL; rlb = CHECK_RLB(request->req_blr); } else if (new_request = (qli_req*) node->nod_arg[e_fun_request]) { request = new_request; gen_request(request); const qli_msg* receive = (qli_msg*) node->nod_arg[e_fun_send]; if (receive) gen_send_receive(receive, blr_receive); const qli_msg* send = (qli_msg*) node->nod_arg[e_fun_receive]; gen_send_receive(send, blr_send); rlb = CHECK_RLB(request->req_blr); STUFF(blr_assignment); } else rlb = CHECK_RLB(request->req_blr); // Generate function body STUFF(blr_function); qli_fun* function = (qli_fun*) node->nod_arg[e_fun_function]; qli_symbol* symbol = function->fun_symbol; STUFF(symbol->sym_length); for (const UCHAR* p = (UCHAR*) symbol->sym_string; *p;) STUFF(*p++); // Generate function arguments qli_nod* args = node->nod_arg[e_fun_args]; STUFF(args->nod_count); qli_nod** ptr = args->nod_arg; for (const qli_nod* const* const end = ptr + args->nod_count; ptr < end; ptr++) gen_expression(*ptr, request); if (new_request) { gen_parameter(node->nod_import, request); gen_compile(request); } }
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 } }
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_statistical( qli_nod* node, qli_req* request) { /************************************** * * g e n _ s t a t i s t i c a l * ************************************** * * Functional description * Generate the BLR for a statistical expresionn. * **************************************/ USHORT operatr; switch (node->nod_type) { case nod_average: operatr = blr_average; break; case nod_count: // count2 // operatr = node->nod_arg [e_stt_value] ? blr_count2 : blr_count; operatr = blr_count; break; case nod_max: operatr = blr_maximum; break; case nod_min: operatr = blr_minimum; break; case nod_total: operatr = blr_total; break; case nod_agg_average: operatr = blr_agg_average; break; case nod_agg_count: // count2 // operatr = node->nod_arg [e_stt_value] ? blr_agg_count2 : blr_agg_count; operatr = blr_agg_count; break; case nod_agg_max: operatr = blr_agg_max; break; case nod_agg_min: operatr = blr_agg_min; break; case nod_agg_total: operatr = blr_agg_total; break; case nod_from: operatr = node->nod_arg[e_stt_default] ? blr_via : blr_from; break; default: ERRQ_bugcheck(355); // Msg355 gen_statistical: not understood } // If there is a request associated with the statement, prepare to // generate BLR. Otherwise assume that a request is alrealdy initialized. qli_rlb* rlb; qli_req* new_request = (qli_req*) node->nod_arg[e_stt_request]; if (new_request) { request = new_request; gen_request(request); const qli_msg* receive = (qli_msg*) node->nod_arg[e_stt_send]; if (receive) gen_send_receive(receive, blr_receive); const qli_msg* send = (qli_msg*) node->nod_arg[e_stt_receive]; gen_send_receive(send, blr_send); rlb = CHECK_RLB(request->req_blr); STUFF(blr_assignment); } else rlb = CHECK_RLB(request->req_blr); STUFF(operatr); if (node->nod_arg[e_stt_rse]) gen_rse(node->nod_arg[e_stt_rse], request); // count 2 // if (node->nod_arg [e_stt_value]) if (node->nod_arg[e_stt_value] && node->nod_type != nod_agg_count) gen_expression(node->nod_arg[e_stt_value], request); if (node->nod_arg[e_stt_default]) gen_expression(node->nod_arg[e_stt_default], request); if (new_request) { gen_parameter(node->nod_import, request); gen_compile(request); } }
char* gen_expression(char* method_name, is_node* expr, prog_env* prog) { char* expr_type; char* expr_type1; int glob; char *c = (char*) malloc(sizeof(char*)); switch (expr->type) { case Call: break; case Or: break; case And: break; case Not: break; case Eq: break; case Neq: break; case Lt: break; case Gt: break; case Leq: break; case Geq: break; case Add: expr_type = gen_expression(method_name, expr->child, prog); expr_type1 = gen_expression(method_name, expr->child->next, prog); printf("\t%%%d = add i32 %s,%s\n", ++counter, expr_type, expr_type1); sprintf(c, "%%%d", counter); return c; break; case Sub: break; case Mul: break; case Div: break; case Mod: break; case Plus: break; case Minus: break; case Length: c = (char*) malloc(sizeof(char*)); counter++; printf("\t%%%d = sub i32 %%.argc, 1\n", counter); sprintf(c, "%%%d", counter); return c; break; case LoadArray: break; case NewInt: break; case NewBool: break; case ParseArgs: counter++; printf("\t%%%d = getelementptr inbounds i8** %%.argv, i64 %d\n", counter, atoi(expr->child->next->id) + 1); printf("\t%%%d = load i8** %%%d\n", counter + 1, counter); counter += 2; printf("\t%%%d = call i32 @atoi(i8* %%%d)\n", counter, counter - 1); c = (char* ) malloc(sizeof(char*)); sprintf(c, "%%%d", counter); return c; break; case IntLit: c = (char*) malloc(sizeof(char*)); int hexa; hexa = strtol(expr->id, NULL, 0); sprintf(c, "%d", hexa); return c; break; case BoolLit: if(strcmp(expr->id, "true") == 0) return "1"; else return "0"; break; case Id: glob = verifyGlobal(expr->id, prog, method_name); expr_type = get_type(expr->id, prog, method_name); // tipo do Id counter++; sprintf(c, "%%%d", counter); if(!glob) printf("\t%%%d = load %s* %%%s\n", counter, expr_type, expr->id); else printf("\t%%%d = load %s* @%s\n",counter, expr_type, expr->id); return c; break; default: break; } return "erro"; }
void GenTree::gen_value( const Value *val ) { if ( val == 0 ) { m_out->writeString( "(null)" ); return; } switch( val->type() ) { case Value::t_nil: m_out->writeString( "nil" ); break; case Value::t_unbound: m_out->writeString( "unbound" ); break; case Value::t_imm_bool: m_out->writeString( val->asBool() ? "true": "false" ); break; case Value::t_imm_integer: { String intStr; intStr.writeNumber( val->asInteger() ); m_out->writeString( intStr ); } break; case Value::t_imm_string: { String temp; val->asString()->escape( temp ); m_out->writeString( "\"" + temp + "\"" ); } break; case Value::t_lbind: { m_out->writeString( "&" + *val->asLBind() ); } break; case Value::t_imm_num: { String numStr; numStr.writeNumber( val->asInteger() ); m_out->writeString( numStr ); } break; case Value::t_range_decl: m_out->writeString( "[" ); gen_value( val->asRange()->rangeStart() ); m_out->writeString( ":" ); if ( ! val->asRange()->isOpen() ) { gen_value( val->asRange()->rangeEnd() ) ; if ( val->asRange()->rangeStep() != 0 ) { m_out->writeString( ":" ); gen_value( val->asRange()->rangeStep() ); } } m_out->writeString( "]" ); break; case Value::t_symbol: m_out->writeString( val->asSymbol()->name() ); break; case Value::t_self: m_out->writeString( "self" ); break; case Value::t_fself: m_out->writeString( "fself" ); break; case Value::t_array_decl: m_out->writeString( "Array: [ " ); gen_array( val->asArray() ); m_out->writeString( " ]" ); break; case Value::t_dict_decl: m_out->writeString( "Dict: [" ); gen_dict( val->asDict() ); m_out->writeString( " ]" ); break; case Value::t_byref: m_out->writeString( "$" ); gen_value( val->asReference() ); break; case Value::t_expression: gen_expression( val->asExpr() ); break; default: break; } }