# HG changeset patch # User Mario de Sousa # Date 1329388072 0 # Node ID ff4d26b7e51dbb7e6910960747edb1ae62f44b07 # Parent bd5998ee8876de88677cdd887c4bfb4ae89af871 Narrow IL code backwords, so as to correctly handle invocations to overloaded functions from IL code. diff -r bd5998ee8876 -r ff4d26b7e51d absyntax/absyntax.def --- a/absyntax/absyntax.def Mon Feb 13 17:04:29 2012 +0000 +++ b/absyntax/absyntax.def Thu Feb 16 10:27:52 2012 +0000 @@ -913,7 +913,11 @@ SYM_LIST(instruction_list_c) /* | label ':' [il_incomplete_instruction] eol_list */ -SYM_REF2(il_instruction_c, label, il_instruction) +/* NOTE: The parameter 'prev_il_instruction' is used to point to all previous il instructions that may be executed imedaitely before this instruction. + * In case of an il instruction preceded by a label, this will include all IL instructions that jump to this label! + * It is filled in by the flow_control_analysis_c during stage 3. + */ +SYM_REF2(il_instruction_c, label, il_instruction, symbol_c *prev_il_instruction;) /* | il_simple_operator [il_operand] */ diff -r bd5998ee8876 -r ff4d26b7e51d stage3/Makefile.am --- a/stage3/Makefile.am Mon Feb 13 17:04:29 2012 +0000 +++ b/stage3/Makefile.am Thu Feb 16 10:27:52 2012 +0000 @@ -4,6 +4,7 @@ libstage3_a_SOURCES = \ stage3.cc \ + flow_control_analysis.cc \ fill_candidate_datatypes.cc \ narrow_candidate_datatypes.cc \ print_datatypes_error.cc \ diff -r bd5998ee8876 -r ff4d26b7e51d stage3/Makefile.in --- a/stage3/Makefile.in Mon Feb 13 17:04:29 2012 +0000 +++ b/stage3/Makefile.in Thu Feb 16 10:27:52 2012 +0000 @@ -71,6 +71,7 @@ libstage3_a_AR = $(AR) $(ARFLAGS) libstage3_a_LIBADD = am_libstage3_a_OBJECTS = stage3.$(OBJEXT) \ + flow_control_analysis.$(OBJEXT) \ fill_candidate_datatypes.$(OBJEXT) \ narrow_candidate_datatypes.$(OBJEXT) \ print_datatypes_error.$(OBJEXT) datatype_functions.$(OBJEXT) @@ -190,6 +191,7 @@ lib_LIBRARIES = libstage3.a libstage3_a_SOURCES = \ stage3.cc \ + flow_control_analysis.cc \ fill_candidate_datatypes.cc \ narrow_candidate_datatypes.cc \ print_datatypes_error.cc \ @@ -274,6 +276,7 @@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/datatype_functions.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fill_candidate_datatypes.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/flow_control_analysis.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/narrow_candidate_datatypes.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/print_datatypes_error.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stage3.Po@am__quote@ diff -r bd5998ee8876 -r ff4d26b7e51d stage3/datatype_functions.cc --- a/stage3/datatype_functions.cc Mon Feb 13 17:04:29 2012 +0000 +++ b/stage3/datatype_functions.cc Thu Feb 16 10:27:52 2012 +0000 @@ -172,6 +172,9 @@ * Returns: position of datatype in the list, or -1 if not found. */ int search_in_datatype_list(symbol_c *datatype, std::vector candidate_datatypes) { + if (NULL == datatype) + return -1; + for(unsigned int i = 0; i < candidate_datatypes.size(); i++) if (is_type_equal(datatype, candidate_datatypes[i])) return i; @@ -180,6 +183,24 @@ } + + + +/* Copy the elements in the candidate_datatype_list in one symbol (from) + * into the candidate_datatype_list of another symbol (to) + */ +void copy_candidate_datatype_list(symbol_c *from, symbol_c *to) { + if ((NULL == from) || (NULL == to)) + return; + + for(unsigned int i = 0; i < from->candidate_datatypes.size(); i++) + to->candidate_datatypes.push_back(from->candidate_datatypes[i]); +} + + + + + /* A helper function... */ bool is_ANY_ELEMENTARY_type(symbol_c *type_symbol) { if (type_symbol == NULL) {return false;} diff -r bd5998ee8876 -r ff4d26b7e51d stage3/datatype_functions.hh --- a/stage3/datatype_functions.hh Mon Feb 13 17:04:29 2012 +0000 +++ b/stage3/datatype_functions.hh Thu Feb 16 10:27:52 2012 +0000 @@ -141,6 +141,12 @@ */ int search_in_datatype_list(symbol_c *datatype, std::vector candidate_datatypes); +/* Copy the elements in the candidate_datatype_list in one symbol (from) + * into the candidate_datatype_list of another symbol (to) + */ +void copy_candidate_datatype_list(symbol_c *from, symbol_c *to); + + /* A helper function... */ bool is_ANY_ELEMENTARY_type (symbol_c *type_symbol); bool is_ANY_SAFEELEMENTARY_type (symbol_c *type_symbol); diff -r bd5998ee8876 -r ff4d26b7e51d stage3/fill_candidate_datatypes.cc --- a/stage3/fill_candidate_datatypes.cc Mon Feb 13 17:04:29 2012 +0000 +++ b/stage3/fill_candidate_datatypes.cc Thu Feb 16 10:27:52 2012 +0000 @@ -48,7 +48,6 @@ static int debug = 0; fill_candidate_datatypes_c::fill_candidate_datatypes_c(symbol_c *ignore) { - } fill_candidate_datatypes_c::~fill_candidate_datatypes_c(void) { @@ -68,6 +67,11 @@ /* returns true if compatible function/FB invocation, otherwise returns false */ /* Assumes that the candidate_datatype lists of all the parameters being passed haved already been filled in */ +/* + * All parameters being passed to the called function MUST be in the parameter list to which f_call points to! + * This means that, for non formal function calls in IL, de current (default value) must be artificially added to the + * beginning of the parameter list BEFORE calling handle_function_call(). + */ bool fill_candidate_datatypes_c::match_nonformal_call(symbol_c *f_call, symbol_c *f_decl) { symbol_c *call_param_value, *param_type; identifier_c *param_name; @@ -544,12 +548,15 @@ return NULL; } - +/* TYPE type_declaration_list END_TYPE */ +// SYM_REF1(data_type_declaration_c, type_declaration_list) +/* NOTE: Not required. already handled by iterator_visitor_c base class */ +/* void *fill_candidate_datatypes_c::visit(data_type_declaration_c *symbol) { - // TODO !!! - /* for the moment we must return NULL so semantic analysis of remaining code is not interrupted! */ - return NULL; -} + symbol->type_declaration_list->accept(*this); + return NULL; +} +*/ void *fill_candidate_datatypes_c::visit(enumerated_value_c *symbol) { symbol_c *enumerated_type; @@ -678,9 +685,7 @@ symbol->var_declarations_list->accept(*this); if (debug) printf("Filling candidate data types list in body of function %s\n", ((token_c *)(symbol->derived_function_name))->value); il_parenthesis_level = 0; - prev_il_instruction = NULL; symbol->function_body->accept(*this); - prev_il_instruction = NULL; delete search_varfb_instance_type; search_varfb_instance_type = NULL; return NULL; @@ -694,9 +699,7 @@ symbol->var_declarations->accept(*this); if (debug) printf("Filling candidate data types list in body of FB %s\n", ((token_c *)(symbol->fblock_name))->value); il_parenthesis_level = 0; - prev_il_instruction = NULL; symbol->fblock_body->accept(*this); - prev_il_instruction = NULL; delete search_varfb_instance_type; search_varfb_instance_type = NULL; return NULL; @@ -710,9 +713,7 @@ symbol->var_declarations->accept(*this); if (debug) printf("Filling candidate data types list in body of program %s\n", ((token_c *)(symbol->program_type_name))->value); il_parenthesis_level = 0; - prev_il_instruction = NULL; symbol->function_block_body->accept(*this); - prev_il_instruction = NULL; delete search_varfb_instance_type; search_varfb_instance_type = NULL; return NULL; @@ -737,7 +738,30 @@ /***********************************/ /* B 2.1 Instructions and Operands */ /***********************************/ + +/*| instruction_list il_instruction */ +// SYM_LIST(instruction_list_c) // 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); +void *fill_candidate_datatypes_c::visit(il_instruction_c *symbol) { + if (NULL == symbol->il_instruction) + return NULL; + + prev_il_instruction = symbol->prev_il_instruction; + symbol->il_instruction->accept(*this); + /* This object has (inherits) the same candidate datatypes as the il_instruction */ + copy_candidate_datatype_list(symbol->il_instruction /*from*/, symbol /*to*/); + prev_il_instruction = NULL; + + return NULL; +} + + + void *fill_candidate_datatypes_c::visit(il_simple_operation_c *symbol) { /* determine the data type of the operand */ if (NULL != symbol->il_operand) { @@ -747,6 +771,8 @@ il_operand = symbol->il_operand; symbol->il_simple_operator->accept(*this); il_operand = NULL; + /* This object has (inherits) the same candidate datatypes as the il_simple_operator */ + copy_candidate_datatype_list(symbol->il_simple_operator /*from*/, symbol /*to*/); return NULL; } @@ -897,7 +923,6 @@ symbol->candidate_datatypes.push_back(il_operand->candidate_datatypes[i]); } if (debug) std::cout << "LD [" << il_operand->candidate_datatypes.size() << "] ==> " << symbol->candidate_datatypes.size() << " result.\n"; - prev_il_instruction = symbol; return NULL; } @@ -907,7 +932,6 @@ symbol->candidate_datatypes.push_back(il_operand->candidate_datatypes[i]); } if (debug) std::cout << "LDN [" << il_operand->candidate_datatypes.size() << "] ==> " << symbol->candidate_datatypes.size() << " result.\n"; - prev_il_instruction = symbol; return NULL; } @@ -924,7 +948,6 @@ } } if (debug) std::cout << "ST [" << prev_il_instruction->candidate_datatypes.size() << "," << il_operand->candidate_datatypes.size() << "] ==> " << symbol->candidate_datatypes.size() << " result.\n"; - prev_il_instruction = symbol; return NULL; } @@ -941,12 +964,10 @@ } } if (debug) std::cout << "STN [" << prev_il_instruction->candidate_datatypes.size() << "," << il_operand->candidate_datatypes.size() << "] ==> " << symbol->candidate_datatypes.size() << " result.\n"; - prev_il_instruction = symbol; return NULL; } void *fill_candidate_datatypes_c::visit(NOT_operator_c *symbol) { - prev_il_instruction = symbol; return NULL; } @@ -963,7 +984,6 @@ } } if (debug) std::cout << "S [" << prev_il_instruction->candidate_datatypes.size() << "," << il_operand->candidate_datatypes.size() << "] ==> " << symbol->candidate_datatypes.size() << " result.\n"; - prev_il_instruction = symbol; return NULL; } @@ -980,7 +1000,6 @@ } } if (debug) std::cout << "R [" << prev_il_instruction->candidate_datatypes.size() << "," << il_operand->candidate_datatypes.size() << "] ==> " << symbol->candidate_datatypes.size() << " result.\n"; - prev_il_instruction = symbol; return NULL; } @@ -997,7 +1016,6 @@ } } if (debug) std::cout << "S1 [" << prev_il_instruction->candidate_datatypes.size() << "," << il_operand->candidate_datatypes.size() << "] ==> " << symbol->candidate_datatypes.size() << " result.\n"; - prev_il_instruction = symbol; return NULL; } @@ -1014,7 +1032,6 @@ } } if (debug) std::cout << "R1 [" << prev_il_instruction->candidate_datatypes.size() << "," << il_operand->candidate_datatypes.size() << "] ==> " << symbol->candidate_datatypes.size() << " result.\n"; - prev_il_instruction = symbol; return NULL; } @@ -1022,7 +1039,6 @@ /* MANU: * How it works? I(MANU) don't know this function */ - prev_il_instruction = symbol; return NULL; } @@ -1030,7 +1046,6 @@ /* MANU: * How it works? I(MANU) don't know this function */ - prev_il_instruction = symbol; return NULL; } @@ -1038,8 +1053,6 @@ /* MANU: * How it works? I(MANU) don't know this function */ - - prev_il_instruction = symbol; return NULL; } @@ -1047,8 +1060,6 @@ /* MANU: * How it works? I(MANU) don't know this function */ - - prev_il_instruction = symbol; return NULL; } @@ -1056,8 +1067,6 @@ /* MANU: * How it works? I(MANU) don't know this function */ - - prev_il_instruction = symbol; return NULL; } @@ -1065,8 +1074,6 @@ /* MANU: * How it works? I(MANU) don't know this function */ - - prev_il_instruction = symbol; return NULL; } @@ -1083,7 +1090,6 @@ symbol->candidate_datatypes.push_back(prev_instruction_type); } } - prev_il_instruction = symbol; return NULL; } @@ -1100,7 +1106,6 @@ symbol->candidate_datatypes.push_back(prev_instruction_type); } } - prev_il_instruction = symbol; return NULL; } @@ -1117,7 +1122,6 @@ symbol->candidate_datatypes.push_back(prev_instruction_type); } } - prev_il_instruction = symbol; return NULL; } @@ -1134,7 +1138,6 @@ symbol->candidate_datatypes.push_back(prev_instruction_type); } } - prev_il_instruction = symbol; return NULL; } @@ -1151,7 +1154,6 @@ symbol->candidate_datatypes.push_back(prev_instruction_type); } } - prev_il_instruction = symbol; return NULL; } @@ -1168,7 +1170,6 @@ symbol->candidate_datatypes.push_back(prev_instruction_type); } } - prev_il_instruction = symbol; return NULL; } @@ -1192,7 +1193,6 @@ } } if (debug) std::cout << "ADD [" << prev_il_instruction->candidate_datatypes.size() << "," << il_operand->candidate_datatypes.size() << "] ==> " << symbol->candidate_datatypes.size() << " result.\n"; - prev_il_instruction = symbol; return NULL; } @@ -1215,7 +1215,6 @@ } } if (debug) std::cout << "SUB [" << prev_il_instruction->candidate_datatypes.size() << "," << il_operand->candidate_datatypes.size() << "] ==> " << symbol->candidate_datatypes.size() << " result.\n"; - prev_il_instruction = symbol; return NULL; } @@ -1238,7 +1237,6 @@ } } if (debug) std::cout << "MUL [" << prev_il_instruction->candidate_datatypes.size() << "," << il_operand->candidate_datatypes.size() << "] ==> " << symbol->candidate_datatypes.size() << " result.\n"; - prev_il_instruction = symbol; return NULL; } @@ -1261,7 +1259,6 @@ } } if (debug) std::cout << "DIV [" << prev_il_instruction->candidate_datatypes.size() << "," << il_operand->candidate_datatypes.size() << "] ==> " << symbol->candidate_datatypes.size() << " result.\n"; - prev_il_instruction = symbol; return NULL; } @@ -1279,7 +1276,6 @@ } } if (debug) std::cout << "MOD [" << prev_il_instruction->candidate_datatypes.size() << "," << il_operand->candidate_datatypes.size() << "] ==> " << symbol->candidate_datatypes.size() << " result.\n"; - prev_il_instruction = symbol; return NULL; } @@ -1297,7 +1293,6 @@ } } if (found) symbol->candidate_datatypes.push_back(&search_constant_type_c::bool_type_name); - prev_il_instruction = symbol; return NULL; } @@ -1315,7 +1310,6 @@ } } if (found) symbol->candidate_datatypes.push_back(&search_constant_type_c::bool_type_name); - prev_il_instruction = symbol; return NULL; } @@ -1333,7 +1327,6 @@ } } if (found) symbol->candidate_datatypes.push_back(&search_constant_type_c::bool_type_name); - prev_il_instruction = symbol; return NULL; } @@ -1351,7 +1344,6 @@ } } if (found) symbol->candidate_datatypes.push_back(&search_constant_type_c::bool_type_name); - prev_il_instruction = symbol; return NULL; } @@ -1369,7 +1361,6 @@ } } if (found) symbol->candidate_datatypes.push_back(&search_constant_type_c::bool_type_name); - prev_il_instruction = symbol; return NULL; } @@ -1387,7 +1378,6 @@ } } if (found) symbol->candidate_datatypes.push_back(&search_constant_type_c::bool_type_name); - prev_il_instruction = symbol; return NULL; } @@ -1398,7 +1388,6 @@ symbol->candidate_datatypes.push_back(prev_il_instruction->candidate_datatypes[i]); } if (debug) std::cout << "CAL [" << prev_il_instruction->candidate_datatypes.size() << "] ==> " << symbol->candidate_datatypes.size() << " result.\n"; - prev_il_instruction = symbol; return NULL; } @@ -1409,7 +1398,6 @@ symbol->candidate_datatypes.push_back(prev_il_instruction->candidate_datatypes[i]); } if (debug) std::cout << "CALC [" << prev_il_instruction->candidate_datatypes.size() << "] ==> " << symbol->candidate_datatypes.size() << " result.\n"; - prev_il_instruction = symbol; return NULL; } @@ -1420,7 +1408,6 @@ symbol->candidate_datatypes.push_back(prev_il_instruction->candidate_datatypes[i]); } if (debug) std::cout << "CALCN [" << prev_il_instruction->candidate_datatypes.size() << "] ==> " << symbol->candidate_datatypes.size() << " result.\n"; - prev_il_instruction = symbol; return NULL; } @@ -1431,7 +1418,6 @@ symbol->candidate_datatypes.push_back(prev_il_instruction->candidate_datatypes[i]); } if (debug) std::cout << "RET [" << prev_il_instruction->candidate_datatypes.size() << "] ==> " << symbol->candidate_datatypes.size() << " result.\n"; - prev_il_instruction = symbol; return NULL; } @@ -1442,7 +1428,6 @@ symbol->candidate_datatypes.push_back(prev_il_instruction->candidate_datatypes[i]); } if (debug) std::cout << "RETC [" << prev_il_instruction->candidate_datatypes.size() << "] ==> " << symbol->candidate_datatypes.size() << " result.\n"; - prev_il_instruction = symbol; return NULL; } @@ -1453,7 +1438,6 @@ symbol->candidate_datatypes.push_back(prev_il_instruction->candidate_datatypes[i]); } if (debug) std::cout << "RETCN [" << prev_il_instruction->candidate_datatypes.size() << "] ==> " << symbol->candidate_datatypes.size() << " result.\n"; - prev_il_instruction = symbol; return NULL; } @@ -1464,7 +1448,6 @@ symbol->candidate_datatypes.push_back(prev_il_instruction->candidate_datatypes[i]); } if (debug) std::cout << "JMP [" << prev_il_instruction->candidate_datatypes.size() << "] ==> " << symbol->candidate_datatypes.size() << " result.\n"; - prev_il_instruction = symbol; return NULL; } @@ -1474,7 +1457,6 @@ symbol->candidate_datatypes.push_back(prev_il_instruction->candidate_datatypes[i]); } if (debug) std::cout << "JMPC [" << prev_il_instruction->candidate_datatypes.size() << "] ==> " << symbol->candidate_datatypes.size() << " result.\n"; - prev_il_instruction = symbol; return NULL; } @@ -1484,7 +1466,6 @@ symbol->candidate_datatypes.push_back(prev_il_instruction->candidate_datatypes[i]); } if (debug) std::cout << "JMPCN [" << prev_il_instruction->candidate_datatypes.size() << "] ==> " << symbol->candidate_datatypes.size() << " result.\n"; - prev_il_instruction = symbol; return NULL; } /* Symbol class handled together with function call checks */ diff -r bd5998ee8876 -r ff4d26b7e51d stage3/fill_candidate_datatypes.hh --- a/stage3/fill_candidate_datatypes.hh Mon Feb 13 17:04:29 2012 +0000 +++ b/stage3/fill_candidate_datatypes.hh Thu Feb 16 10:27:52 2012 +0000 @@ -145,7 +145,7 @@ /* B 1.3.3 - Derived data types */ /********************************/ void *visit(subrange_c *symbol); - void *visit(data_type_declaration_c *symbol); +// void *visit(data_type_declaration_c *symbol); void *visit(enumerated_value_c *symbol); /*********************/ @@ -194,6 +194,7 @@ /* B 2.1 Instructions and Operands */ /***********************************/ // void *visit(instruction_list_c *symbol); + void *visit(il_instruction_c *symbol); void *visit(il_simple_operation_c *symbol); void *visit(il_function_call_c *symbol); void *visit(il_expression_c *symbol); diff -r bd5998ee8876 -r ff4d26b7e51d stage3/flow_control_analysis.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/stage3/flow_control_analysis.cc Thu Feb 16 10:27:52 2012 +0000 @@ -0,0 +1,185 @@ +/* + * matiec - a compiler for the programming languages defined in IEC 61131-3 + * + * Copyright (C) 2012 Mario de Sousa (msousa@fe.up.pt) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * + * This code is made available on the understanding that it will not be + * used in safety-critical situations without a full and competent review. + */ + +/* + * An IEC 61131-3 compiler. + * + * Based on the + * FINAL DRAFT - IEC 61131-3, 2nd Ed. (2001-12-10) + * + */ + + +/* + * Do flow control analysis of the IEC 61131-3 code. + * + * We currently only do this for IL code. + * This class will annotate the abstract syntax tree, by filling in the + * prev_il_instruction variable in the il_instruction_c, so it points to + * the previous il_instruction_c object in the instruction list instruction_list_c. + */ + +#include "flow_control_analysis.hh" + + + +/* set to 1 to see debug info during execution */ +static int debug = 0; + +flow_control_analysis_c::flow_control_analysis_c(symbol_c *ignore) { +} + +flow_control_analysis_c::~flow_control_analysis_c(void) { +} + + + +/************************************/ +/* B 1.5 Program organization units */ +/************************************/ +/*********************/ +/* 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); + 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; + return NULL; +} + +/***************************/ +/* 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); + 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; + return NULL; +} + +/********************/ +/* 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); + 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; + return NULL; +} + + +/********************************/ +/* B 1.7 Configuration elements */ +/********************************/ +void *flow_control_analysis_c::visit(configuration_declaration_c *symbol) { + return NULL; +} + + +/****************************************/ +/* B.2 - Language IL (Instruction List) */ +/****************************************/ +/***********************************/ +/* B 2.1 Instructions and Operands */ +/***********************************/ + +/*| instruction_list il_instruction */ +// SYM_LIST(instruction_list_c) +void *flow_control_analysis_c::visit(instruction_list_c *symbol) { + for(int i = 1; i < symbol->n; i++) { + prev_il_instruction = symbol->elements[i-1]; + symbol->elements[i]->accept(*this); + } + return NULL; +} + +/* | label ':' [il_incomplete_instruction] eol_list */ +// 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 = prev_il_instruction; + /* TODO: handle labels correctly! + * + * Don't forget to handle multiple consecutive lables too! + * label2: + * label3: + * label4: + * LD I + */ + +return NULL; +} + + +#if 0 +/* | 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; +} + +/* | il_expr_operator '(' [il_operand] eol_list [simple_instr_list] ')' */ +// SYM_REF3(il_expression_c, il_expr_operator, il_operand, simple_instr_list); +void *flow_control_analysis_c::visit(il_expression_c *symbol) { +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 ')' + * | il_call_operator prev_declared_fb_name '(' il_operand_list ')' + * | il_call_operator prev_declared_fb_name '(' eol_list il_param_list ')' + */ +/* 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; +} + + +/* | 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; +} + + +/* + void *visit(il_operand_list_c *symbol); + void *visit(simple_instr_list_c *symbol); + void *visit(il_param_list_c *symbol); + void *visit(il_param_assignment_c *symbol); + void *visit(il_param_out_assignment_c *symbol); + */ + + +#endif + diff -r bd5998ee8876 -r ff4d26b7e51d stage3/flow_control_analysis.hh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/stage3/flow_control_analysis.hh Thu Feb 16 10:27:52 2012 +0000 @@ -0,0 +1,161 @@ +/* + * matiec - a compiler for the programming languages defined in IEC 61131-3 + * + * Copyright (C) 2012 Mario de Sousa (msousa@fe.up.pt) + * + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * + * This code is made available on the understanding that it will not be + * used in safety-critical situations without a full and competent review. + */ + +/* + * An IEC 61131-3 compiler. + * + * Based on the + * FINAL DRAFT - IEC 61131-3, 2nd Ed. (2001-12-10) + * + */ + + +/* + * Do flow control analysis of the IEC 61131-3 code. + * + * We currently only do this for IL code. + * This class will annotate the abstract syntax tree, by filling in the + * prev_il_instruction variable in the il_instruction_c, so it points to + * the previous il_instruction_c object in the instruction list instruction_list_c. + */ + + + +#include "../absyntax_utils/absyntax_utils.hh" + + +class flow_control_analysis_c: public iterator_visitor_c { + + private: + search_varfb_instance_type_c *search_varfb_instance_type; + symbol_c *prev_il_instruction; + + public: + flow_control_analysis_c(symbol_c *ignore); + virtual ~flow_control_analysis_c(void); + + /**************************************/ + /* B 1.5 - Program organization units */ + /**************************************/ + /***********************/ + /* B 1.5.1 - Functions */ + /***********************/ + void *visit(function_declaration_c *symbol); + + /*****************************/ + /* B 1.5.2 - Function blocks */ + /*****************************/ + void *visit(function_block_declaration_c *symbol); + + /**********************/ + /* B 1.5.3 - Programs */ + /**********************/ + void *visit(program_declaration_c *symbol); + + /********************************/ + /* B 1.7 Configuration elements */ + /********************************/ + void *visit(configuration_declaration_c *symbol); + + /****************************************/ + /* B.2 - Language IL (Instruction List) */ + /****************************************/ + /***********************************/ + /* B 2.1 Instructions and Operands */ + /***********************************/ + void *visit(instruction_list_c *symbol); + void *visit(il_instruction_c *symbol); +// void *visit(il_simple_operation_c *symbol); +// void *visit(il_function_call_c *symbol); +// void *visit(il_expression_c *symbol); +// void *visit(il_fb_call_c *symbol); +// void *visit(il_formal_funct_call_c *symbol); + /* + void *visit(il_operand_list_c *symbol); + void *visit(simple_instr_list_c *symbol); + void *visit(il_param_list_c *symbol); + void *visit(il_param_assignment_c *symbol); + void *visit(il_param_out_assignment_c *symbol); + */ + + /*******************/ + /* 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); + +}; // flow_control_analysis_c + + + + + + + + diff -r bd5998ee8876 -r ff4d26b7e51d stage3/narrow_candidate_datatypes.cc --- a/stage3/narrow_candidate_datatypes.cc Mon Feb 13 17:04:29 2012 +0000 +++ b/stage3/narrow_candidate_datatypes.cc Thu Feb 16 10:27:52 2012 +0000 @@ -76,6 +76,11 @@ return false; } +/* + * All parameters being passed to the called function MUST be in the parameter list to which f_call points to! + * This means that, for non formal function calls in IL, de current (default value) must be artificially added to the + * beginning of the parameter list BEFORE calling handle_function_call(). + */ void narrow_candidate_datatypes_c::narrow_nonformal_call(symbol_c *f_call, symbol_c *f_decl, int *ext_parm_count) { symbol_c *call_param_value, *param_type; identifier_c *param_name; @@ -110,6 +115,19 @@ if ((NULL != param_name) && (NULL == desired_datatype)) ERROR; if ((NULL == param_name) && (NULL != desired_datatype)) ERROR; + /* NOTE: When we are handling a nonformal function call made from IL, the first parameter is the 'default' or 'current' + * il value. However, a pointer to the prev_il_instruction is pre-pended into the operand list (done in fill_candidate_datatypes_c, + * and later undone in print_datatypes_error_c - this class is run after the first, and before the latter!), so + * the call + * call_param_value->accept(*this); + * may actually be calling an object of the il_instruction_c class. + * If that is the case, that same il_instruction_c object will be called again inside the for() loop + * of void *narrow_candidate_datatypes_c::visit(instruction_list_c *symbol); + * This is actually safe, as the narrow algorithm for all IL instructions is idem-potent. + * (It is easier to just let it be called twice than to hack the code to guarantee that it is + * only called once - this would also make this hacked code ugly an un-elegant, so we leave + * it as it is for now...) + */ set_datatype(desired_datatype, call_param_value); call_param_value->accept(*this); @@ -265,6 +283,17 @@ return NULL; } +/* simple_specification ASSIGN constant */ +// SYM_REF2(simple_spec_init_c, simple_specification, constant) +void *narrow_candidate_datatypes_c::visit(simple_spec_init_c *symbol) { + symbol_c *datatype = base_type(symbol->simple_specification); + if (NULL != symbol->constant) { + int typeoffset = search_in_datatype_list(datatype, symbol->constant->candidate_datatypes); + if (typeoffset >= 0) + symbol->constant->datatype = symbol->constant->candidate_datatypes[typeoffset]; + } + return NULL; +} /*********************/ /* B 1.4 - Variables */ @@ -309,10 +338,9 @@ /*********************/ void *narrow_candidate_datatypes_c::visit(function_declaration_c *symbol) { search_varfb_instance_type = new search_varfb_instance_type_c(symbol); + symbol->var_declarations_list->accept(*this); if (debug) printf("Narrowing candidate data types list in body of function %s\n", ((token_c *)(symbol->derived_function_name))->value); - prev_il_instruction = NULL; symbol->function_body->accept(*this); - prev_il_instruction = NULL; delete search_varfb_instance_type; search_varfb_instance_type = NULL; return NULL; @@ -323,10 +351,9 @@ /***************************/ void *narrow_candidate_datatypes_c::visit(function_block_declaration_c *symbol) { search_varfb_instance_type = new search_varfb_instance_type_c(symbol); + symbol->var_declarations->accept(*this); if (debug) printf("Narrowing candidate data types list in body of FB %s\n", ((token_c *)(symbol->fblock_name))->value); - prev_il_instruction = NULL; symbol->fblock_body->accept(*this); - prev_il_instruction = NULL; delete search_varfb_instance_type; search_varfb_instance_type = NULL; return NULL; @@ -337,10 +364,9 @@ /********************/ void *narrow_candidate_datatypes_c::visit(program_declaration_c *symbol) { search_varfb_instance_type = new search_varfb_instance_type_c(symbol); + symbol->var_declarations->accept(*this); if (debug) printf("Narrowing candidate data types list in body of program %s\n", ((token_c *)(symbol->program_type_name))->value); - prev_il_instruction = NULL; symbol->function_block_body->accept(*this); - prev_il_instruction = NULL; delete search_varfb_instance_type; search_varfb_instance_type = NULL; return NULL; @@ -351,10 +377,8 @@ /* B 1.7 Configuration elements */ /********************************/ void *narrow_candidate_datatypes_c::visit(configuration_declaration_c *symbol) { -#if 0 // TODO !!! /* for the moment we must return NULL so semantic analysis of remaining code is not interrupted! */ -#endif return NULL; } @@ -365,13 +389,38 @@ /***********************************/ /* B 2.1 Instructions and Operands */ /***********************************/ + +/*| instruction_list il_instruction */ +// SYM_LIST(instruction_list_c) +void *narrow_candidate_datatypes_c::visit(instruction_list_c *symbol) { + /* We need to go through the instructions backwards, so we can not use the base class' visitor */ + for(int i = symbol->n-1; i >= 0; i--) { + symbol->elements[i]->accept(*this); + } + return NULL; +} + +/* | label ':' [il_incomplete_instruction] eol_list */ +// SYM_REF2(il_instruction_c, label, il_instruction) +// void *visit(instruction_list_c *symbol); +void *narrow_candidate_datatypes_c::visit(il_instruction_c *symbol) { + if (NULL == symbol->il_instruction) + return NULL; + + prev_il_instruction = symbol->prev_il_instruction; + /* Tell the il_instruction the datatype that it must generate - this was chosen by the next il_instruction (we iterate backwards!) */ + symbol->il_instruction->datatype = symbol->datatype; + symbol->il_instruction->accept(*this); + return NULL; +} + + // void *visit(instruction_list_c *symbol); void *narrow_candidate_datatypes_c::visit(il_simple_operation_c *symbol) { + /* Tell the il_simple_operator the datatype that it must generate - this was chosen by the next il_instruction (we iterate backwards!) */ + symbol->il_simple_operator->datatype = symbol->datatype; + /* recursive call to see whether data types are compatible */ il_operand = symbol->il_operand; - if (NULL != symbol->il_operand) { - symbol->il_operand->accept(*this); - } - /* recursive call to see whether data types are compatible */ symbol->il_simple_operator->accept(*this); il_operand = NULL; return NULL; @@ -399,6 +448,8 @@ * the following code is actually correct! */ narrow_function_invocation(symbol, fcall_param); + /* set the desired datatype of the previous il instruction */ + prev_il_instruction->datatype = symbol->datatype; return NULL; } @@ -464,6 +515,8 @@ }; narrow_function_invocation(symbol, fcall_param); + /* set the desired datatype of the previous il instruction */ + prev_il_instruction->datatype = symbol->datatype; return NULL; } @@ -479,28 +532,51 @@ /*******************/ /* B 2.2 Operators */ /*******************/ -void *narrow_candidate_datatypes_c::visit(LD_operator_c *symbol) { - prev_il_instruction = symbol; - return NULL; -} - -void *narrow_candidate_datatypes_c::visit(LDN_operator_c *symbol) { + +void *narrow_candidate_datatypes_c::handle_il_instruction(symbol_c *symbol) { + if (NULL == symbol->datatype) + /* next IL instructions were unable to determine the datatype this instruction should produce */ + return NULL; + /* set the datatype for the operand */ + il_operand->datatype = symbol->datatype; + il_operand->accept(*this); + /* set the desired datatype of the previous il instruction */ + prev_il_instruction->datatype = symbol->datatype; + return NULL; +} + +void *narrow_candidate_datatypes_c::visit(LD_operator_c *symbol) { + if (NULL == symbol->datatype) + /* next IL instructions were unable to determine the datatype this instruction should produce */ + return NULL; + /* set the datatype for the operand */ + il_operand->datatype = symbol->datatype; + il_operand->accept(*this); + return NULL; +} + + +void *narrow_candidate_datatypes_c::visit(LDN_operator_c *symbol) { + if (NULL == symbol->datatype) + /* next IL instructions were unable to determine the datatype this instruction should produce */ + return NULL; + /* set the datatype for the operand */ + il_operand->datatype = symbol->datatype; + il_operand->accept(*this); + return NULL; +} + +void *narrow_candidate_datatypes_c::visit(ST_operator_c *symbol) { + if (debug) printf("narrow_candidate_datatypes_c::visit(ST_operator_c *symbol) called.\n"); if (symbol->candidate_datatypes.size() != 1) return NULL; symbol->datatype = symbol->candidate_datatypes[0]; + /* set the datatype for the operand */ il_operand->datatype = symbol->datatype; il_operand->accept(*this); - prev_il_instruction = symbol; - return NULL; -} - -void *narrow_candidate_datatypes_c::visit(ST_operator_c *symbol) { - if (symbol->candidate_datatypes.size() != 1) - return NULL; - symbol->datatype = symbol->candidate_datatypes[0]; - il_operand->datatype = symbol->datatype; - il_operand->accept(*this); - prev_il_instruction = symbol; + /* 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); return NULL; } @@ -508,9 +584,11 @@ if (symbol->candidate_datatypes.size() != 1) return NULL; symbol->datatype = symbol->candidate_datatypes[0]; + /* set the datatype for the operand */ il_operand->datatype = symbol->datatype; il_operand->accept(*this); - prev_il_instruction = symbol; + /* set the desired datatype of the previous il instruction */ + prev_il_instruction->datatype = symbol->datatype; return NULL; } @@ -519,233 +597,86 @@ return NULL; } -void *narrow_candidate_datatypes_c::visit(S_operator_c *symbol) { - if (symbol->candidate_datatypes.size() != 1) - return NULL; - symbol->datatype = symbol->candidate_datatypes[0]; - il_operand->datatype = symbol->datatype; - il_operand->accept(*this); - prev_il_instruction = symbol; - return NULL; -} - -void *narrow_candidate_datatypes_c::visit(R_operator_c *symbol) { - if (symbol->candidate_datatypes.size() != 1) - return NULL; - symbol->datatype = symbol->candidate_datatypes[0]; - il_operand->datatype = symbol->datatype; - il_operand->accept(*this); - prev_il_instruction = symbol; - return NULL; -} - -void *narrow_candidate_datatypes_c::visit(S1_operator_c *symbol) { - if (symbol->candidate_datatypes.size() != 1) - return NULL; - symbol->datatype = symbol->candidate_datatypes[0]; - il_operand->datatype = symbol->datatype; - il_operand->accept(*this); - prev_il_instruction = symbol; - return NULL; -} - -void *narrow_candidate_datatypes_c::visit(R1_operator_c *symbol) { - if (symbol->candidate_datatypes.size() != 1) - return NULL; - symbol->datatype = symbol->candidate_datatypes[0]; - il_operand->datatype = symbol->datatype; - il_operand->accept(*this); - prev_il_instruction = symbol; - return NULL; -} +void *narrow_candidate_datatypes_c::visit(S_operator_c *symbol) {return handle_il_instruction(symbol);} +void *narrow_candidate_datatypes_c::visit(R_operator_c *symbol) {return handle_il_instruction(symbol);} +void *narrow_candidate_datatypes_c::visit(S1_operator_c *symbol) {return handle_il_instruction(symbol);} +void *narrow_candidate_datatypes_c::visit(R1_operator_c *symbol) {return handle_il_instruction(symbol);} void *narrow_candidate_datatypes_c::visit(CLK_operator_c *symbol) { - prev_il_instruction = symbol; return NULL; } void *narrow_candidate_datatypes_c::visit(CU_operator_c *symbol) { - prev_il_instruction = symbol; return NULL; } void *narrow_candidate_datatypes_c::visit(CD_operator_c *symbol) { - prev_il_instruction = symbol; return NULL; } void *narrow_candidate_datatypes_c::visit(PV_operator_c *symbol) { - prev_il_instruction = symbol; return NULL; } void *narrow_candidate_datatypes_c::visit(IN_operator_c *symbol) { - prev_il_instruction = symbol; return NULL; } void *narrow_candidate_datatypes_c::visit(PT_operator_c *symbol) { - prev_il_instruction = symbol; - return NULL; -} - -void *narrow_candidate_datatypes_c::visit(AND_operator_c *symbol) { - if (symbol->candidate_datatypes.size() != 1) - return NULL; - symbol->datatype = symbol->candidate_datatypes[0]; - il_operand->datatype = symbol->datatype; - il_operand->accept(*this); - prev_il_instruction = symbol; - return NULL; -} - -void *narrow_candidate_datatypes_c::visit(OR_operator_c *symbol) { - if (symbol->candidate_datatypes.size() != 1) - return NULL; - symbol->datatype = symbol->candidate_datatypes[0]; - il_operand->datatype = symbol->datatype; - il_operand->accept(*this); - prev_il_instruction = symbol; - return NULL; -} - -void *narrow_candidate_datatypes_c::visit(XOR_operator_c *symbol) { - if (symbol->candidate_datatypes.size() != 1) - return NULL; - symbol->datatype = symbol->candidate_datatypes[0]; - il_operand->datatype = symbol->datatype; - il_operand->accept(*this); - prev_il_instruction = symbol; - return NULL; -} - -void *narrow_candidate_datatypes_c::visit(ANDN_operator_c *symbol) { - if (symbol->candidate_datatypes.size() != 1) - return NULL; - symbol->datatype = symbol->candidate_datatypes[0]; - il_operand->datatype = symbol->datatype; - il_operand->accept(*this); - prev_il_instruction = symbol; - return NULL; -} - -void *narrow_candidate_datatypes_c::visit(ORN_operator_c *symbol) { - if (symbol->candidate_datatypes.size() != 1) - return NULL; - symbol->datatype = symbol->candidate_datatypes[0]; - il_operand->datatype = symbol->datatype; - il_operand->accept(*this); - prev_il_instruction = symbol; - return NULL; -} - -void *narrow_candidate_datatypes_c::visit(XORN_operator_c *symbol) { - if (symbol->candidate_datatypes.size() != 1) - return NULL; - symbol->datatype = symbol->candidate_datatypes[0]; - il_operand->datatype = symbol->datatype; - il_operand->accept(*this); - prev_il_instruction = symbol; - return NULL; -} - -void *narrow_candidate_datatypes_c::visit(ADD_operator_c *symbol) { - prev_il_instruction = symbol; - return NULL; -} - -void *narrow_candidate_datatypes_c::visit(SUB_operator_c *symbol) { - prev_il_instruction = symbol; - return NULL; -} - -void *narrow_candidate_datatypes_c::visit(MUL_operator_c *symbol) { - prev_il_instruction = symbol; - return NULL; -} - -void *narrow_candidate_datatypes_c::visit(DIV_operator_c *symbol) { - prev_il_instruction = symbol; - return NULL; -} - -void *narrow_candidate_datatypes_c::visit(MOD_operator_c *symbol) { - prev_il_instruction = symbol; - return NULL; -} - -void *narrow_candidate_datatypes_c::visit(GT_operator_c *symbol) { - prev_il_instruction = symbol; - return NULL; -} - -void *narrow_candidate_datatypes_c::visit(GE_operator_c *symbol) { - prev_il_instruction = symbol; - return NULL; -} - -void *narrow_candidate_datatypes_c::visit(EQ_operator_c *symbol) { - prev_il_instruction = symbol; - return NULL; -} - -void *narrow_candidate_datatypes_c::visit(LT_operator_c *symbol) { - prev_il_instruction = symbol; - return NULL; -} - -void *narrow_candidate_datatypes_c::visit(LE_operator_c *symbol) { - prev_il_instruction = symbol; - return NULL; -} - -void *narrow_candidate_datatypes_c::visit(NE_operator_c *symbol) { - prev_il_instruction = symbol; - return NULL; -} + return NULL; +} + +void *narrow_candidate_datatypes_c::visit(AND_operator_c *symbol) {return handle_il_instruction(symbol);} +void *narrow_candidate_datatypes_c::visit(OR_operator_c *symbol) {return handle_il_instruction(symbol);} +void *narrow_candidate_datatypes_c::visit(XOR_operator_c *symbol) {return handle_il_instruction(symbol);} +void *narrow_candidate_datatypes_c::visit(ANDN_operator_c *symbol) {return handle_il_instruction(symbol);} +void *narrow_candidate_datatypes_c::visit(ORN_operator_c *symbol) {return handle_il_instruction(symbol);} +void *narrow_candidate_datatypes_c::visit(XORN_operator_c *symbol) {return handle_il_instruction(symbol);} +void *narrow_candidate_datatypes_c::visit(ADD_operator_c *symbol) {return handle_il_instruction(symbol);} +void *narrow_candidate_datatypes_c::visit(SUB_operator_c *symbol) {return handle_il_instruction(symbol);} +void *narrow_candidate_datatypes_c::visit(MUL_operator_c *symbol) {return handle_il_instruction(symbol);} +void *narrow_candidate_datatypes_c::visit(DIV_operator_c *symbol) {return handle_il_instruction(symbol);} +void *narrow_candidate_datatypes_c::visit(MOD_operator_c *symbol) {return handle_il_instruction(symbol);} +void *narrow_candidate_datatypes_c::visit(GT_operator_c *symbol) {return handle_il_instruction(symbol);} +void *narrow_candidate_datatypes_c::visit(GE_operator_c *symbol) {return handle_il_instruction(symbol);} +void *narrow_candidate_datatypes_c::visit(EQ_operator_c *symbol) {return handle_il_instruction(symbol);} +void *narrow_candidate_datatypes_c::visit(LT_operator_c *symbol) {return handle_il_instruction(symbol);} +void *narrow_candidate_datatypes_c::visit(LE_operator_c *symbol) {return handle_il_instruction(symbol);} +void *narrow_candidate_datatypes_c::visit(NE_operator_c *symbol) {return handle_il_instruction(symbol);} void *narrow_candidate_datatypes_c::visit(CAL_operator_c *symbol) { - prev_il_instruction = symbol; return NULL; } void *narrow_candidate_datatypes_c::visit(CALC_operator_c *symbol) { - prev_il_instruction = symbol; return NULL; } void *narrow_candidate_datatypes_c::visit(CALCN_operator_c *symbol) { - prev_il_instruction = symbol; return NULL; } void *narrow_candidate_datatypes_c::visit(RET_operator_c *symbol) { - prev_il_instruction = symbol; return NULL; } void *narrow_candidate_datatypes_c::visit(RETC_operator_c *symbol) { - prev_il_instruction = symbol; return NULL; } void *narrow_candidate_datatypes_c::visit(RETCN_operator_c *symbol) { - prev_il_instruction = symbol; return NULL; } void *narrow_candidate_datatypes_c::visit(JMP_operator_c *symbol) { - prev_il_instruction = symbol; return NULL; } void *narrow_candidate_datatypes_c::visit(JMPC_operator_c *symbol) { - prev_il_instruction = symbol; return NULL; } void *narrow_candidate_datatypes_c::visit(JMPCN_operator_c *symbol) { - prev_il_instruction = symbol; return NULL; } diff -r bd5998ee8876 -r ff4d26b7e51d stage3/narrow_candidate_datatypes.hh --- a/stage3/narrow_candidate_datatypes.hh Mon Feb 13 17:04:29 2012 +0000 +++ b/stage3/narrow_candidate_datatypes.hh Thu Feb 16 10:27:52 2012 +0000 @@ -39,10 +39,8 @@ class narrow_candidate_datatypes_c: public iterator_visitor_c { private: - symbol_c * selected_datatype; search_varfb_instance_type_c *search_varfb_instance_type; search_base_type_c search_base_type; - symbol_c *case_expression_type; symbol_c *il_operand; symbol_c *prev_il_instruction; @@ -51,6 +49,8 @@ void narrow_function_invocation(symbol_c *f_call, generic_function_call_t fcall_data); void narrow_nonformal_call(symbol_c *f_call, symbol_c *f_decl, int *ext_parm_count = NULL); void narrow_formal_call(symbol_c *f_call, symbol_c *f_decl, int *ext_parm_count = NULL); + + void *handle_il_instruction(symbol_c *symbol); public: narrow_candidate_datatypes_c(symbol_c *ignore); @@ -65,6 +65,7 @@ /* B 1.3.3 - Derived data types */ /********************************/ void *visit(subrange_c *symbol); + void *visit(simple_spec_init_c *symbol); /*********************/ /* B 1.4 - Variables */ @@ -76,6 +77,7 @@ /* B 1.4.2 - Multi-element variables */ /*************************************/ void *visit(array_variable_c *symbol); + void *visit(il_instruction_c *symbol); void *visit(subscript_list_c *symbol); /**************************************/ @@ -106,7 +108,7 @@ /***********************************/ /* B 2.1 Instructions and Operands */ /***********************************/ - // void *visit(instruction_list_c *symbol); + void *visit(instruction_list_c *symbol); void *visit(il_simple_operation_c *symbol); void *visit(il_function_call_c *symbol); void *visit(il_expression_c *symbol); diff -r bd5998ee8876 -r ff4d26b7e51d stage3/print_datatypes_error.cc --- a/stage3/print_datatypes_error.cc Mon Feb 13 17:04:29 2012 +0000 +++ b/stage3/print_datatypes_error.cc Thu Feb 16 10:27:52 2012 +0000 @@ -139,10 +139,10 @@ param_value = fcp_iterator.get_current_value(); /* Find the corresponding parameter in function declaration */ if (NULL == fp_iterator.search(param_name)) { - STAGE3_ERROR(0, fcall, fcall, "Invalid parameter '%s' when invoking %s '%s'", ((identifier_c *)param_name)->value, POU_str, ((identifier_c *)fcall_data.function_name)->value); + STAGE3_ERROR(0, param_name, param_name, "Invalid parameter '%s' when invoking %s '%s'", ((identifier_c *)param_name)->value, POU_str, ((identifier_c *)fcall_data.function_name)->value); } else if (NULL == param_value->datatype) { function_invocation_error = true; - STAGE3_ERROR(0, fcall, fcall, "Data type incompatibility between parameter '%s' and value being passed, when invoking %s '%s'", ((identifier_c *)param_name)->value, POU_str, ((identifier_c *)fcall_data.function_name)->value); + STAGE3_ERROR(0, param_value, param_value, "Data type incompatibility between parameter '%s' and value being passed, when invoking %s '%s'", ((identifier_c *)param_name)->value, POU_str, ((identifier_c *)fcall_data.function_name)->value); } } } @@ -153,7 +153,7 @@ for (int i = 1; (param_value = fcp_iterator.next_nf()) != NULL; i++) { if (NULL == param_value->datatype) { function_invocation_error = true; - STAGE3_ERROR(0, fcall, fcall, "Data type incompatibility for value passed in position %d when invoking %s '%s'", i, POU_str, ((identifier_c *)fcall_data.function_name)->value); + STAGE3_ERROR(0, param_value, param_value, "Data type incompatibility for value passed in position %d when invoking %s '%s'", i, POU_str, ((identifier_c *)fcall_data.function_name)->value); } } } diff -r bd5998ee8876 -r ff4d26b7e51d stage3/print_datatypes_error.hh --- a/stage3/print_datatypes_error.hh Mon Feb 13 17:04:29 2012 +0000 +++ b/stage3/print_datatypes_error.hh Thu Feb 16 10:27:52 2012 +0000 @@ -41,6 +41,7 @@ private: /* The level of detail that the user wants us to display error messages. */ +// #define error_level_default (1) #define error_level_default (1) #define error_level_nagging (4) unsigned int current_display_error_level; diff -r bd5998ee8876 -r ff4d26b7e51d stage3/stage3.cc --- a/stage3/stage3.cc Mon Feb 13 17:04:29 2012 +0000 +++ b/stage3/stage3.cc Thu Feb 16 10:27:52 2012 +0000 @@ -34,23 +34,36 @@ #include "stage3.hh" +#include "flow_control_analysis.hh" #include "fill_candidate_datatypes.hh" #include "narrow_candidate_datatypes.hh" #include "print_datatypes_error.hh" -int type_safety(symbol_c *tree_root){ +static int flow_control_analysis(symbol_c *tree_root){ + flow_control_analysis_c flow_control_analysis(tree_root); + tree_root->accept(flow_control_analysis); + return 0; +} + +/* Type safety analysis assumes that flow control analysis has already been completed, + * so be sure to call flow_control_analysis() before calling this function + */ +static int type_safety(symbol_c *tree_root){ fill_candidate_datatypes_c fill_candidate_datatypes(tree_root); tree_root->accept(fill_candidate_datatypes); narrow_candidate_datatypes_c narrow_candidate_datatypes(tree_root); tree_root->accept(narrow_candidate_datatypes); - print_datatypes_error_c print_datatypes_error(tree_root); + print_datatypes_error_c print_datatypes_error(tree_root); tree_root->accept(print_datatypes_error); if (print_datatypes_error.get_error_found()) return -1; return 0; } + + int stage3(symbol_c *tree_root){ + flow_control_analysis(tree_root); return type_safety(tree_root); } diff -r bd5998ee8876 -r ff4d26b7e51d stage3/stage3.hh --- a/stage3/stage3.hh Mon Feb 13 17:04:29 2012 +0000 +++ b/stage3/stage3.hh Thu Feb 16 10:27:52 2012 +0000 @@ -35,4 +35,4 @@ int stage3(symbol_c *tree_root); -int type_safety(symbol_c *tree_root); +