--- a/absyntax/absyntax.hh Sun Dec 02 18:20:02 2012 +0100
+++ b/absyntax/absyntax.hh Thu Dec 27 15:04:58 2012 +0000
@@ -143,15 +143,15 @@
* having more than one entry filled in!
*/
typedef enum { cs_undefined, /* not defined/not yet evaluated --> const_value is not valid! */
- cs_non_const, /* we have deternmined that expression is not a const value --> const_value is not valid! */
+ cs_non_const, /* we have determined that expression is not a const value --> const_value is not valid! */
cs_const_value, /* const value is valid */
cs_overflow /* result produced overflow or underflow --> const_value is not valid! */
} const_status_t;
- typedef struct {const_status_t status; real64_t value; } const_value_real64_t;
- typedef struct {const_status_t status; int64_t value; } const_value_int64_t;
- typedef struct {const_status_t status; uint64_t value; } const_value_uint64_t;
- typedef struct {const_status_t status; bool value; } const_value_bool_t;
+ typedef struct const_value_real64_s {const_status_t status; real64_t value; const_value_real64_s (): status(cs_undefined), value(0.0) {} } const_value_real64_t;
+ typedef struct const_value_int64_s {const_status_t status; int64_t value; const_value_int64_s (): status(cs_undefined), value(0) {} } const_value_int64_t;
+ typedef struct const_value_uint64_s {const_status_t status; uint64_t value; const_value_uint64_s (): status(cs_undefined), value(0) {} } const_value_uint64_t;
+ typedef struct const_value_bool_s {const_status_t status; bool value; const_value_bool_s (): status(cs_undefined), value(false) {} } const_value_bool_t;
typedef struct {
const_value_real64_t _real64; /* status is initialised to UNDEFINED */
--- a/absyntax_utils/debug_ast.cc Sun Dec 02 18:20:02 2012 +0100
+++ b/absyntax_utils/debug_ast.cc Thu Dec 27 15:04:58 2012 +0000
@@ -190,7 +190,7 @@
void print_ast_c::print(const char *str) {
- fprintf(stderr, str);
+ fprintf(stderr, "%s", str);
}
@@ -209,7 +209,7 @@
void debug_c::print(const char *str) {
- fprintf(stderr, str);
+ fprintf(stderr, "%s", str);
}
void debug_c::print(symbol_c *symbol) {
--- a/absyntax_utils/type_initial_value.cc Sun Dec 02 18:20:02 2012 +0100
+++ b/absyntax_utils/type_initial_value.cc Thu Dec 27 15:04:58 2012 +0000
@@ -81,7 +81,7 @@
* for the DATE data type. Untill we fix our implementation, we use 1970-01-01
* as our default value!!
*/
- date_literal_0 = new date_literal_c(integer_1, integer_1, integer_1);
+//date_literal_0 = new date_literal_c(integer_1, integer_1, integer_1);
date_literal_0 = new date_literal_c(new integer_c("1970"), integer_1, integer_1);
daytime_literal_0 = new daytime_c(integer_0, integer_0, real_0);
time_0 = new duration_c(new time_type_name_c(), NULL, new interval_c(NULL, NULL, NULL, integer_0, NULL)); // T#0s
@@ -98,9 +98,9 @@
-symbol_c *type_initial_value_c::get(identifier_c *type_name) {
+symbol_c *type_initial_value_c::get(symbol_c *type) {
TRACE("type_initial_value_c::get(): called ");
- return (symbol_c *)type_name->accept(*this);
+ return (symbol_c *)type->accept(*type_initial_value_c::instance());
}
--- a/absyntax_utils/type_initial_value.hh Sun Dec 02 18:20:02 2012 +0100
+++ b/absyntax_utils/type_initial_value.hh Thu Dec 27 15:04:58 2012 +0000
@@ -59,8 +59,10 @@
class type_initial_value_c : public null_visitor_c {
+ public:
+ static symbol_c *get(symbol_c *type);
+
private:
- static type_initial_value_c *_instance;
/* constants for the default values of elementary data types... */
static real_c *real_0;
static integer_c *integer_0, *integer_1;
@@ -74,17 +76,12 @@
static single_byte_character_string_c *string_0;
static double_byte_character_string_c *wstring_0;
- public:
- static type_initial_value_c *instance(void);
-
protected:
type_initial_value_c(void);
- public:
- symbol_c *get(identifier_c *type_name);
-
-
private:
+ static type_initial_value_c *_instance;
+ static type_initial_value_c *instance(void);
void *handle_type_spec(symbol_c *base_type_name, symbol_c *type_spec_init);
private:
--- a/main.hh Sun Dec 02 18:20:02 2012 +0100
+++ b/main.hh Thu Dec 27 15:04:58 2012 +0000
@@ -48,8 +48,9 @@
/* Get the definition of INT16_MAX, INT16_MIN, UINT64_MAX, INT64_MAX, INT64_MIN, ... */
-
+#ifndef __STDC_LIMIT_MACROS
#define __STDC_LIMIT_MACROS /* required to have UINTxx_MAX defined when including stdint.h from C++ source code. */
+#endif
#include <stdint.h>
#include <limits>
@@ -124,7 +125,9 @@
* e.g. uint64_t v; printf("value=%"PRIu64" !!\n", v);
* e.g. uint64_t v; printf("value=%"PRIx64" !!\n", v); // hexadecimal format
*/
+#ifndef __STDC_FORMAT_MACROS
#define __STDC_FORMAT_MACROS
+#endif
#include <inttypes.h>
--- a/stage1_2/iec_bison.yy Sun Dec 02 18:20:02 2012 +0100
+++ b/stage1_2/iec_bison.yy Thu Dec 27 15:04:58 2012 +0000
@@ -8265,8 +8265,9 @@
fprintf (stderr, "Out of memory. Bailing out!\n");
return -1;
}
-
- if(parse_file(libfilename) < 0) {
+
+ FILE *libfile = NULL;
+ if((libfile = parse_file(libfilename)) == NULL) {
char *errmsg = strdup2("Error opening library file ", libfilename);
perror(errmsg);
free(errmsg);
@@ -8279,7 +8280,8 @@
full_token_loc = full_token_loc_;
if (yyparse() != 0)
ERROR;
-
+ fclose(libfile);
+
if (yynerrs > 0) {
fprintf (stderr, "\n%d error(s) found in %s. Bailing out!\n", yynerrs /* global variable */, libfilename);
ERROR;
@@ -8299,8 +8301,8 @@
#if YYDEBUG
yydebug = 1;
#endif
-
- if(parse_file(filename) < 0) {
+ FILE *mainfile = NULL;
+ if ((mainfile = parse_file(filename)) == NULL) {
char *errmsg = strdup2("Error opening main file ", filename);
perror(errmsg);
free(errmsg);
@@ -8315,7 +8317,8 @@
fprintf (stderr, "\nParsing failed because of too many consecutive syntax errors. Bailing out!\n");
exit(EXIT_FAILURE);
}
-
+ fclose(mainfile);
+
if (yynerrs > 0) {
fprintf (stderr, "\n%d error(s) found. Bailing out!\n", yynerrs /* global variable */);
exit(EXIT_FAILURE);
--- a/stage1_2/iec_flex.ll Sun Dec 02 18:20:02 2012 +0100
+++ b/stage1_2/iec_flex.ll Thu Dec 27 15:04:58 2012 +0000
@@ -884,17 +884,28 @@
}
-<<EOF>> { /* NOTE: We must not change the value of include_stack_ptr
- * just yet. We must only decrement it if we are NOT
- * at the end of the main file.
- * If we have finished parsing the main file, then we
- * must leave include_stack_ptr at 0, in case the
- * parser is called once again with a new file.
- * (In fact, we currently do just that!)
+<<EOF>> { /* NOTE: Currently bison is incorrectly using END_OF_INPUT in many rules
+ * when checking for syntax errors in the input source code.
+ * This means that in reality flex will be asked to carry on reading the input
+ * even after it has reached the end of all (including the main) input files.
+ * In other owrds, we will be called to return more tokens, even after we have
+ * already returned an END_OF_INPUT token. In this case, we must carry on returning
+ * more END_OF_INPUT tokens.
+ *
+ * However, in the above case we will be asked to carry on reading more tokens
+ * from the main input file, after we have reached the end. For this to work
+ * correctly, we cannot close the main input file!
+ *
+ * This is why we WILL be called with include_stack_ptr == 0 multiple times,
+ * and why we must handle it as a special case
+ * that leaves the include_stack_ptr unchanged, and returns END_OF_INPUT once again.
+ *
+ * As a corollory, flex can never safely close the main input file, and we must ask
+ * bison to close it!
*/
- fclose(yyin);
- free(current_tracking);
if (include_stack_ptr == 0) {
+ // fclose(yyin); // Must not do this!!
+ // free(current_tracking); // Must not do this!!
/* yyterminate() terminates the scanner and returns a 0 to the
* scanner's caller, indicating "all done".
*
@@ -905,6 +916,8 @@
*/
yyterminate();
} else {
+ fclose(yyin);
+ free(current_tracking);
--include_stack_ptr;
yy_delete_buffer(YY_CURRENT_BUFFER);
yy_switch_to_buffer((include_stack[include_stack_ptr]).buffer_state);
@@ -1864,18 +1877,18 @@
/* Tell flex which file to parse. This function will not imediately start parsing the file.
* To parse the file, you then need to call yyparse()
*
- * Returns -1 on error opening the file (and a valid errno), or 0 on success.
- */
-int parse_file(const char *filename) {
+ * Returns NULL on error opening the file (and a valid errno), or 0 on success.
+ * Caller must close the file!
+ */
+FILE *parse_file(const char *filename) {
FILE *filehandle = NULL;
- if((filehandle = fopen(filename, "r")) == NULL)
- return -1;
-
- yyin = filehandle;
- current_filename = strdup(filename);
- current_tracking = GetNewTracking(yyin);
- return 0;
+ if((filehandle = fopen(filename, "r")) != NULL) {
+ yyin = filehandle;
+ current_filename = strdup(filename);
+ current_tracking = GetNewTracking(yyin);
+ }
+ return filehandle;
}
--- a/stage1_2/stage1_2_priv.hh Sun Dec 02 18:20:02 2012 +0100
+++ b/stage1_2/stage1_2_priv.hh Thu Dec 27 15:04:58 2012 +0000
@@ -126,10 +126,10 @@
/* Tell flex which file to parse. This function will not imediately start parsing the file.
* To parse the file, you then need to call yyparse()
*
- * Returns -1 on error opening the file (and a valid errno), or 0 on success.
- */
-int parse_file(const char *filename);
-
+ * Returns NULL on error opening the file (and a valid errno), or 0 on success.
+ * Caller must close the file!
+ */
+FILE *parse_file(const char *filename);
--- a/stage3/constant_folding.cc Sun Dec 02 18:20:02 2012 +0100
+++ b/stage3/constant_folding.cc Thu Dec 27 15:04:58 2012 +0000
@@ -206,8 +206,27 @@
{SET_NONCONST(dtype, symbol);} \
}
-
-
+/* Constant Propagation: Rules for Meet from "Cooper K., Torczon L. - Engineering a Compiler, Second Edition - 2011"
+ * at 9.3 Static Single-Assignment Form page 517
+ * - any * undefined = any
+ * - any * non_const = non_const
+ * - constant * constant = constant (if equal)
+ * - constant * constant = non_const (if not equal)
+ */
+#define COMPUTE_MEET_SEMILATTICE(dtype, c1, c2, resValue) {\
+ if (( c1._##dtype.value != c2._##dtype.value && c2._##dtype.status == symbol_c::cs_const_value &&\
+ c1._##dtype.status == symbol_c::cs_const_value) ||\
+ ( c1._##dtype.status == symbol_c::cs_non_const && c2._##dtype.status == symbol_c::cs_const_value ) ||\
+ ( c2._##dtype.status == symbol_c::cs_non_const && c1._##dtype.status == symbol_c::cs_const_value )) {\
+ resValue._##dtype.status = symbol_c::cs_non_const;\
+ } else {\
+ resValue._##dtype.status = symbol_c::cs_const_value;\
+ resValue._##dtype.value = c1._##dtype.value;\
+ }\
+}
+
+
+static std::map <std::string, symbol_c::const_value_t> values;
/***********************************************************************/
@@ -916,6 +935,37 @@
return NULL;
}
+/*********************/
+/* B 1.4 - Variables */
+/*********************/
+void *constant_folding_c::visit(symbolic_variable_c *symbol) {
+ std::string varName;
+
+ varName = convert.toString(symbol->var_name);
+ if (values.count(varName) > 0) {
+ symbol->const_value = values[varName];
+ }
+ return NULL;
+}
+
+/**********************/
+/* B 1.5.3 - Programs */
+/**********************/
+void *constant_folding_c::visit(program_declaration_c *symbol) {
+ symbol_c *var_name;
+
+ values.clear(); /* Clear global map */
+ search_var_instance_decl_c search_var_instance_decl(symbol);
+ function_param_iterator_c fpi(symbol);
+ while((var_name = fpi.next()) != NULL) {
+ std::string varName = convert.toString(var_name);
+ symbol_c *varDecl = search_var_instance_decl.get_decl(var_name);
+ values[varName] = varDecl->const_value;
+ }
+ /* Add all variables declared into Values map and put them to initial value */
+ symbol->function_block_body->accept(*this);
+ return NULL;
+}
/****************************************/
@@ -1185,3 +1235,60 @@
/* TODO: handle function invocations... */
// void *fill_candidate_datatypes_c::visit(function_invocation_c *symbol) {}
+
+
+
+
+/*********************************/
+/* B 3.2.1 Assignment Statements */
+/*********************************/
+void *constant_folding_c::visit(assignment_statement_c *symbol) {
+ std::string varName;
+
+ symbol->r_exp->accept(*this);
+ symbol->l_exp->const_value = symbol->r_exp->const_value;
+ varName = convert.toString(symbol->l_exp);
+ values[varName] = symbol->l_exp->const_value;
+ return NULL;
+}
+
+/********************************/
+/* B 3.2.3 Selection Statements */
+/********************************/
+void *constant_folding_c::visit(if_statement_c *symbol) {
+ std::map <std::string, symbol_c::const_value_t> values_incoming;
+ std::map <std::string, symbol_c::const_value_t> values_statement_result;
+ std::map <std::string, symbol_c::const_value_t> values_elsestatement_result;
+ std::map <std::string, symbol_c::const_value_t>::iterator itr;
+ values_incoming = values; /* save incoming status */
+
+ symbol->statement_list->accept(*this);
+ values_statement_result = values;
+ if (NULL != symbol->else_statement_list) {
+ values = values_incoming;
+ symbol->else_statement_list->accept(*this);
+ values_elsestatement_result = values;
+ } else
+ values_elsestatement_result = values_incoming;
+ values.clear();
+ itr = values_statement_result.begin();
+ for ( ; itr != values_statement_result.end(); ++itr) {
+ std::string name = itr->first;
+ symbol_c::const_value_t value;
+
+ if (values_elsestatement_result.count(name) > 0) {
+ symbol_c::const_value_t c1 = itr->second;
+ symbol_c::const_value_t c2 = values_elsestatement_result[name];
+ COMPUTE_MEET_SEMILATTICE (real64, c1, c2, value);
+ COMPUTE_MEET_SEMILATTICE (uint64, c1, c2, value);
+ COMPUTE_MEET_SEMILATTICE ( int64, c1, c2, value);
+ COMPUTE_MEET_SEMILATTICE ( bool, c1, c2, value);
+ } else
+ value = values_statement_result[name];
+ values[name] = value;
+ }
+ return NULL;
+}
+
+
+
--- a/stage3/constant_folding.hh Sun Dec 02 18:20:02 2012 +0100
+++ b/stage3/constant_folding.hh Thu Dec 27 15:04:58 2012 +0000
@@ -43,9 +43,31 @@
#include "../absyntax_utils/absyntax_utils.hh"
+class convert_c : public iterator_visitor_c {
+ std::string text;
+
+public:
+ convert_c(symbol_c *symbol = NULL) {
+ text = "";
+ }
+
+ std::string toString(symbol_c *symbol) {
+ symbol->accept(*this);
+ return text;
+ }
+
+ void *visit(identifier_c *symbol) {
+ text = symbol->value;
+ return NULL;
+ }
+
+ void *visit(symbolic_variable_c *symbol) {
+ symbol->var_name->accept(*this);
+ return NULL;
+ }
+};
class constant_folding_c : public iterator_visitor_c {
- private:
search_varfb_instance_type_c *search_varfb_instance_type;
int error_count;
bool warning_found;
@@ -54,6 +76,7 @@
symbol_c *prev_il_instruction;
/* the current IL operand being analyzed */
symbol_c *il_operand;
+ convert_c convert;
public:
constant_folding_c(symbol_c *symbol = NULL);
@@ -86,6 +109,16 @@
/********* **************/
void *visit(fixed_point_c *symbol);
+ /*********************/
+ /* B 1.4 - Variables */
+ /*********************/
+ void *visit(symbolic_variable_c *symbol);
+
+ /**********************/
+ /* B 1.5.3 - Programs */
+ /**********************/
+ void *visit(program_declaration_c *symbol);
+
/****************************************/
/* B.2 - Language IL (Instruction List) */
/****************************************/
@@ -178,6 +211,16 @@
void *visit( neg_expression_c *symbol);
void *visit( not_expression_c *symbol);
//void *visit(function_invocation_c *symbol); /* TODO */
+
+ /*********************************/
+ /* B 3.2.1 Assignment Statements */
+ /*********************************/
+ void *visit(assignment_statement_c *symbol);
+
+ /********************************/
+ /* B 3.2.3 Selection Statements */
+ /********************************/
+ void *visit(if_statement_c *symbol);
};
--- a/stage4/generate_c/generate_c.cc Sun Dec 02 18:20:02 2012 +0100
+++ b/stage4/generate_c/generate_c.cc Thu Dec 27 15:04:58 2012 +0000
@@ -1124,7 +1124,7 @@
s4o.print(" = ");
{
/* get the default value of this variable's type */
- symbol_c *default_value = (symbol_c *)symbol->type_name->accept(*type_initial_value_c::instance());
+ symbol_c *default_value = type_initial_value_c::get(symbol->type_name);
if (default_value == NULL) ERROR;
initialization_analyzer_c initialization_analyzer(default_value);
switch (initialization_analyzer.get_initialization_type()) {
--- a/stage4/generate_c/generate_c_il.cc Sun Dec 02 18:20:02 2012 +0100
+++ b/stage4/generate_c/generate_c_il.cc Thu Dec 27 15:04:58 2012 +0000
@@ -903,7 +903,7 @@
s4o.print(",\n"+s4o.indent_spaces);
if (param_value == NULL) {
/* If not, get the default value of this variable's type */
- param_value = (symbol_c *)current_param_type->accept(*type_initial_value_c::instance());
+ param_value = type_initial_value_c::get(current_param_type);
}
if (param_value == NULL) ERROR;
s4o.print("(");
@@ -1292,7 +1292,7 @@
s4o.print(",\n"+s4o.indent_spaces);
if (param_value == NULL) {
/* If not, get the default value of this variable's type */
- param_value = (symbol_c *)current_param_type->accept(*type_initial_value_c::instance());
+ param_value = type_initial_value_c::get(current_param_type);
}
if (param_value == NULL) ERROR;
s4o.print("(");
--- a/stage4/generate_c/generate_c_st.cc Sun Dec 02 18:20:02 2012 +0100
+++ b/stage4/generate_c/generate_c_st.cc Thu Dec 27 15:04:58 2012 +0000
@@ -752,7 +752,7 @@
s4o.print(",\n"+s4o.indent_spaces);
if (param_value == NULL) {
/* If not, get the default value of this variable's type */
- param_value = (symbol_c *)current_param_type->accept(*type_initial_value_c::instance());
+ param_value = type_initial_value_c::get(current_param_type);
}
if (param_value == NULL) ERROR;
s4o.print("(");
--- a/stage4/generate_c/generate_c_vardecl.cc Sun Dec 02 18:20:02 2012 +0100
+++ b/stage4/generate_c/generate_c_vardecl.cc Thu Dec 27 15:04:58 2012 +0000
@@ -195,7 +195,7 @@
case arraysize_am:
symbol->array_subrange_list->accept(*this);
array_base_type = symbol->non_generic_type_name;
- array_default_value = (symbol_c *)symbol->non_generic_type_name->accept(*type_initial_value_c::instance());;
+ array_default_value = type_initial_value_c::get(symbol->non_generic_type_name);
if (array_default_value == NULL) ERROR;
break;
case typedecl_am:
@@ -618,7 +618,7 @@
if (current_element_type == NULL) ERROR;
/* If not, get the default value of this variable's type */
- element_value = (symbol_c *)current_element_type->accept(*type_initial_value_c::instance());
+ element_value = type_initial_value_c::get(current_element_type);
}
if (element_value == NULL) ERROR;
@@ -878,7 +878,7 @@
ERROR;
if (NULL == this->current_var_init_symbol) {
/* We try to find the data type's default value... */
- this->current_var_init_symbol = (symbol_c *)this->current_var_type_symbol->accept(*type_initial_value_c::instance());
+ this->current_var_init_symbol = type_initial_value_c::get(this->current_var_type_symbol);
/* Note that Function Block 'data types' do not have a default value, so we cannot abort if no default value is found! */
/*
if (NULL == this->current_var_init_symbol)