msousa@443: /* msousa@443: * matiec - a compiler for the programming languages defined in IEC 61131-3 msousa@443: * msousa@443: * Copyright (C) 2012 Mario de Sousa (msousa@fe.up.pt) msousa@443: * msousa@443: * This program is free software: you can redistribute it and/or modify msousa@443: * it under the terms of the GNU General Public License as published by msousa@443: * the Free Software Foundation, either version 3 of the License, or msousa@443: * (at your option) any later version. msousa@443: * msousa@443: * This program is distributed in the hope that it will be useful, msousa@443: * but WITHOUT ANY WARRANTY; without even the implied warranty of msousa@443: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the msousa@443: * GNU General Public License for more details. msousa@443: * msousa@443: * You should have received a copy of the GNU General Public License msousa@443: * along with this program. If not, see . msousa@443: * msousa@443: * msousa@443: * This code is made available on the understanding that it will not be msousa@443: * used in safety-critical situations without a full and competent review. msousa@443: */ msousa@443: msousa@443: /* msousa@443: * An IEC 61131-3 compiler. msousa@443: * msousa@443: * Based on the msousa@443: * FINAL DRAFT - IEC 61131-3, 2nd Ed. (2001-12-10) msousa@443: * msousa@443: */ msousa@443: msousa@443: msousa@443: /* msousa@443: * Do flow control analysis of the IEC 61131-3 code. msousa@443: * msousa@443: * We currently only do this for IL code. msousa@443: * This class will annotate the abstract syntax tree, by filling in the msousa@443: * prev_il_instruction variable in the il_instruction_c, so it points to msousa@443: * the previous il_instruction_c object in the instruction list instruction_list_c. msousa@443: */ msousa@443: msousa@443: #include "flow_control_analysis.hh" msousa@443: msousa@443: msousa@443: msousa@443: /* set to 1 to see debug info during execution */ msousa@443: static int debug = 0; msousa@443: msousa@443: flow_control_analysis_c::flow_control_analysis_c(symbol_c *ignore) { msousa@443: } msousa@443: msousa@443: flow_control_analysis_c::~flow_control_analysis_c(void) { msousa@443: } msousa@443: msousa@443: msousa@443: msousa@443: /************************************/ msousa@443: /* B 1.5 Program organization units */ msousa@443: /************************************/ msousa@443: /*********************/ msousa@443: /* B 1.5.1 Functions */ msousa@443: /*********************/ msousa@443: void *flow_control_analysis_c::visit(function_declaration_c *symbol) { msousa@443: search_varfb_instance_type = new search_varfb_instance_type_c(symbol); msousa@443: if (debug) printf("Doing flow control analysis in body of function %s\n", ((token_c *)(symbol->derived_function_name))->value); msousa@443: symbol->function_body->accept(*this); msousa@443: delete search_varfb_instance_type; msousa@443: search_varfb_instance_type = NULL; msousa@443: return NULL; msousa@443: } msousa@443: msousa@443: /***************************/ msousa@443: /* B 1.5.2 Function blocks */ msousa@443: /***************************/ msousa@443: void *flow_control_analysis_c::visit(function_block_declaration_c *symbol) { msousa@443: search_varfb_instance_type = new search_varfb_instance_type_c(symbol); msousa@443: if (debug) printf("Doing flow control analysis in body of FB %s\n", ((token_c *)(symbol->fblock_name))->value); msousa@443: symbol->fblock_body->accept(*this); msousa@443: delete search_varfb_instance_type; msousa@443: search_varfb_instance_type = NULL; msousa@443: return NULL; msousa@443: } msousa@443: msousa@443: /********************/ msousa@443: /* B 1.5.3 Programs */ msousa@443: /********************/ msousa@443: void *flow_control_analysis_c::visit(program_declaration_c *symbol) { msousa@443: search_varfb_instance_type = new search_varfb_instance_type_c(symbol); msousa@443: if (debug) printf("Doing flow control analysis in body of program %s\n", ((token_c *)(symbol->program_type_name))->value); msousa@443: symbol->function_block_body->accept(*this); msousa@443: delete search_varfb_instance_type; msousa@443: search_varfb_instance_type = NULL; msousa@443: return NULL; msousa@443: } msousa@443: msousa@443: msousa@443: /********************************/ msousa@443: /* B 1.7 Configuration elements */ msousa@443: /********************************/ msousa@443: void *flow_control_analysis_c::visit(configuration_declaration_c *symbol) { msousa@443: return NULL; msousa@443: } msousa@443: msousa@443: msousa@443: /****************************************/ msousa@443: /* B.2 - Language IL (Instruction List) */ msousa@443: /****************************************/ msousa@443: /***********************************/ msousa@443: /* B 2.1 Instructions and Operands */ msousa@443: /***********************************/ msousa@443: msousa@443: /*| instruction_list il_instruction */ msousa@443: // SYM_LIST(instruction_list_c) msousa@443: void *flow_control_analysis_c::visit(instruction_list_c *symbol) { msousa@443: for(int i = 1; i < symbol->n; i++) { msousa@443: prev_il_instruction = symbol->elements[i-1]; msousa@443: symbol->elements[i]->accept(*this); msousa@443: } msousa@443: return NULL; msousa@443: } msousa@443: msousa@443: /* | label ':' [il_incomplete_instruction] eol_list */ msousa@443: // SYM_REF2(il_instruction_c, label, il_instruction) msousa@443: // void *visit(instruction_list_c *symbol); msousa@443: void *flow_control_analysis_c::visit(il_instruction_c *symbol) { msousa@443: symbol->prev_il_instruction = prev_il_instruction; msousa@443: /* TODO: handle labels correctly! msousa@443: * msousa@443: * Don't forget to handle multiple consecutive lables too! msousa@443: * label2: msousa@443: * label3: msousa@443: * label4: msousa@443: * LD I msousa@443: */ msousa@443: msousa@443: return NULL; msousa@443: } msousa@443: msousa@443: msousa@443: #if 0 msousa@443: /* | function_name [il_operand_list] */ msousa@443: /* NOTE: The parameters 'called_function_declaration' and 'extensible_param_count' are used to pass data between the stage 3 and stage 4. */ msousa@443: // SYM_REF2(il_function_call_c, function_name, il_operand_list, symbol_c *called_function_declaration; int extensible_param_count;) msousa@443: void *flow_control_analysis_c::visit(il_function_call_c *symbol) { msousa@443: return NULL; msousa@443: } msousa@443: msousa@443: /* | il_expr_operator '(' [il_operand] eol_list [simple_instr_list] ')' */ msousa@443: // SYM_REF3(il_expression_c, il_expr_operator, il_operand, simple_instr_list); msousa@443: void *flow_control_analysis_c::visit(il_expression_c *symbol) { msousa@443: return NULL; msousa@443: } msousa@443: msousa@443: /* il_call_operator prev_declared_fb_name msousa@443: * | il_call_operator prev_declared_fb_name '(' ')' msousa@443: * | il_call_operator prev_declared_fb_name '(' eol_list ')' msousa@443: * | il_call_operator prev_declared_fb_name '(' il_operand_list ')' msousa@443: * | il_call_operator prev_declared_fb_name '(' eol_list il_param_list ')' msousa@443: */ msousa@443: /* 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 */ msousa@443: // SYM_REF4(il_fb_call_c, il_call_operator, fb_name, il_operand_list, il_param_list, symbol_c *called_fb_declaration) msousa@443: void *flow_control_analysis_c::visit(il_fb_call_c *symbol) { msousa@443: return NULL; msousa@443: } msousa@443: msousa@443: msousa@443: /* | function_name '(' eol_list [il_param_list] ')' */ msousa@443: /* NOTE: The parameter 'called_function_declaration' is used to pass data between the stage 3 and stage 4. */ msousa@443: // SYM_REF2(il_formal_funct_call_c, function_name, il_param_list, symbol_c *called_function_declaration; int extensible_param_count;) msousa@443: void *flow_control_analysis_c::visit(il_formal_funct_call_c *symbol) { msousa@443: return NULL; msousa@443: } msousa@443: msousa@443: msousa@443: /* msousa@443: void *visit(il_operand_list_c *symbol); msousa@443: void *visit(simple_instr_list_c *symbol); msousa@443: void *visit(il_param_list_c *symbol); msousa@443: void *visit(il_param_assignment_c *symbol); msousa@443: void *visit(il_param_out_assignment_c *symbol); msousa@443: */ msousa@443: msousa@443: msousa@443: #endif msousa@443: