# HG changeset patch # User Mario de Sousa # Date 1330692821 0 # Node ID 01f6664bf8c5b288de68d9ec3b2ae9d89c3399a9 # Parent 587884880be6e26cea64acd7a7ab0ffd66e18667 Continue adding support for semantic verification of JMP and RET. diff -r 587884880be6 -r 01f6664bf8c5 absyntax/absyntax.def --- a/absyntax/absyntax.def Thu Mar 01 10:28:27 2012 +0000 +++ b/absyntax/absyntax.def Fri Mar 02 12:53:41 2012 +0000 @@ -97,6 +97,12 @@ SYM_REF0(eno_param_c) */ +/* A class used to identify an entry (literal, variable, etc...) in the abstract syntax tree with an invalid data type */ +/* This is only used from stage3 onwards. Stages 1 and 2 will never create any instances of invalid_type_name_c */ +SYM_REF0(invalid_type_name_c) + + + /********************/ /* 2.1.6 - Pragmas */ /********************/ diff -r 587884880be6 -r 01f6664bf8c5 absyntax/absyntax.hh --- a/absyntax/absyntax.hh Thu Mar 01 10:28:27 2012 +0000 +++ b/absyntax/absyntax.hh Fri Mar 02 12:53:41 2012 +0000 @@ -77,8 +77,13 @@ int last_column; const char *last_file; /* filename referenced by last line/column */ long int last_order; /* relative order in which it is read by lexcial analyser */ - symbol_c * datatype; /* data type of the expression/literal/etc. Filled in stage3 by narrow_candidate_datatypes_c */ std::vector candidate_datatypes; /* All possible data types the expression/literal/etc. may take. Filled in stage3 by fill_candidate_datatypes_c class */ + /* Data type of the expression/literal/etc. Filled in stage3 by narrow_candidate_datatypes_c + * If set to NULL, it means it has not yet been evaluated. + * If it points to an object of type invalid_type_name_c, it means it is invalid. + * Otherwise, it points to an object of the apropriate data type (e.g. int_type_name_c, bool_type_name_c, ...) + */ + symbol_c *datatype; public: diff -r 587884880be6 -r 01f6664bf8c5 absyntax_utils/Makefile.am --- a/absyntax_utils/Makefile.am Thu Mar 01 10:28:27 2012 +0000 +++ b/absyntax_utils/Makefile.am Fri Mar 02 12:53:41 2012 +0000 @@ -13,6 +13,7 @@ function_param_iterator.cc \ get_function_type.cc \ get_sizeof_datatype.cc \ + search_il_label.cc \ search_base_type.cc \ search_constant_type.cc \ search_expression_type.cc \ diff -r 587884880be6 -r 01f6664bf8c5 absyntax_utils/Makefile.in --- a/absyntax_utils/Makefile.in Thu Mar 01 10:28:27 2012 +0000 +++ b/absyntax_utils/Makefile.in Fri Mar 02 12:53:41 2012 +0000 @@ -78,8 +78,8 @@ function_call_iterator.$(OBJEXT) \ function_call_param_iterator.$(OBJEXT) \ function_param_iterator.$(OBJEXT) get_function_type.$(OBJEXT) \ - get_sizeof_datatype.$(OBJEXT) search_base_type.$(OBJEXT) \ - search_constant_type.$(OBJEXT) \ + get_sizeof_datatype.$(OBJEXT) search_il_label.$(OBJEXT) \ + search_base_type.$(OBJEXT) search_constant_type.$(OBJEXT) \ search_expression_type.$(OBJEXT) \ search_fb_instance_decl.$(OBJEXT) search_fb_typedecl.$(OBJEXT) \ search_varfb_instance_type.$(OBJEXT) \ @@ -213,6 +213,7 @@ function_param_iterator.cc \ get_function_type.cc \ get_sizeof_datatype.cc \ + search_il_label.cc \ search_base_type.cc \ search_constant_type.cc \ search_expression_type.cc \ @@ -319,6 +320,7 @@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/search_expression_type.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/search_fb_instance_decl.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/search_fb_typedecl.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/search_il_label.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/search_var_instance_decl.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/search_varfb_instance_type.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/spec_init_separator.Po@am__quote@ diff -r 587884880be6 -r 01f6664bf8c5 absyntax_utils/absyntax_utils.hh --- a/absyntax_utils/absyntax_utils.hh Thu Mar 01 10:28:27 2012 +0000 +++ b/absyntax_utils/absyntax_utils.hh Fri Mar 02 12:53:41 2012 +0000 @@ -120,7 +120,7 @@ #include "add_en_eno_param_decl.hh" #include "get_sizeof_datatype.hh" #include "get_function_type.h" - +#include "search_il_label.hh" /***********************************************************************/ /***********************************************************************/ diff -r 587884880be6 -r 01f6664bf8c5 absyntax_utils/search_constant_type.cc --- a/absyntax_utils/search_constant_type.cc Thu Mar 01 10:28:27 2012 +0000 +++ b/absyntax_utils/search_constant_type.cc Fri Mar 02 12:53:41 2012 +0000 @@ -133,6 +133,12 @@ return (void *)value_type; } + + + +invalid_type_name_c search_constant_type_c::invalid_type_name; + + real_type_name_c search_constant_type_c::real_type_name; sint_type_name_c search_constant_type_c::sint_type_name; lint_type_name_c search_constant_type_c::lint_type_name; diff -r 587884880be6 -r 01f6664bf8c5 absyntax_utils/search_constant_type.hh --- a/absyntax_utils/search_constant_type.hh Thu Mar 01 10:28:27 2012 +0000 +++ b/absyntax_utils/search_constant_type.hh Fri Mar 02 12:53:41 2012 +0000 @@ -30,6 +30,14 @@ * */ +/* NOTE: The use of this visitor class is now deprecated. + * The new version of stage3 data type checking adds an entry to + * every relevant object in the abstract syntax tree defining + * the data type of that object. Please use that instead! + */ + + + /* Determine the data type of a specific constant or variable. * A reference to the relevant type definition is returned. * @@ -49,6 +57,10 @@ class search_constant_type_c: public search_visitor_c { public: + /* object used to identify an entry in the abstract syntax tree with an invalid data type */ + /* This is only used from stage3 onwards. Stages 1 and 2 will never create any instances of invalid_type_name_c */ + static invalid_type_name_c invalid_type_name; + /**********************/ /* B.1.3 - Data types */ /**********************/ diff -r 587884880be6 -r 01f6664bf8c5 stage3/datatype_functions.cc --- a/stage3/datatype_functions.cc Thu Mar 01 10:28:27 2012 +0000 +++ b/stage3/datatype_functions.cc Fri Mar 02 12:53:41 2012 +0000 @@ -228,6 +228,20 @@ +/* intersect the candidate_datatype lists of all prev_il_intructions, and set the local candidate_datatype list to the result! */ +void intersect_prev_candidate_datatype_lists(il_instruction_c *symbol) { + if (symbol->prev_il_instruction.empty()) + return; + + copy_candidate_datatype_list(symbol->prev_il_instruction[0] /*from*/, symbol /*to*/); + for (unsigned int i = 1; i < symbol->prev_il_instruction.size(); i++) { + intersect_candidate_datatype_list(symbol /*origin, dest.*/, symbol->prev_il_instruction[i] /*with*/); + } +} + + + + /* A helper function... */ bool is_ANY_ELEMENTARY_type(symbol_c *type_symbol) { if (type_symbol == NULL) {return false;} @@ -544,16 +558,30 @@ -bool is_type_equal(symbol_c *first_type, symbol_c *second_type) -{ - if (first_type == NULL || second_type == NULL) { - return false; - } - if (is_ANY_ELEMENTARY_type(first_type)) { - if (typeid(*first_type) == typeid(*second_type)) - return true; - } else /* ANY_DERIVED */ - return (first_type == second_type); - - return false; -} +bool is_type_equal(symbol_c *first_type, symbol_c *second_type) { + if ((NULL == first_type) || (NULL == second_type)) + return false; + if (typeid(* first_type) == typeid(invalid_type_name_c)) + return false; + if (typeid(*second_type) == typeid(invalid_type_name_c)) + return false; + + if (is_ANY_ELEMENTARY_type(first_type)) { + if (typeid(*first_type) == typeid(*second_type)) + return true; + } else /* ANY_DERIVED */ + return (first_type == second_type); + + return false; +} + + + +bool is_type_valid(symbol_c *type) { + if (NULL == type) + return false; + if (typeid(*type) == typeid(invalid_type_name_c)) + return false; + + return true; +} diff -r 587884880be6 -r 01f6664bf8c5 stage3/datatype_functions.hh --- a/stage3/datatype_functions.hh Thu Mar 01 10:28:27 2012 +0000 +++ b/stage3/datatype_functions.hh Fri Mar 02 12:53:41 2012 +0000 @@ -154,6 +154,10 @@ */ void intersect_candidate_datatype_list(symbol_c *list1 /*origin, dest.*/, symbol_c *list2 /*with*/); +/* intersect the candidate_datatype lists of all prev_il_intructions, and set the local candidate_datatype list to the result! */ +void intersect_prev_candidate_datatype_lists(il_instruction_c *symbol); + + /* A helper function... */ bool is_ANY_ELEMENTARY_type (symbol_c *type_symbol); @@ -206,8 +210,9 @@ bool is_type_equal(symbol_c *first_type, symbol_c *second_type); - -// typedef bool (*helper_function_t) (symbol_c *type_symbol); /* a pointer to a function! */ +bool is_type_valid(symbol_c *type); + + #endif /* _HELPER_FUNCTIONS_HH_ */ diff -r 587884880be6 -r 01f6664bf8c5 stage3/fill_candidate_datatypes.cc --- a/stage3/fill_candidate_datatypes.cc Thu Mar 01 10:28:27 2012 +0000 +++ b/stage3/fill_candidate_datatypes.cc Fri Mar 02 12:53:41 2012 +0000 @@ -565,7 +565,9 @@ /************************/ void *fill_candidate_datatypes_c::visit(duration_c *symbol) { /* TODO: check whether the literal follows the rules specified in section '2.2.3.1 Duration' of the standard! */ - symbol->candidate_datatypes.push_back(symbol->type_name); + + symbol->candidate_datatypes.push_back(&search_constant_type_c::time_type_name); +// symbol->candidate_datatypes.push_back(symbol->type_name); if (debug) std::cout << "TIME_LITERAL [" << symbol->candidate_datatypes.size() << "]\n"; return NULL; } @@ -800,6 +802,7 @@ // void *visit(instruction_list_c *symbol); + /* | label ':' [il_incomplete_instruction] eol_list */ // SYM_REF2(il_instruction_c, label, il_instruction) // void *visit(instruction_list_c *symbol); @@ -808,16 +811,14 @@ /* This empty/null il_instruction does not change the value of the current/default IL variable. * So it inherits the candidate_datatypes from it's previous IL instructions! */ - if (!symbol->prev_il_instruction.empty()) { - copy_candidate_datatype_list(symbol->prev_il_instruction[0] /*from*/, symbol /*to*/); - for (unsigned int i = 1; i < symbol->prev_il_instruction.size(); i++) { - intersect_candidate_datatype_list(symbol /*origin, dest.*/, symbol->prev_il_instruction[i] /*with*/); - } - } + intersect_prev_candidate_datatype_lists(symbol); } else { - if (symbol->prev_il_instruction.size() > 1) ERROR; /* This assertion is only valid for now. Remove it once flow_control_analysis_c is complete */ +// if (symbol->prev_il_instruction.size() > 1) ERROR; /* This assertion is only valid for now. Remove it once flow_control_analysis_c is complete */ + il_instruction_c fake_prev_il_instruction = *symbol; + intersect_prev_candidate_datatype_lists(&fake_prev_il_instruction); + if (symbol->prev_il_instruction.size() == 0) prev_il_instruction = NULL; - else prev_il_instruction = symbol->prev_il_instruction[0]; + else prev_il_instruction = &fake_prev_il_instruction; symbol->il_instruction->accept(*this); prev_il_instruction = NULL; @@ -855,7 +856,6 @@ * * However, if no further paramters are given, then il_operand_list will be NULL, and we will * need to create a new object to hold the pointer to prev_il_instruction. - * This change will also be undone later in print_datatypes_error_c. */ if (NULL == symbol->il_operand_list) symbol->il_operand_list = new il_operand_list_c; if (NULL == symbol->il_operand_list) ERROR; @@ -1022,7 +1022,7 @@ // SYM_REF1(il_simple_instruction_c, il_simple_instruction, symbol_c *prev_il_instruction;) void *fill_candidate_datatypes_c::visit(il_simple_instruction_c *symbol) { - if (symbol->prev_il_instruction.size() > 1) ERROR; /* This assertion is only valid for now. Remove it once flow_control_analysis_c is complete */ + if (symbol->prev_il_instruction.size() > 1) ERROR; /* There should be no labeled insructions inside an IL expression! */ if (symbol->prev_il_instruction.size() == 0) prev_il_instruction = NULL; else prev_il_instruction = symbol->prev_il_instruction[0]; symbol->il_simple_instruction->accept(*this); diff -r 587884880be6 -r 01f6664bf8c5 stage3/flow_control_analysis.cc --- a/stage3/flow_control_analysis.cc Thu Mar 01 10:28:27 2012 +0000 +++ b/stage3/flow_control_analysis.cc Fri Mar 02 12:53:41 2012 +0000 @@ -113,6 +113,8 @@ static int debug = 0; flow_control_analysis_c::flow_control_analysis_c(symbol_c *ignore) { + prev_il_instruction = NULL; + curr_il_instruction = NULL; } flow_control_analysis_c::~flow_control_analysis_c(void) { @@ -127,11 +129,11 @@ /* B 1.5.1 Functions */ /*********************/ void *flow_control_analysis_c::visit(function_declaration_c *symbol) { - search_varfb_instance_type = new search_varfb_instance_type_c(symbol); + search_il_label = new search_il_label_c(symbol); if (debug) printf("Doing flow control analysis in body of function %s\n", ((token_c *)(symbol->derived_function_name))->value); symbol->function_body->accept(*this); - delete search_varfb_instance_type; - search_varfb_instance_type = NULL; + delete search_il_label; + search_il_label = NULL; return NULL; } @@ -139,11 +141,11 @@ /* B 1.5.2 Function blocks */ /***************************/ void *flow_control_analysis_c::visit(function_block_declaration_c *symbol) { - search_varfb_instance_type = new search_varfb_instance_type_c(symbol); + search_il_label = new search_il_label_c(symbol); if (debug) printf("Doing flow control analysis in body of FB %s\n", ((token_c *)(symbol->fblock_name))->value); symbol->fblock_body->accept(*this); - delete search_varfb_instance_type; - search_varfb_instance_type = NULL; + delete search_il_label; + search_il_label = NULL; return NULL; } @@ -151,11 +153,11 @@ /* B 1.5.3 Programs */ /********************/ void *flow_control_analysis_c::visit(program_declaration_c *symbol) { - search_varfb_instance_type = new search_varfb_instance_type_c(symbol); + search_il_label = new search_il_label_c(symbol); if (debug) printf("Doing flow control analysis in body of program %s\n", ((token_c *)(symbol->program_type_name))->value); symbol->function_block_body->accept(*this); - delete search_varfb_instance_type; - search_varfb_instance_type = NULL; + delete search_il_label; + search_il_label = NULL; return NULL; } @@ -181,7 +183,9 @@ for(int i = 0; i < symbol->n; i++) { prev_il_instruction = NULL; if (i > 0) prev_il_instruction = symbol->elements[i-1]; - symbol->elements[i]->accept(*this); + curr_il_instruction = symbol->elements[i]; + curr_il_instruction->accept(*this); + curr_il_instruction = NULL; } return NULL; } @@ -190,34 +194,28 @@ // SYM_REF2(il_instruction_c, label, il_instruction) // void *visit(instruction_list_c *symbol); void *flow_control_analysis_c::visit(il_instruction_c *symbol) { - symbol->prev_il_instruction.push_back(prev_il_instruction); - /* TODO: handle labels correctly! - * - * Don't forget to handle multiple consecutive lables too! - * label2: - * label3: - * label4: - * LD I - */ - /* NOTE: the following recursive call will mess up the value in the - * this->prev_il_instruction variable, so be sure not to use it - * after the return of symbol->il_instruction->accept(*this); - */ - /* check if it is an il_expression_c, and if so, handle it correctly */ + if (NULL != prev_il_instruction) + symbol->prev_il_instruction.push_back(prev_il_instruction); + + /* check if it is an il_expression_c, or a JMP[C[N]] and if so, handle it correctly */ if (NULL != symbol->il_instruction) symbol->il_instruction->accept(*this); return NULL; } -#if 0 + +/* | il_simple_operator [il_operand] */ +// SYM_REF2(il_simple_operation_c, il_simple_operator, il_operand) +// void *flow_control_analysis_c::visit(il_simple_operation_c *symbol) + + + /* | function_name [il_operand_list] */ /* NOTE: The parameters 'called_function_declaration' and 'extensible_param_count' are used to pass data between the stage 3 and stage 4. */ // SYM_REF2(il_function_call_c, function_name, il_operand_list, symbol_c *called_function_declaration; int extensible_param_count;) -void *flow_control_analysis_c::visit(il_function_call_c *symbol) { - return NULL; -} -#endif +// void *flow_control_analysis_c::visit(il_function_call_c *symbol) + /* | il_expr_operator '(' [il_operand] eol_list [simple_instr_list] ')' */ // SYM_REF3(il_expression_c, il_expr_operator, il_operand, simple_instr_list); @@ -226,13 +224,28 @@ /* nothing to do... */ return NULL; + symbol_c *save_prev_il_instruction = prev_il_instruction; prev_il_instruction = symbol->il_operand; symbol->simple_instr_list->accept(*this); - return NULL; -} - - -#if 0 + prev_il_instruction = save_prev_il_instruction; + return NULL; +} + + +/* il_jump_operator label */ +// SYM_REF2(il_jump_operation_c, il_jump_operator, label) +void *flow_control_analysis_c::visit(il_jump_operation_c *symbol) { + /* search for the il_instruction_c containing the label */ + il_instruction_c *destination = search_il_label->find_label(symbol->label); + + /* TODO: for JMP and RET (unconditional) instructions, make sure the next IL instruction does not point back! */ + /* add, to that il_instruction's list of prev_il_intsructions, the curr_il_instruction */ + if (NULL != destination) + destination->prev_il_instruction.push_back(curr_il_instruction); + return NULL; +} + + /* il_call_operator prev_declared_fb_name * | il_call_operator prev_declared_fb_name '(' ')' * | il_call_operator prev_declared_fb_name '(' eol_list ')' @@ -241,18 +254,14 @@ */ /* NOTE: The parameter 'called_fb_declaration'is used to pass data between stage 3 and stage4 (although currently it is not used in stage 4 */ // SYM_REF4(il_fb_call_c, il_call_operator, fb_name, il_operand_list, il_param_list, symbol_c *called_fb_declaration) -void *flow_control_analysis_c::visit(il_fb_call_c *symbol) { - return NULL; -} +// void *flow_control_analysis_c::visit(il_fb_call_c *symbol) /* | function_name '(' eol_list [il_param_list] ')' */ /* NOTE: The parameter 'called_function_declaration' is used to pass data between the stage 3 and stage 4. */ // SYM_REF2(il_formal_funct_call_c, function_name, il_param_list, symbol_c *called_function_declaration; int extensible_param_count;) -void *flow_control_analysis_c::visit(il_formal_funct_call_c *symbol) { - return NULL; -} -#endif +// void *flow_control_analysis_c::visit(il_formal_funct_call_c *symbol) + // void *visit(il_operand_list_c *symbol); @@ -268,7 +277,8 @@ // SYM_REF1(il_simple_instruction_c, il_simple_instruction, symbol_c *prev_il_instruction;) void *flow_control_analysis_c::visit(il_simple_instruction_c*symbol) { - symbol->prev_il_instruction.push_back(prev_il_instruction); + if (NULL != prev_il_instruction) + symbol->prev_il_instruction.push_back(prev_il_instruction); return NULL; } @@ -281,3 +291,54 @@ + +/*******************/ +/* B 2.2 Operators */ +/*******************/ +// void *visit( LD_operator_c *symbol); +// void *visit( LDN_operator_c *symbol); +// void *visit( ST_operator_c *symbol); +// void *visit( STN_operator_c *symbol); +// void *visit( NOT_operator_c *symbol); +// void *visit( S_operator_c *symbol); +// void *visit( R_operator_c *symbol); +// void *visit( S1_operator_c *symbol); +// void *visit( R1_operator_c *symbol); +// void *visit( CLK_operator_c *symbol); +// void *visit( CU_operator_c *symbol); +// void *visit( CD_operator_c *symbol); +// void *visit( PV_operator_c *symbol); +// void *visit( IN_operator_c *symbol); +// void *visit( PT_operator_c *symbol); +// void *visit( AND_operator_c *symbol); +// void *visit( OR_operator_c *symbol); +// void *visit( XOR_operator_c *symbol); +// void *visit( ANDN_operator_c *symbol); +// void *visit( ORN_operator_c *symbol); +// void *visit( XORN_operator_c *symbol); +// void *visit( ADD_operator_c *symbol); +// void *visit( SUB_operator_c *symbol); +// void *visit( MUL_operator_c *symbol); +// void *visit( DIV_operator_c *symbol); +// void *visit( MOD_operator_c *symbol); +// void *visit( GT_operator_c *symbol); +// void *visit( GE_operator_c *symbol); +// void *visit( EQ_operator_c *symbol); +// void *visit( LT_operator_c *symbol); +// void *visit( LE_operator_c *symbol); +// void *visit( NE_operator_c *symbol); +// void *visit( CAL_operator_c *symbol); +// void *visit( CALC_operator_c *symbol); +// void *visit(CALCN_operator_c *symbol); +// void *visit( RET_operator_c *symbol); +// void *visit( RETC_operator_c *symbol); +// void *visit(RETCN_operator_c *symbol); +// void *visit( JMP_operator_c *symbol); +// void *visit( JMPC_operator_c *symbol); +// void *visit(JMPCN_operator_c *symbol); + +/* Symbol class handled together with function call checks */ +// void *visit(il_assign_operator_c *symbol, variable_name); +/* Symbol class handled together with function call checks */ +// void *visit(il_assign_operator_c *symbol, option, variable_name); + diff -r 587884880be6 -r 01f6664bf8c5 stage3/flow_control_analysis.hh --- a/stage3/flow_control_analysis.hh Thu Mar 01 10:28:27 2012 +0000 +++ b/stage3/flow_control_analysis.hh Fri Mar 02 12:53:41 2012 +0000 @@ -48,8 +48,9 @@ class flow_control_analysis_c: public iterator_visitor_c { private: - search_varfb_instance_type_c *search_varfb_instance_type; + search_il_label_c *search_il_label; symbol_c *prev_il_instruction; + symbol_c *curr_il_instruction; public: flow_control_analysis_c(symbol_c *ignore); @@ -89,6 +90,7 @@ // void *visit(il_simple_operation_c *symbol); // void *visit(il_function_call_c *symbol); void *visit(il_expression_c *symbol); + void *visit(il_jump_operation_c *symbol); // void *visit(il_fb_call_c *symbol); // void *visit(il_formal_funct_call_c *symbol); // void *visit(il_operand_list_c *symbol); @@ -101,49 +103,48 @@ /*******************/ /* B 2.2 Operators */ /*******************/ - /* - void *visit(LD_operator_c *symbol); - void *visit(LDN_operator_c *symbol); - void *visit(ST_operator_c *symbol); - void *visit(STN_operator_c *symbol); - void *visit(NOT_operator_c *symbol); - void *visit(S_operator_c *symbol); - void *visit(R_operator_c *symbol); - void *visit(S1_operator_c *symbol); - void *visit(R1_operator_c *symbol); - void *visit(CLK_operator_c *symbol); - void *visit(CU_operator_c *symbol); - void *visit(CD_operator_c *symbol); - void *visit(PV_operator_c *symbol); - void *visit(IN_operator_c *symbol); - void *visit(PT_operator_c *symbol); - void *visit(AND_operator_c *symbol); - void *visit(OR_operator_c *symbol); - void *visit(XOR_operator_c *symbol); - void *visit(ANDN_operator_c *symbol); - void *visit(ORN_operator_c *symbol); - void *visit(XORN_operator_c *symbol); - void *visit(ADD_operator_c *symbol); - void *visit(SUB_operator_c *symbol); - void *visit(MUL_operator_c *symbol); - void *visit(DIV_operator_c *symbol); - void *visit(MOD_operator_c *symbol); - void *visit(GT_operator_c *symbol); - void *visit(GE_operator_c *symbol); - void *visit(EQ_operator_c *symbol); - void *visit(LT_operator_c *symbol); - void *visit(LE_operator_c *symbol); - void *visit(NE_operator_c *symbol); - void *visit(CAL_operator_c *symbol); - void *visit(CALC_operator_c *symbol); - void *visit(CALCN_operator_c *symbol); - void *visit(RET_operator_c *symbol); - void *visit(RETC_operator_c *symbol); - void *visit(RETCN_operator_c *symbol); - void *visit(JMP_operator_c *symbol); - void *visit(JMPC_operator_c *symbol); - void *visit(JMPCN_operator_c *symbol); - */ +// void *visit( LD_operator_c *symbol); +// void *visit( LDN_operator_c *symbol); +// void *visit( ST_operator_c *symbol); +// void *visit( STN_operator_c *symbol); +// void *visit( NOT_operator_c *symbol); +// void *visit( S_operator_c *symbol); +// void *visit( R_operator_c *symbol); +// void *visit( S1_operator_c *symbol); +// void *visit( R1_operator_c *symbol); +// void *visit( CLK_operator_c *symbol); +// void *visit( CU_operator_c *symbol); +// void *visit( CD_operator_c *symbol); +// void *visit( PV_operator_c *symbol); +// void *visit( IN_operator_c *symbol); +// void *visit( PT_operator_c *symbol); +// void *visit( AND_operator_c *symbol); +// void *visit( OR_operator_c *symbol); +// void *visit( XOR_operator_c *symbol); +// void *visit( ANDN_operator_c *symbol); +// void *visit( ORN_operator_c *symbol); +// void *visit( XORN_operator_c *symbol); +// void *visit( ADD_operator_c *symbol); +// void *visit( SUB_operator_c *symbol); +// void *visit( MUL_operator_c *symbol); +// void *visit( DIV_operator_c *symbol); +// void *visit( MOD_operator_c *symbol); +// void *visit( GT_operator_c *symbol); +// void *visit( GE_operator_c *symbol); +// void *visit( EQ_operator_c *symbol); +// void *visit( LT_operator_c *symbol); +// void *visit( LE_operator_c *symbol); +// void *visit( NE_operator_c *symbol); +// void *visit( CAL_operator_c *symbol); +// void *visit( CALC_operator_c *symbol); +// void *visit(CALCN_operator_c *symbol); +// void *visit( RET_operator_c *symbol); +// void *visit( RETC_operator_c *symbol); +// void *visit(RETCN_operator_c *symbol); +// void *visit( JMP_operator_c *symbol); +// void *visit( JMPC_operator_c *symbol); +// void *visit(JMPCN_operator_c *symbol); + /* Symbol class handled together with function call checks */ // void *visit(il_assign_operator_c *symbol, variable_name); /* Symbol class handled together with function call checks */ diff -r 587884880be6 -r 01f6664bf8c5 stage3/narrow_candidate_datatypes.cc --- a/stage3/narrow_candidate_datatypes.cc Thu Mar 01 10:28:27 2012 +0000 +++ b/stage3/narrow_candidate_datatypes.cc Fri Mar 02 12:53:41 2012 +0000 @@ -57,15 +57,38 @@ /* Only set the symbol's desired datatype to 'datatype' if that datatype is in the candidate_datatype list */ static void set_datatype(symbol_c *datatype, symbol_c *symbol) { - symbol->datatype = NULL; - if (search_in_candidate_datatype_list(datatype, symbol->candidate_datatypes) >= 0) - symbol->datatype = datatype; + + /* If we are trying to set to the undefined type, and the symbol's datatype has already been set to something else, + * we abort the compoiler as I don't think this should ever occur. + * However, I (Mario) am not too sure of this, so if the compiler ever aborts here, please analyse the situation + * carefully as it might be perfectly legal and something I have missed! + */ + if ((NULL == datatype) && (NULL != symbol->datatype)) ERROR; + + if ((NULL == datatype) && (NULL == symbol->datatype)) return; + + if (search_in_candidate_datatype_list(datatype, symbol->candidate_datatypes) < 0) + symbol->datatype = &(search_constant_type_c::invalid_type_name); + else { + if (NULL == symbol->datatype) + /* not yet set to anything, so we set it to the requested data type */ + symbol->datatype = datatype; + else { + /* had already been set previously to some data type. Let's check if they are the same! */ + if (!is_type_equal(symbol->datatype, datatype)) + symbol->datatype = &(search_constant_type_c::invalid_type_name); +// else + /* we leave it unchanged, as it is the same as the requested data type! */ + } + } } /* Only set the symbol's desired datatype to 'datatype' if that datatype is in the candidate_datatype list */ -static void set_datatype_in_prev_il_instruction(symbol_c *datatype, il_instruction_c *symbol) { +// static void set_datatype_in_prev_il_instructions(symbol_c *datatype, std::vector prev_il_instructions) { +static void set_datatype_in_prev_il_instructions(symbol_c *datatype, il_instruction_c *symbol) { + if (NULL == symbol) ERROR; for (unsigned int i = 0; i < symbol->prev_il_instruction.size(); i++) set_datatype(datatype, symbol->prev_il_instruction[i]); } @@ -276,7 +299,7 @@ } symbol_c *fb_decl = il_operand->datatype; - if (NULL == prev_il_instruction) { + if (0 == fake_prev_il_instruction->prev_il_instruction.size()) { /* This IL implicit FB call (e.g. CLK ton_var) is not preceded by another IL instruction * (or list of instructions) that will set the IL current/default value. * We cannot proceed verifying type compatibility of something that does not exist. @@ -286,9 +309,9 @@ if (NULL == fb_decl) { /* the il_operand is a not FB instance */ - /* so we simply pass on the required datatype to the prev_il_instruction */ - /* The invalid FB invocation will be caught by the print_datatypes_error_c by analysing NULL value in il_operand->datatype! */ - prev_il_instruction->datatype = il_instruction->datatype; + /* so we simply pass on the required datatype to the prev_il_instructions */ + /* The invalid FB invocation will be caught in the print_datatypes_error_c by analysing NULL value in il_operand->datatype! */ + set_datatype_in_prev_il_instructions(il_instruction->datatype, fake_prev_il_instruction); return NULL; } @@ -302,8 +325,15 @@ * would be changed to the IL instruction coming before the current prev_il_instruction! => things would get all messed up!) * The easiest way to work around this is to simply use a new object, and copy the relevant details to that object! */ - symbol_c param_value = *prev_il_instruction; - +printf("XX::narrow_candidate_datatypes_c::narrow_implicit_il_fb_call(): fake_prev_il_instruction->candidate_datatypes.size() = %d\n",fake_prev_il_instruction->candidate_datatypes.size()); +printf("XX::narrow_candidate_datatypes_c::narrow_implicit_il_fb_call(): fake_prev_il_instruction->candidate_datatypes[0] = %p\n",fake_prev_il_instruction->candidate_datatypes[0]); + symbol_c param_value = *fake_prev_il_instruction; /* copy the candidate_datatypes list ! */ +printf("XX::narrow_candidate_datatypes_c::narrow_implicit_il_fb_call(): param_value.candidate_datatypes.size() = %d\n",param_value.candidate_datatypes.size()); +printf("XX::narrow_candidate_datatypes_c::narrow_implicit_il_fb_call(): param_value.candidate_datatypes[0] = %p\n",param_value.candidate_datatypes[0]); +printf("00::narrow_candidate_datatypes_c::narrow_implicit_il_fb_call(): search_constant_type::time_type_name = %p\n", &search_constant_type_c::time_type_name); +printf("00::narrow_candidate_datatypes_c::narrow_implicit_il_fb_call(): search_constant_type::invalid_type_name = %p\n", &search_constant_type_c::invalid_type_name); + +printf("11::narrow_candidate_datatypes_c::narrow_implicit_il_fb_call(): param_value.datatype = %p\n", param_value.datatype); identifier_c variable_name(param_name); // SYM_REF1(il_assign_operator_c, variable_name) il_assign_operator_c il_assign_operator(&variable_name); @@ -314,6 +344,7 @@ // SYM_REF4(il_fb_call_c, il_call_operator, fb_name, il_operand_list, il_param_list, symbol_c *called_fb_declaration) CAL_operator_c CAL_operator; il_fb_call_c il_fb_call(&CAL_operator, il_operand, NULL, &il_param_list); +printf("22::narrow_candidate_datatypes_c::narrow_implicit_il_fb_call(): param_value.datatype = %p\n", param_value.datatype); /* A FB call does not return any datatype, but the IL instructions that come after this * FB call may require a specific datatype in the il current/default variable, @@ -326,6 +357,7 @@ // copy_candidate_datatype_list(il_instruction/*from*/, &il_fb_call/*to*/); il_fb_call.called_fb_declaration = called_fb_declaration; il_fb_call.accept(*this); +printf("33::narrow_candidate_datatypes_c::narrow_implicit_il_fb_call(): param_value.datatype = %p\n", param_value.datatype); /* set the required datatype of the previous IL instruction! */ /* NOTE: @@ -338,7 +370,7 @@ * This means that we have two consumers/users for the same value. * We must therefore check whether the datatype required by the IL instructions following this FB call * is the same as that required for the first parameter. If not, then we have a semantic error, - * and we set it to NULL. + * and we set it to invalid_type_name. * * However, we only do that if: * - The IL instruction that comes after this IL FB call actually asked this FB call for a specific @@ -348,9 +380,11 @@ * FB call must be left unchanged! */ if ((NULL == il_instruction->datatype) || (is_type_equal(param_value.datatype, il_instruction->datatype))) { - prev_il_instruction->datatype = param_value.datatype; +printf("44::narrow_candidate_datatypes_c::narrow_implicit_il_fb_call(): param_value.datatype = %p\n", param_value.datatype); + set_datatype_in_prev_il_instructions(param_value.datatype, fake_prev_il_instruction); } else { - prev_il_instruction->datatype = NULL; +printf("55::narrow_candidate_datatypes_c::narrow_implicit_il_fb_call(): param_value.datatype = %p\n", param_value.datatype); + set_datatype_in_prev_il_instructions(&search_constant_type_c::invalid_type_name, fake_prev_il_instruction); } return NULL; } @@ -510,14 +544,21 @@ void *narrow_candidate_datatypes_c::visit(il_instruction_c *symbol) { if (NULL == symbol->il_instruction) { /* this empty/null il_instruction cannot generate the desired datatype. We pass on the request to the previous il instruction. */ - set_datatype_in_prev_il_instruction(symbol->datatype, symbol); + set_datatype_in_prev_il_instructions(symbol->datatype, symbol); } else { + il_instruction_c tmp_prev_il_instruction(NULL, NULL); + /* the narrow algorithm will need access to the intersected candidate_datatype lists of all prev_il_instructions, as well as the + * list of the prev_il_instructions. + * Instead of creating two 'global' (within the class) variables, we create a single il_instruction_c variable (fake_prev_il_instruction), + * and shove that data into this single variable. + */ + tmp_prev_il_instruction.prev_il_instruction = symbol->prev_il_instruction; + intersect_prev_candidate_datatype_lists(&tmp_prev_il_instruction); /* Tell the il_instruction the datatype that it must generate - this was chosen by the next il_instruction (remember: we are iterating backwards!) */ - if (symbol->prev_il_instruction.size() > 1) ERROR; /* This assertion is only valid for now. Remove it once flow_control_analysis_c is complete */ - if (symbol->prev_il_instruction.size() == 0) prev_il_instruction = NULL; - else prev_il_instruction = symbol->prev_il_instruction[0]; + fake_prev_il_instruction = &tmp_prev_il_instruction; + symbol->il_instruction->datatype = symbol->datatype; symbol->il_instruction->accept(*this); - prev_il_instruction = NULL; + fake_prev_il_instruction = NULL; } return NULL; } @@ -552,12 +593,10 @@ * need to create a new object to hold the pointer to prev_il_instruction. * This change will also be undone later in print_datatypes_error_c. */ - symbol_c param_value; + symbol_c param_value = *fake_prev_il_instruction; /* copy the candidate_datatypes list */ if (NULL == symbol->il_operand_list) symbol->il_operand_list = new il_operand_list_c; if (NULL == symbol->il_operand_list) ERROR; - if (NULL != prev_il_instruction) - param_value = *prev_il_instruction; ((list_c *)symbol->il_operand_list)->insert_element(¶m_value, 0); generic_function_call_t fcall_param = { @@ -571,8 +610,7 @@ }; narrow_function_invocation(symbol, fcall_param); - if (NULL != prev_il_instruction) - prev_il_instruction->datatype = param_value.datatype; + set_datatype_in_prev_il_instructions(param_value.datatype, fake_prev_il_instruction); /* Undo the changes to the abstract syntax tree we made above... */ ((list_c *)symbol->il_operand_list)->remove_element(0); @@ -596,10 +634,10 @@ /* now give the parenthesised IL list a chance to narrow the datatypes */ /* The datatype that is must return was set by the call symbol->il_expr_operator->accept(*this) */ - symbol_c *save_prev_il_instruction = prev_il_instruction; /*this is not really necessary, but lets play it safe */ + il_instruction_c *save_fake_prev_il_instruction = fake_prev_il_instruction; /*this is not really necessary, but lets play it safe */ symbol->simple_instr_list->accept(*this); - prev_il_instruction = save_prev_il_instruction; -return NULL; + fake_prev_il_instruction = save_fake_prev_il_instruction; + return NULL; } @@ -664,12 +702,23 @@ // SYM_REF1(il_simple_instruction_c, il_simple_instruction, symbol_c *prev_il_instruction;) void *narrow_candidate_datatypes_c::visit(il_simple_instruction_c *symbol) { - if (symbol->prev_il_instruction.size() > 1) ERROR; /* This assertion is only valid for now. Remove it once flow_control_analysis_c is complete */ - if (symbol->prev_il_instruction.size() == 0) prev_il_instruction = NULL; - else prev_il_instruction = symbol->prev_il_instruction[0]; + if (symbol->prev_il_instruction.size() > 1) ERROR; /* There should be no labeled insructions inside an IL expression! */ + + il_instruction_c tmp_prev_il_instruction(NULL, NULL); + /* the narrow algorithm will need access to the intersected candidate_datatype lists of all prev_il_instructions, as well as the + * list of the prev_il_instructions. + * Instead of creating two 'global' (within the class) variables, we create a single il_instruction_c variable (fake_prev_il_instruction), + * and shove that data into this single variable. + */ + if (symbol->prev_il_instruction.size() > 0) + tmp_prev_il_instruction.candidate_datatypes = symbol->prev_il_instruction[0]->candidate_datatypes; + tmp_prev_il_instruction.prev_il_instruction = symbol->prev_il_instruction; + + /* copy the candidate_datatypes list */ + fake_prev_il_instruction = &tmp_prev_il_instruction; symbol->il_simple_instruction->datatype = symbol->datatype; symbol->il_simple_instruction->accept(*this); - prev_il_instruction = NULL; + fake_prev_il_instruction = NULL; return NULL; } @@ -702,7 +751,8 @@ * (or simple_instr_list_c), which iterates backwards. */ /* set the desired datatype of the previous il instruction */ - prev_il_instruction->datatype = symbol->datatype; + set_datatype_in_prev_il_instructions(symbol->datatype, fake_prev_il_instruction); + /* set the datatype for the operand */ il_operand->datatype = symbol->datatype; il_operand->accept(*this); @@ -739,8 +789,7 @@ il_operand->datatype = symbol->datatype; il_operand->accept(*this); /* set the desired datatype of the previous il instruction */ - prev_il_instruction->datatype = symbol->datatype; - if (debug) printf("narrow_candidate_datatypes_c::visit(ST_operator_c *symbol) returning. previous_il_instruction->datatype = %p\n", prev_il_instruction->datatype); + set_datatype_in_prev_il_instructions(symbol->datatype, fake_prev_il_instruction); return NULL; } @@ -752,7 +801,7 @@ il_operand->datatype = symbol->datatype; il_operand->accept(*this); /* set the desired datatype of the previous il instruction */ - prev_il_instruction->datatype = symbol->datatype; + set_datatype_in_prev_il_instructions(symbol->datatype, fake_prev_il_instruction); return NULL; } @@ -805,8 +854,7 @@ void *narrow_candidate_datatypes_c::visit(CAL_operator_c *symbol) { /* set the desired datatype of the previous il instruction */ /* This FB call does not change the value in the current/default IL variable, so we pass the required datatype to the previous IL instruction */ - if (NULL != prev_il_instruction) - prev_il_instruction->datatype = symbol->datatype; + set_datatype_in_prev_il_instructions(symbol->datatype, fake_prev_il_instruction); return NULL; } @@ -827,7 +875,7 @@ if ((NULL != symbol->datatype) && (!is_type(symbol->datatype, bool_type_name_c))) ERROR; /* set the required datatype of the previous IL instruction, i.e. a bool_type_name_c! */ - if (NULL != prev_il_instruction) prev_il_instruction->datatype = symbol->datatype; + set_datatype_in_prev_il_instructions(symbol->datatype, fake_prev_il_instruction); return NULL; } @@ -846,8 +894,7 @@ * However, since that class has not yet been completely finished, we do not yet check this assertion! */ // if (NULL != symbol->datatype) ERROR; - if (NULL != prev_il_instruction) - prev_il_instruction->datatype = symbol->datatype; + set_datatype_in_prev_il_instructions(symbol->datatype, fake_prev_il_instruction); return NULL; } @@ -861,8 +908,7 @@ * However, since that class has not yet been completely finished, we do not yet check this assertion! */ // if (NULL != symbol->datatype) ERROR; - if (NULL != prev_il_instruction) - prev_il_instruction->datatype = symbol->datatype; + set_datatype_in_prev_il_instructions(symbol->datatype, fake_prev_il_instruction); return NULL; } diff -r 587884880be6 -r 01f6664bf8c5 stage3/narrow_candidate_datatypes.hh --- a/stage3/narrow_candidate_datatypes.hh Thu Mar 01 10:28:27 2012 +0000 +++ b/stage3/narrow_candidate_datatypes.hh Fri Mar 02 12:53:41 2012 +0000 @@ -42,7 +42,9 @@ search_varfb_instance_type_c *search_varfb_instance_type; search_base_type_c search_base_type; symbol_c *il_operand; - symbol_c *prev_il_instruction; + il_instruction_c *fake_prev_il_instruction; + std::vector *prev_il_instructions; + std::vector *prev_il_instructions_intersected_datatypes; bool is_widening_compatible(symbol_c *left_type, symbol_c *right_type, symbol_c *result_type, const struct widen_entry widen_table[]); diff -r 587884880be6 -r 01f6664bf8c5 stage3/print_datatypes_error.cc --- a/stage3/print_datatypes_error.cc Thu Mar 01 10:28:27 2012 +0000 +++ b/stage3/print_datatypes_error.cc Fri Mar 02 12:53:41 2012 +0000 @@ -92,6 +92,27 @@ return error_found; } + + + + +/* Verify if the datatypes of all prev_il_instructions are valid and equal! */ +static bool are_all_datatypes_of_prev_il_instructions_datatypes_equal(il_instruction_c *symbol) { + if (NULL == symbol) ERROR; + bool res; + + if (symbol->prev_il_instruction.size() > 0) + res = is_type_valid(symbol->prev_il_instruction[0]->datatype); + + for (unsigned int i = 1; i < symbol->prev_il_instruction.size(); i++) + res &= is_type_equal(symbol->prev_il_instruction[i-1]->datatype, symbol->prev_il_instruction[i]->datatype); + + return res; +} + + + + /* a helper function... */ symbol_c *print_datatypes_error_c::base_type(symbol_c *symbol) { /* NOTE: symbol == NULL is valid. It will occur when, for e.g., an undefined/undeclared symbolic_variable is used @@ -239,7 +260,7 @@ return; } - if (NULL == prev_il_instruction) { + if (fake_prev_il_instruction->prev_il_instruction.empty()) { STAGE3_ERROR(0, il_operator, il_operand, "FB invocation operator '%s' must be preceded by a 'LD' (or equivalent) operator.", param_name); return; } @@ -257,7 +278,7 @@ STAGE3_ERROR(0, il_operator, il_operand, "FB called by '%s' operator does not have a parameter named '%s'", param_name, param_name); return; } - if (NULL == prev_il_instruction->datatype) { + if (!are_all_datatypes_of_prev_il_instructions_datatypes_equal(fake_prev_il_instruction)) { STAGE3_ERROR(0, il_operator, il_operand, "Data type incompatibility between parameter '%s' and value being passed.", param_name); return; } @@ -618,12 +639,29 @@ // SYM_REF2(il_instruction_c, label, il_instruction) void *print_datatypes_error_c::visit(il_instruction_c *symbol) { if (NULL != symbol->il_instruction) { - if (symbol->prev_il_instruction.size() > 1) ERROR; /* This assertion is only valid for now. Remove it once flow_control_analysis_c is complete */ - if (symbol->prev_il_instruction.size() == 0) prev_il_instruction = NULL; - else prev_il_instruction = symbol->prev_il_instruction[0]; - +// #if 0 + il_instruction_c tmp_prev_il_instruction(NULL, NULL); + /* the narrow algorithm will need access to the intersected candidate_datatype lists of all prev_il_instructions, as well as the + * list of the prev_il_instructions. + * Instead of creating two 'global' (within the class) variables, we create a single il_instruction_c variable (fake_prev_il_instruction), + * and shove that data into this single variable. + */ + tmp_prev_il_instruction.prev_il_instruction = symbol->prev_il_instruction; + intersect_prev_candidate_datatype_lists(&tmp_prev_il_instruction); + if (are_all_datatypes_of_prev_il_instructions_datatypes_equal(symbol)) + if (symbol->prev_il_instruction.size() > 0) + tmp_prev_il_instruction.datatype = (symbol->prev_il_instruction[0])->datatype; + /* Tell the il_instruction the datatype that it must generate - this was chosen by the next il_instruction (remember: we are iterating backwards!) */ + fake_prev_il_instruction = &tmp_prev_il_instruction; symbol->il_instruction->accept(*this); - prev_il_instruction = NULL; + fake_prev_il_instruction = NULL; +// #endif +// if (symbol->prev_il_instruction.size() > 1) ERROR; /* only valid for now! */ +// if (symbol->prev_il_instruction.size() == 0) prev_il_instruction = NULL; +// else prev_il_instruction = symbol->prev_il_instruction[0]; + +// symbol->il_instruction->accept(*this); +// prev_il_instruction = NULL; } return NULL; @@ -657,7 +695,7 @@ if (NULL == symbol->il_operand_list) symbol->il_operand_list = new il_operand_list_c; if (NULL == symbol->il_operand_list) ERROR; - ((list_c *)symbol->il_operand_list)->insert_element(prev_il_instruction, 0); + ((list_c *)symbol->il_operand_list)->insert_element(fake_prev_il_instruction, 0); generic_function_call_t fcall_param = { /* fcall_param.function_name = */ symbol->function_name, @@ -671,16 +709,10 @@ /* TODO: check what error message (if any) the compiler will give out if this function invocation * is not preceded by a LD operator (or another equivalent operator or list of operators). - * I.e. if it is preceded by an operator or operator list that will set the 'current value'. - * I.e. if the prev_il_operand == NULL; */ handle_function_invocation(symbol, fcall_param); - /* The first parameter of a non formal function call in IL will be the 'current value' (i.e. the prev_il_instruction) - * In order to be able to handle this without coding special cases, we simply prepend that symbol - * to the il_operand_list. This was done in fill_candidate_datatypes_c. - * We now undo those changes! - */ + /* We now undo those changes to the abstract syntax tree made above! */ ((list_c *)symbol->il_operand_list)->remove_element(0); if (((list_c *)symbol->il_operand_list)->n == 0) { /* if the list becomes empty, then that means that it did not exist before we made these changes, so we delete it! */ @@ -696,9 +728,9 @@ // SYM_REF3(il_expression_c, il_expr_operator, il_operand, simple_instr_list); void *print_datatypes_error_c::visit(il_expression_c *symbol) { /* first give the parenthesised IL list a chance to print errors */ - symbol_c *save_prev_il_instruction = prev_il_instruction; + il_instruction_c *save_fake_prev_il_instruction = fake_prev_il_instruction; symbol->simple_instr_list->accept(*this); - prev_il_instruction = save_prev_il_instruction; + fake_prev_il_instruction = save_fake_prev_il_instruction; /* Now handle the operation (il_expr_operator) that will use the result coming from the parenthesised IL list (i.e. simple_instr_list) */ il_operand = symbol->simple_instr_list; /* This is not a bug! The parenthesised expression will be used as the operator! */ @@ -759,13 +791,31 @@ // SYM_REF1(il_simple_instruction_c, il_simple_instruction, symbol_c *prev_il_instruction;) void *print_datatypes_error_c::visit(il_simple_instruction_c *symbol) { - if (symbol->prev_il_instruction.size() > 1) ERROR; /* This assertion is only valid for now. Remove it once flow_control_analysis_c is complete */ - if (symbol->prev_il_instruction.size() == 0) prev_il_instruction = NULL; - else prev_il_instruction = symbol->prev_il_instruction[0]; - + if (symbol->prev_il_instruction.size() > 1) ERROR; /* There should be no labeled insructions inside an IL expression! */ + + il_instruction_c tmp_prev_il_instruction(NULL, NULL); + /* the print error algorithm will need access to the intersected candidate_datatype lists of all prev_il_instructions, as well as the + * list of the prev_il_instructions. + * Instead of creating two 'global' (within the class) variables, we create a single il_instruction_c variable (fake_prev_il_instruction), + * and shove that data into this single variable. + */ + if (symbol->prev_il_instruction.size() > 0) + tmp_prev_il_instruction.candidate_datatypes = symbol->prev_il_instruction[0]->candidate_datatypes; + tmp_prev_il_instruction.prev_il_instruction = symbol->prev_il_instruction; + + /* copy the candidate_datatypes list */ + fake_prev_il_instruction = &tmp_prev_il_instruction; symbol->il_simple_instruction->accept(*this); - prev_il_instruction = NULL; + fake_prev_il_instruction = NULL; return NULL; + + +// if (symbol->prev_il_instruction.size() == 0) prev_il_instruction = NULL; +// else prev_il_instruction = symbol->prev_il_instruction[0]; + +// symbol->il_simple_instruction->accept(*this); +// prev_il_instruction = NULL; +// return NULL; } diff -r 587884880be6 -r 01f6664bf8c5 stage3/print_datatypes_error.hh --- a/stage3/print_datatypes_error.hh Thu Mar 01 10:28:27 2012 +0000 +++ b/stage3/print_datatypes_error.hh Fri Mar 02 12:53:41 2012 +0000 @@ -77,8 +77,12 @@ bool warning_found; /* the current data type of the data stored in the IL stack, i.e. the default variable */ - symbol_c *prev_il_instruction; - /* the current IL operand being analyzed - its symbol and its data type */ + il_instruction_c *fake_prev_il_instruction; + /* the narrow algorithm will need access to the intersected candidate_datatype lists of all prev_il_instructions, as well as the + * list of the prev_il_instructions. + * Instead of creating two 'global' (within the class) variables, we create a single il_instruction_c variable (fake_prev_il_instruction), + * and shove that data into this single variable. + */ symbol_c *il_operand_type; symbol_c *il_operand; diff -r 587884880be6 -r 01f6664bf8c5 stage4/generate_iec/generate_iec.cc --- a/stage4/generate_iec/generate_iec.cc Thu Mar 01 10:28:27 2012 +0000 +++ b/stage4/generate_iec/generate_iec.cc Fri Mar 02 12:53:41 2012 +0000 @@ -58,6 +58,10 @@ +#define ERROR error_exit(__FILE__,__LINE__) +/* function defined in main.cc */ +extern void error_exit(const char *file_name, int line_no); + @@ -153,6 +157,13 @@ #endif +/* A class used to identify an entry (literal, variable, etc...) in the abstract syntax tree with an invalid data type */ +/* This is only used from stage3 onwards. Stages 1 and 2 will never create any instances of invalid_type_name_c */ +// SYM_REF0(invalid_type_name_c) +void *visit(invalid_type_name_c *symbol) { + ERROR; + return NULL; +} /******************/