stage3/constant_folding.cc
changeset 569 0d1ab9e78574
parent 568 5f79478142d7
child 570 cb704eca7e37
equal deleted inserted replaced
568:5f79478142d7 569:0d1ab9e78574
    29  * FINAL DRAFT - IEC 61131-3, 2nd Ed. (2001-12-10)
    29  * FINAL DRAFT - IEC 61131-3, 2nd Ed. (2001-12-10)
    30  *
    30  *
    31  */
    31  */
    32 
    32 
    33 
    33 
    34 /* Determine the value of an ST expression.
    34 /* Do constant folding...
    35  * Filling in all symbols the correct value.
    35  *
       
    36  * I.e., Determine the value of all expressions in which only constant values (i.e. literals) are used.
       
    37  * The (constant) result of each operation is stored (annotated) in the respective operation symbol 
       
    38  * (e.g.: add_expression_c) in the abstract syntax tree,
    36  *
    39  *
    37  * For example:
    40  * For example:
    38  *       2 + 3         -> returns constant_value_integer = 5
    41  *       2 + 3         -> the constant value '5'    is stored in the add_expression_c symbol.
    39  *       22.2 - 5.0    -> returns constant_value_real    = 17.2
    42  *       22.2 - 5.0    -> the constant value '17.2' is stored in the add_expression_c symbol.
    40  *       etc...
    43  *       etc...
       
    44  *
       
    45  *
       
    46  * NOTE 1 that some operations and constants can have multiple data types. For example,
       
    47  *        1 AND 0
       
    48  *      may be either a BOOL, BYTE, WORD or LWORD.
       
    49  *
       
    50  *      The same happens with 
       
    51  *        1 + 2
       
    52  *      which may be signed (e.g. INT) or unsigned (UINT)
       
    53  *
       
    54  *      For the above reason, instead of storing a single constant value, we actually store 4:
       
    55  *        - bool
       
    56  *        - uint64
       
    57  *        -  int64
       
    58  *        - real64
       
    59  *
       
    60  *      Additionally, since the result of an operation may result in an overflow, we actually
       
    61  *      store the result inside a struct (defined in absyntax.hh)
       
    62  *
       
    63  *             ** During stage 3 (semantic analysis/checking) we will be doing constant folding.
       
    64  *              * That algorithm will anotate the abstract syntax tree with the result of operations
       
    65  *              * on literals (i.e. 44 + 55 will store the result 99).
       
    66  *              * Since the same source code (e.g. 1 + 0) may actually be a BOOL or an ANY_INT,
       
    67  *              * or an ANY_BIT, we need to handle all possibilities, and determine the result of the
       
    68  *              * operation assuming each type.
       
    69  *              * For this reason, we have one entry for each possible type, with some expressions
       
    70  *              * having more than one entry filled in!
       
    71  *              **
       
    72  *             typedef enum { cs_undefined,   // not defined --> const_value is not valid!
       
    73  *                            cs_const_value, // const value is valid
       
    74  *                            cs_overflow     // result produced overflow or underflow --> const_value is not valid!
       
    75  *                          } const_status_t;
       
    76  *    
       
    77  *             typedef struct {
       
    78  *                 const_status_t status;
       
    79  *                 real64_t       value; 
       
    80  *             } const_value_real64_t;
       
    81  *             const_value_real64_t *const_value_real64; // when NULL --> UNDEFINED
       
    82  *             
       
    83  *             typedef struct {
       
    84  *                 const_status_t status;
       
    85  *                 int64_t        value; 
       
    86  *             } const_value_int64_t;
       
    87  *             const_value_int64_t *const_value_int64; // when NULL --> UNDEFINED
       
    88  *             
       
    89  *             typedef struct {
       
    90  *                 const_status_t status;
       
    91  *                 uint64_t       value; 
       
    92  *             } const_value_uint64_t;
       
    93  *             const_value_uint64_t *const_value_uint64; // when NULL --> UNDEFINED
       
    94  *             
       
    95  *             typedef struct {
       
    96  *                 const_status_t status;
       
    97  *                 bool           value; 
       
    98  *             } const_value_bool_t;
       
    99  *             const_value_bool_t *const_value_bool; // when NULL --> UNDEFINED
       
   100  *
       
   101  *
       
   102  *
       
   103  * NOTE 2 
       
   104  *    This file does not print out any error messages!
       
   105  *    We cannot really print out error messages when we find an overflow. Since each operation
       
   106  *    (symbol in the absract syntax tree for that operation) will have up to 4 constant results,
       
   107  *    it may happen that some of them overflow, while other do not.
       
   108  *    We must wait for data type checking to determine the exact data type of each expression
       
   109  *    before we can decide whether or not we should print out an overflow error message.
       
   110  *
       
   111  *    For this reason, this visitor merely annotates the abstract syntax tree, and leaves the
       
   112  `    actuall printing of errors for the print_datatype_errors_c class!
    41  */
   113  */
    42 
   114 
    43 #include "constant_folding.hh"
   115 #include "constant_folding.hh"
    44 #include <typeinfo>
   116 #include <typeinfo>
    45 #include <limits>
   117 #include <limits>
    74 }
   146 }
    75 
   147 
    76 
   148 
    77 
   149 
    78 
   150 
    79 #define MALLOC(variable, data_type) \
   151 
    80  variable = (data_type *)malloc(sizeof(data_type)); \
   152 
    81  if (variable == NULL) ERROR;
   153 
    82 
   154 
    83 
   155 
    84 #define DO_OPER(dtype)\
   156 
    85     (NULL != symbol->r_exp->const_value_##dtype ) && \
   157 
    86     (NULL != symbol->l_exp->const_value_##dtype )
   158 
    87 
   159 #define NEW_CVALUE(dtype, symbol) \
    88 
   160  (symbol->const_value_##dtype) = new(symbol_c::const_value_##dtype##_t); \
    89 #define CHECK_OVERFLOW_SUM(a, b, type)\
   161  if ((symbol->const_value_##dtype) == NULL) ERROR; \
    90 	((((std::numeric_limits< type >::max() - a) < (b)) ? 1 : 0) || \
   162  (symbol->const_value_##dtype)->status = symbol_c::cs_undefined;
    91 	 (((std::numeric_limits< type >::min() + a) > (b)) ? 1 : 0))
   163 
    92 
   164 #define SET_CVALUE(dtype, symbol, new_value)  ((symbol)->const_value_##dtype->value) = new_value; ((symbol)->const_value_##dtype->status) = symbol_c::cs_const_value;  
    93 #define CHECK_OVERFLOW_SUB(a, b, type)\
   165 #define GET_CVALUE(dtype, symbol)             ((symbol)->const_value_##dtype->value) 
    94 	((((std::numeric_limits< type >::max() - a) < (-b)) ? 1 : 0) || \
   166 #define SET_OVFLOW(dtype, symbol)             ((symbol)->const_value_##dtype->status) = symbol_c::cs_overflow
    95 	 (((std::numeric_limits< type >::min() + a) > (-b)) ? 1 : 0))
   167     /* The following test is correct in the presence of a NULL pointer, as the logical evaluation will be suspended as soon as the first condition is false! */
    96 
   168 #define VALID_CVALUE(dtype, symbol)           ((NULL != (symbol)->const_value_##dtype) && (symbol_c::cs_const_value == (symbol)->const_value_##dtype->status))
    97 #define SYMBOL_BOOL_VALUE (symbol->exp->const_value_bool)
   169 #define ISZERO_CVALUE(dtype, symbol)          ((VALID_CVALUE(dtype, symbol)) && (GET_CVALUE(dtype, symbol) == 0))
    98 #define SYMBOL_REAL_VALUE (symbol->exp->const_value_real)
   170 #define DO_BIN_OPER(dtype, oper)\
       
   171 	if (VALID_CVALUE(dtype, symbol->r_exp) && VALID_CVALUE(dtype, symbol->l_exp)) {                                \
       
   172 		NEW_CVALUE(dtype, symbol);                                                                             \
       
   173 		SET_CVALUE(dtype, symbol, GET_CVALUE(dtype, symbol->l_exp) oper GET_CVALUE(dtype, symbol->r_exp));     \
       
   174 	}
       
   175 
    99 
   176 
   100 
   177 
   101 
   178 
   102 
   179 
   103 constant_folding_c::constant_folding_c(symbol_c *symbol) {
   180 constant_folding_c::constant_folding_c(symbol_c *symbol) {
   108     /* check whether the platform on which the compiler is being run implements IEC 559 floating point data types. */
   185     /* check whether the platform on which the compiler is being run implements IEC 559 floating point data types. */
   109     symbol_c null_symbol;
   186     symbol_c null_symbol;
   110     if (! (std::numeric_limits<real64_t>::is_iec559) )
   187     if (! (std::numeric_limits<real64_t>::is_iec559) )
   111         STAGE3_WARNING(&null_symbol, &null_symbol, "The platform running the compiler does not implement IEC 559 floating point numbers. "
   188         STAGE3_WARNING(&null_symbol, &null_symbol, "The platform running the compiler does not implement IEC 559 floating point numbers. "
   112                                                    "Any error and/or warning messages related to overflow/underflow of the result of operations on REAL/LREAL literals "
   189                                                    "Any error and/or warning messages related to overflow/underflow of the result of operations on REAL/LREAL literals "
   113                                                    " (i.e. constant folding) may themselves be erroneous, although are most probably correct");
   190                                                    " (i.e. constant folding) may themselves be erroneous, although are most probably correct.");
   114 }
   191 }
   115 
   192 
   116 
   193 
   117 constant_folding_c::~constant_folding_c(void) {
   194 constant_folding_c::~constant_folding_c(void) {
   118 }
   195 }
   128 /*********************/
   205 /*********************/
   129 /******************************/
   206 /******************************/
   130 /* B 1.2.1 - Numeric Literals */
   207 /* B 1.2.1 - Numeric Literals */
   131 /******************************/
   208 /******************************/
   132 void *constant_folding_c::visit(real_c *symbol) {
   209 void *constant_folding_c::visit(real_c *symbol) {
   133 	MALLOC(symbol->const_value_real, real64_t);
   210 	NEW_CVALUE(real64, symbol);
   134 	*symbol->const_value_real = extract_real_value(symbol);
   211 	SET_CVALUE(real64, symbol, extract_real_value(symbol));
   135 
       
   136 	return NULL;
   212 	return NULL;
   137 }
   213 }
   138 
   214 
   139 
   215 
   140 void *constant_folding_c::visit(integer_c *symbol) {
   216 void *constant_folding_c::visit(integer_c *symbol) {
   141 	int64_t *integer_value;
   217 	NEW_CVALUE( int64, symbol);
   142 
   218 	SET_CVALUE( int64, symbol, extract_integer_value(symbol));
   143 	integer_value = (int64_t *)malloc(sizeof(int64_t));
   219 	NEW_CVALUE(uint64, symbol);
   144 	*integer_value = extract_integer_value(symbol);
   220 	SET_CVALUE(uint64, symbol, extract_integer_value(symbol));
   145 	symbol->const_value_integer = integer_value;
       
   146 
       
   147 	return NULL;
   221 	return NULL;
   148 }
   222 }
   149 
   223 
   150 
   224 
   151 void *constant_folding_c::visit(neg_real_c *symbol) {
   225 void *constant_folding_c::visit(neg_real_c *symbol) {
   152 	symbol->exp->accept(*this);
   226 	symbol->exp->accept(*this);
   153 	if (NULL == symbol->exp->const_value_real)
   227 	if (!VALID_CVALUE(real64, symbol->exp))
   154 		ERROR;
   228 		return NULL;
   155 	symbol->const_value_real = (real64_t*) malloc(sizeof(real64_t));
   229 	NEW_CVALUE(real64, symbol);
   156 	*symbol->const_value_real = - *(symbol->exp->const_value_real);
   230 	SET_CVALUE(real64, symbol, - GET_CVALUE( real64, symbol->exp));
   157 	return NULL;
   231 	return NULL;
   158 }
   232 }
   159 
   233 
   160 
   234 /* | '-' integer	{$$ = new neg_integer_c($2, locloc(@$));} */
   161 void *constant_folding_c::visit(neg_integer_c *symbol) {
   235 void *constant_folding_c::visit(neg_integer_c *symbol) {
   162 	int64_t *integer_value;
   236 	symbol->exp->accept(*this);
   163 
   237 	if (VALID_CVALUE(int64, symbol->exp)) {
   164 	integer_value = (int64_t *)malloc(sizeof(int64_t));
   238 		NEW_CVALUE( int64, symbol);
   165 	*integer_value = extract_integer_value(symbol);
   239 		SET_CVALUE( int64, symbol, - GET_CVALUE( int64, symbol->exp));
   166 	symbol->const_value_integer = integer_value;
   240 	}
   167 
       
   168 	return NULL;
   241 	return NULL;
   169 }
   242 }
   170 
   243 
   171 
   244 
   172 void *constant_folding_c::visit(binary_integer_c *symbol) {
   245 void *constant_folding_c::visit(binary_integer_c *symbol) {
   173 
       
   174 	return NULL;
   246 	return NULL;
   175 }
   247 }
   176 
   248 
   177 
   249 
   178 void *constant_folding_c::visit(octal_integer_c *symbol) {
   250 void *constant_folding_c::visit(octal_integer_c *symbol) {
   179 
       
   180 	return NULL;
   251 	return NULL;
   181 }
   252 }
   182 
   253 
   183 
   254 
   184 void *constant_folding_c::visit(hex_integer_c *symbol) {
   255 void *constant_folding_c::visit(hex_integer_c *symbol) {
   185 	symbol->const_value_integer = (int64_t*) malloc(sizeof(int64_t));
   256 	NEW_CVALUE( int64, symbol);
   186 	*(symbol->const_value_integer) = extract_hex_value(symbol);
   257 	SET_CVALUE( int64, symbol, extract_hex_value(symbol));
   187 
   258 	NEW_CVALUE(uint64, symbol);
   188 	return NULL;
   259 	SET_CVALUE(uint64, symbol, extract_hex_value(symbol));
   189 }
   260 	return NULL;
   190 
   261 }
   191 
   262 
       
   263 
       
   264 /*
       
   265 integer_literal:
       
   266   integer_type_name '#' signed_integer	{$$ = new integer_literal_c($1, $3, locloc(@$));}
       
   267 | integer_type_name '#' binary_integer	{$$ = new integer_literal_c($1, $3, locloc(@$));}
       
   268 | integer_type_name '#' octal_integer	{$$ = new integer_literal_c($1, $3, locloc(@$));}
       
   269 | integer_type_name '#' hex_integer	{$$ = new integer_literal_c($1, $3, locloc(@$));}
       
   270 */
       
   271 // SYM_REF2(integer_literal_c, type, value)
   192 void *constant_folding_c::visit(integer_literal_c *symbol) {
   272 void *constant_folding_c::visit(integer_literal_c *symbol) {
   193 	symbol->value->accept(*this);
   273 	symbol->value->accept(*this);
   194 	if (NULL == symbol->value->const_value_integer) ERROR;
   274 	if (VALID_CVALUE( int64, symbol->value)) {
   195 	symbol->const_value_integer = (int64_t*) malloc(sizeof(int64_t));
   275 		NEW_CVALUE( int64, symbol);
   196 	*(symbol->const_value_integer) = *(symbol->value->const_value_integer);
   276 		SET_CVALUE( int64, symbol, GET_CVALUE( int64, symbol->value));
   197 
   277 	}
       
   278 	if (VALID_CVALUE(uint64, symbol->value)) {
       
   279 		NEW_CVALUE(uint64, symbol);
       
   280 		SET_CVALUE(uint64, symbol, GET_CVALUE(uint64, symbol->value));
       
   281 	}
   198 	return NULL;
   282 	return NULL;
   199 }
   283 }
   200 
   284 
   201 
   285 
   202 void *constant_folding_c::visit(real_literal_c *symbol) {
   286 void *constant_folding_c::visit(real_literal_c *symbol) {
   203 	symbol->value->accept(*this);
   287 	symbol->value->accept(*this);
   204 	if (NULL == symbol->value->const_value_real) ERROR;
   288 	if (VALID_CVALUE(real64, symbol->value)) {
   205 	symbol->const_value_real = (real64_t*) malloc(sizeof(real64_t));
   289 		NEW_CVALUE(real64, symbol);
   206 	*symbol->const_value_real =  *(symbol->value->const_value_real);
   290 		SET_CVALUE(real64, symbol,  GET_CVALUE(real64, symbol->value));
   207 
   291 	}
   208 	return NULL;
   292 	return NULL;
   209 }
   293 }
   210 
   294 
   211 
   295 
   212 void *constant_folding_c::visit(bit_string_literal_c *symbol) {
   296 void *constant_folding_c::visit(bit_string_literal_c *symbol) {
   213 
       
   214 	return NULL;
   297 	return NULL;
   215 }
   298 }
   216 
   299 
   217 
   300 
   218 void *constant_folding_c::visit(boolean_literal_c *symbol) {
   301 void *constant_folding_c::visit(boolean_literal_c *symbol) {
   219 	symbol->value->accept(*this);
   302 	symbol->value->accept(*this);
   220 	if (NULL == symbol->value->const_value_bool) ERROR;
   303 	if (VALID_CVALUE(bool, symbol->value)) {
   221 	symbol->const_value_bool = (bool *)malloc(sizeof(bool));
   304 		NEW_CVALUE(bool, symbol);
   222 	*(symbol->const_value_bool) = *(symbol->value->const_value_bool);
   305 		SET_CVALUE(bool, symbol,  GET_CVALUE(  bool, symbol->value));
   223 
   306 	}
   224 	return NULL;
   307 	return NULL;
   225 }
   308 }
   226 
   309 
   227 
   310 
   228 void *constant_folding_c::visit(boolean_true_c *symbol) {
   311 void *constant_folding_c::visit(boolean_true_c *symbol) {
   229 	symbol->const_value_bool = (bool *)malloc(sizeof(bool));
   312 	NEW_CVALUE(bool, symbol);
   230 	*(symbol->const_value_bool) = true;
   313 	SET_CVALUE(bool, symbol, true);
   231 
       
   232 	return NULL;
   314 	return NULL;
   233 }
   315 }
   234 
   316 
   235 
   317 
   236 void *constant_folding_c::visit(boolean_false_c *symbol) {
   318 void *constant_folding_c::visit(boolean_false_c *symbol) {
   237 	symbol->const_value_bool = (bool *)malloc(sizeof(bool));
   319 	NEW_CVALUE(bool, symbol);
   238 	*(symbol->const_value_bool) = false;
   320 	SET_CVALUE(bool, symbol, false);
   239 
   321 	return NULL;
   240 	return NULL;
   322 }
   241 }
       
   242 
       
   243 
   323 
   244 
   324 
   245 /***************************************/
   325 /***************************************/
   246 /* B.3 - Language ST (Structured Text) */
   326 /* B.3 - Language ST (Structured Text) */
   247 /***************************************/
   327 /***************************************/
   249 /* B 3.1 - Expressions */
   329 /* B 3.1 - Expressions */
   250 /***********************/
   330 /***********************/
   251 void *constant_folding_c::visit(or_expression_c *symbol) {
   331 void *constant_folding_c::visit(or_expression_c *symbol) {
   252 	symbol->l_exp->accept(*this);
   332 	symbol->l_exp->accept(*this);
   253 	symbol->r_exp->accept(*this);
   333 	symbol->r_exp->accept(*this);
   254 	if (DO_OPER(bool)) {
   334 	DO_BIN_OPER(bool,   ||);
   255 		symbol->const_value_bool = (bool*) malloc(sizeof(bool));
   335 	DO_BIN_OPER(uint64, | );
   256 		*(symbol->const_value_bool) = *(symbol->l_exp->const_value_bool) || *(symbol->r_exp->const_value_bool);
       
   257 	}
       
   258 	if (DO_OPER(integer)) {
       
   259 		symbol->const_value_integer = (int64_t*) malloc(sizeof(int64_t));
       
   260 		*(symbol->const_value_integer) = *(symbol->l_exp->const_value_integer) | *(symbol->r_exp->const_value_integer);
       
   261 	}
       
   262 
       
   263 	return NULL;
   336 	return NULL;
   264 }
   337 }
   265 
   338 
   266 
   339 
   267 void *constant_folding_c::visit(xor_expression_c *symbol) {
   340 void *constant_folding_c::visit(xor_expression_c *symbol) {
   268 	symbol->l_exp->accept(*this);
   341 	symbol->l_exp->accept(*this);
   269 	symbol->r_exp->accept(*this);
   342 	symbol->r_exp->accept(*this);
   270 	if (DO_OPER(integer)) {
   343 	DO_BIN_OPER(bool,   ^);
   271 		symbol->const_value_bool = (bool*) malloc(sizeof(bool));
   344 	DO_BIN_OPER(uint64, ^);
   272 		*(symbol->const_value_bool) = *(symbol->l_exp->const_value_integer) ^ *(symbol->r_exp->const_value_integer);
       
   273 	}
       
   274 
       
   275 	return NULL;
   345 	return NULL;
   276 }
   346 }
   277 
   347 
   278 
   348 
   279 void *constant_folding_c::visit(and_expression_c *symbol) {
   349 void *constant_folding_c::visit(and_expression_c *symbol) {
   280 	symbol->l_exp->accept(*this);
   350 	symbol->l_exp->accept(*this);
   281 	symbol->r_exp->accept(*this);
   351 	symbol->r_exp->accept(*this);
   282 	if (DO_OPER(bool)) {
   352 	DO_BIN_OPER(bool,   &&);
   283 		symbol->const_value_bool = (bool*) malloc(sizeof(bool));
   353 	DO_BIN_OPER(uint64, & );
   284 		*(symbol->const_value_bool) = *(symbol->l_exp->const_value_bool) && *(symbol->r_exp->const_value_bool);
       
   285 	}
       
   286 	if (DO_OPER(integer)) {
       
   287 		symbol->const_value_integer = (int64_t*) malloc(sizeof(int64_t));
       
   288 		*(symbol->const_value_bool) = *(symbol->l_exp->const_value_integer) & *(symbol->r_exp->const_value_integer);
       
   289 	}
       
   290 
       
   291 	return NULL;
   354 	return NULL;
   292 }
   355 }
   293 
   356 
   294 
   357 
   295 void *constant_folding_c::visit(equ_expression_c *symbol) {
   358 void *constant_folding_c::visit(equ_expression_c *symbol) {
   296 	symbol->l_exp->accept(*this);
   359 	symbol->l_exp->accept(*this);
   297 	symbol->r_exp->accept(*this);
   360 	symbol->r_exp->accept(*this);
   298 	if (DO_OPER(bool)) {
   361 	DO_BIN_OPER(bool,   ==);
   299 		symbol->const_value_bool = (bool*) malloc(sizeof(bool));
   362 	DO_BIN_OPER(uint64, ==);
   300 		*(symbol->const_value_bool) = *(symbol->l_exp->const_value_bool) == *(symbol->r_exp->const_value_bool);
   363 	DO_BIN_OPER( int64, ==);
   301 	}
   364 	DO_BIN_OPER(real64, ==);
   302 	if (DO_OPER(integer)) {
       
   303 		symbol->const_value_bool = (bool*) malloc(sizeof(bool));
       
   304 		*(symbol->const_value_bool) = *(symbol->l_exp->const_value_integer) == *(symbol->r_exp->const_value_integer);
       
   305 	}
       
   306 	if (DO_OPER(real)) {
       
   307 		symbol->const_value_bool = (bool*) malloc(sizeof(bool));
       
   308 		*(symbol->const_value_bool) = *(symbol->l_exp->const_value_real) == *(symbol->r_exp->const_value_real);
       
   309 	}
       
   310 
       
   311 	return NULL;
   365 	return NULL;
   312 }
   366 }
   313 
   367 
   314 
   368 
   315 void *constant_folding_c::visit(notequ_expression_c *symbol) {
   369 void *constant_folding_c::visit(notequ_expression_c *symbol) {
   316 	symbol->l_exp->accept(*this);
   370 	symbol->l_exp->accept(*this);
   317 	symbol->r_exp->accept(*this);
   371 	symbol->r_exp->accept(*this);
   318 	if (DO_OPER(bool)) {
   372 	DO_BIN_OPER(bool,   !=);
   319 		symbol->const_value_bool = (bool*) malloc(sizeof(bool));
   373 	DO_BIN_OPER(uint64, !=);
   320 		*(symbol->const_value_bool) = *(symbol->l_exp->const_value_bool) != *(symbol->r_exp->const_value_bool);
   374 	DO_BIN_OPER( int64, !=);
   321 	}
   375 	DO_BIN_OPER(real64, !=);
   322 	if (DO_OPER(integer)) {
       
   323 		symbol->const_value_bool = (bool*) malloc(sizeof(bool));
       
   324 		*(symbol->const_value_bool) = *(symbol->l_exp->const_value_integer) != *(symbol->r_exp->const_value_integer);
       
   325 	}
       
   326 	if (DO_OPER(real)) {
       
   327 		symbol->const_value_bool = (bool*) malloc(sizeof(bool));
       
   328 		*(symbol->const_value_bool) = *(symbol->l_exp->const_value_real) != *(symbol->r_exp->const_value_real);
       
   329 	}
       
   330 
       
   331 	return NULL;
   376 	return NULL;
   332 }
   377 }
   333 
   378 
   334 
   379 
   335 void *constant_folding_c::visit(lt_expression_c *symbol) {
   380 void *constant_folding_c::visit(lt_expression_c *symbol) {
   336 	symbol->l_exp->accept(*this);
   381 	symbol->l_exp->accept(*this);
   337 	symbol->r_exp->accept(*this);
   382 	symbol->r_exp->accept(*this);
   338 	if (DO_OPER(integer)) {
   383 	DO_BIN_OPER(bool,   <);
   339 		symbol->const_value_bool = (bool*) malloc(sizeof(bool));
   384 	DO_BIN_OPER(uint64, <);
   340 		*(symbol->const_value_bool) = *(symbol->l_exp->const_value_integer) < *(symbol->r_exp->const_value_integer);
   385 	DO_BIN_OPER( int64, <);
   341 	}
   386 	DO_BIN_OPER(real64, <);
   342 	if (DO_OPER(real)) {
       
   343 		symbol->const_value_bool = (bool*) malloc(sizeof(bool));
       
   344 		*(symbol->const_value_bool) = *(symbol->l_exp->const_value_real) < *(symbol->r_exp->const_value_real);
       
   345 	}
       
   346 
       
   347 	return NULL;
   387 	return NULL;
   348 }
   388 }
   349 
   389 
   350 
   390 
   351 void *constant_folding_c::visit(gt_expression_c *symbol) {
   391 void *constant_folding_c::visit(gt_expression_c *symbol) {
   352 	symbol->l_exp->accept(*this);
   392 	symbol->l_exp->accept(*this);
   353 	symbol->r_exp->accept(*this);
   393 	symbol->r_exp->accept(*this);
   354 	if (DO_OPER(integer)) {
   394 	DO_BIN_OPER(bool,   >);
   355 		symbol->const_value_bool = (bool*) malloc(sizeof(bool));
   395 	DO_BIN_OPER(uint64, >);
   356 		*(symbol->const_value_bool) = *(symbol->l_exp->const_value_integer) > *(symbol->r_exp->const_value_integer);
   396 	DO_BIN_OPER( int64, >);
   357 	}
   397 	DO_BIN_OPER(real64, >);
   358 	if (DO_OPER(real)) {
       
   359 		symbol->const_value_bool = (bool*) malloc(sizeof(bool));
       
   360 		*(symbol->const_value_bool) = *(symbol->l_exp->const_value_real) > *(symbol->r_exp->const_value_real);
       
   361 	}
       
   362 
       
   363 	return NULL;
   398 	return NULL;
   364 }
   399 }
   365 
   400 
   366 
   401 
   367 void *constant_folding_c::visit(le_expression_c *symbol) {
   402 void *constant_folding_c::visit(le_expression_c *symbol) {
   368 	symbol->l_exp->accept(*this);
   403 	symbol->l_exp->accept(*this);
   369 	symbol->r_exp->accept(*this);
   404 	symbol->r_exp->accept(*this);
   370 	if (DO_OPER(integer)) {
   405 	DO_BIN_OPER(bool,   <=);
   371 		symbol->const_value_bool = (bool*) malloc(sizeof(bool));
   406 	DO_BIN_OPER(uint64, <=);
   372 		*(symbol->const_value_bool) = *(symbol->l_exp->const_value_integer) <= *(symbol->r_exp->const_value_integer);
   407 	DO_BIN_OPER( int64, <=);
   373 	}
   408 	DO_BIN_OPER(real64, <=);
   374 	if (DO_OPER(real)) {
       
   375 		symbol->const_value_bool = (bool*) malloc(sizeof(bool));
       
   376 		*(symbol->const_value_bool) = *(symbol->l_exp->const_value_real) <= *(symbol->r_exp->const_value_real);
       
   377 	}
       
   378 
       
   379 	return NULL;
   409 	return NULL;
   380 }
   410 }
   381 
   411 
   382 
   412 
   383 void *constant_folding_c::visit(ge_expression_c *symbol) {
   413 void *constant_folding_c::visit(ge_expression_c *symbol) {
   384 	symbol->l_exp->accept(*this);
   414 	symbol->l_exp->accept(*this);
   385 	symbol->r_exp->accept(*this);
   415 	symbol->r_exp->accept(*this);
   386 	if (DO_OPER(integer)) {
   416 	DO_BIN_OPER(bool,   >=);
   387 		symbol->const_value_bool = (bool*) malloc(sizeof(bool));
   417 	DO_BIN_OPER(uint64, >=);
   388 		*(symbol->const_value_bool) = *(symbol->l_exp->const_value_integer) >= *(symbol->r_exp->const_value_integer);
   418 	DO_BIN_OPER( int64, >=);
   389 	}
   419 	DO_BIN_OPER(real64, >=);
   390 	if (DO_OPER(real)) {
   420 	return NULL;
   391 		symbol->const_value_bool = (bool*) malloc(sizeof(bool));
   421 }
   392 		*(symbol->const_value_bool) = *(symbol->l_exp->const_value_real) >= *(symbol->r_exp->const_value_real);
   422 
   393 	}
   423 
   394 
   424 #define CHECK_OVERFLOW_SUM(dtype)\
   395 	return NULL;
   425 	if (VALID_CVALUE(dtype, symbol))                                                                                                             \
   396 }
   426 		if ((((std::numeric_limits< dtype##_t >::max() - GET_CVALUE(dtype, symbol->l_exp)) < (GET_CVALUE(dtype, symbol->r_exp))) ? 1 : 0) || \
   397 
   427 		    (((std::numeric_limits< dtype##_t >::min() + GET_CVALUE(dtype, symbol->l_exp)) > (GET_CVALUE(dtype, symbol->r_exp))) ? 1 : 0))   \
   398 
   428 			SET_OVFLOW(dtype, symbol);
       
   429 #define CHECK_OVERFLOW_real64  \
       
   430 	if (VALID_CVALUE(real64, symbol))                                                                                                            \
       
   431         	/* NaN => underflow, overflow, number is a higher precision format, is a complex number (IEEE standard) */                           \
       
   432 		 if (isnan(GET_CVALUE(real64, symbol)))                                                                                              \
       
   433 			SET_OVFLOW(real64, symbol);
   399 void *constant_folding_c::visit(add_expression_c *symbol) {
   434 void *constant_folding_c::visit(add_expression_c *symbol) {
   400 	symbol->l_exp->accept(*this);
   435 	symbol->l_exp->accept(*this);
   401 	symbol->r_exp->accept(*this);
   436 	symbol->r_exp->accept(*this);
   402 	if (DO_OPER(integer)) {
   437 	DO_BIN_OPER(uint64, +);
   403 		if (CHECK_OVERFLOW_SUM(*(symbol->l_exp->const_value_integer), *(symbol->r_exp->const_value_integer), int64_t))
   438 	DO_BIN_OPER( int64, +);
   404 			STAGE3_ERROR(0, symbol, symbol, "Overflow in constant expression.");
   439 	DO_BIN_OPER(real64, +);
   405 		symbol->const_value_integer = (int64_t*) malloc(sizeof(int64_t));
   440 	CHECK_OVERFLOW_SUM(uint64);
   406 		*(symbol->const_value_integer) = *(symbol->l_exp->const_value_integer) + *(symbol->r_exp->const_value_integer);
   441 	CHECK_OVERFLOW_SUM( int64);
   407 	}
   442 	CHECK_OVERFLOW_real64;
   408 	if (DO_OPER(real)) {
   443 	return NULL;
   409 		symbol->const_value_real = (real64_t*) malloc(sizeof(real64_t));
   444 }
   410 		*(symbol->const_value_real) = *(symbol->l_exp->const_value_real) + *(symbol->r_exp->const_value_real);
   445 
   411 		/*
   446 
   412 		 * According to the IEEE standard, NaN value is used as:
   447 #define CHECK_OVERFLOW_SUB(dtype)\
   413 		 *   - representation of a number that has underflowed
   448 	if (VALID_CVALUE(dtype, symbol))                                                                                                             \
   414 		 *   - representation of number that has overflowed
   449 		if ((((std::numeric_limits< dtype##_t >::max() - GET_CVALUE(dtype, symbol->l_exp)) < (-GET_CVALUE(dtype, symbol->r_exp))) ? 1 : 0) || \
   415 		 *   - number is a higher precision format
   450 		    (((std::numeric_limits< dtype##_t >::min() + GET_CVALUE(dtype, symbol->l_exp)) > (-GET_CVALUE(dtype, symbol->r_exp))) ? 1 : 0))   \
   416 		 *   - A complex number
   451 			SET_OVFLOW(dtype, symbol);
   417 		 */
       
   418 		 if (isnan(*(symbol->const_value_real)))
       
   419 			STAGE3_ERROR(0, symbol, symbol, "Overflow in constant expression.");
       
   420 	}
       
   421 
       
   422 	return NULL;
       
   423 }
       
   424 
       
   425 
       
   426 void *constant_folding_c::visit(sub_expression_c *symbol) {
   452 void *constant_folding_c::visit(sub_expression_c *symbol) {
   427 	symbol->l_exp->accept(*this);
   453 	symbol->l_exp->accept(*this);
   428 	symbol->r_exp->accept(*this);
   454 	symbol->r_exp->accept(*this);
   429 	if (DO_OPER(integer)) {
   455 	DO_BIN_OPER(uint64, -);
   430 		if (CHECK_OVERFLOW_SUB(*(symbol->l_exp->const_value_integer), *(symbol->r_exp->const_value_integer), int64_t))
   456 	DO_BIN_OPER( int64, -);
   431 			STAGE3_ERROR(0, symbol, symbol, "Overflow in constant expression.");
   457 	DO_BIN_OPER(real64, -);
   432 		symbol->const_value_integer = (int64_t*) malloc(sizeof(int64_t));
   458 	CHECK_OVERFLOW_SUB(uint64);
   433 		*(symbol->const_value_integer) = *(symbol->l_exp->const_value_integer) - *(symbol->r_exp->const_value_integer);
   459 	CHECK_OVERFLOW_SUB( int64);
   434 	}
   460 	CHECK_OVERFLOW_real64;
   435 	if (DO_OPER(real)) {
   461 	return NULL;
   436 		symbol->const_value_real = (real64_t*) malloc(sizeof(real64_t));
   462 }
   437 		*(symbol->const_value_real) = *(symbol->l_exp->const_value_real) - *(symbol->r_exp->const_value_real);
   463 
   438 		/*
   464 
   439 		 * According to the IEEE standard, NaN value is used as:
   465 /* TODO!!! */
   440 		 *   - representation of a number that has underflowed
   466 #define CHECK_OVERFLOW_MUL(dtype)\
   441 		 *   - representation of number that has overflowed
   467 	if (VALID_CVALUE(dtype, symbol))                                                                                                             \
   442 		 *   - number is a higher precision format
   468 		if (false)                                                                                                                                   \
   443 		 *   - A complex number
   469 			SET_OVFLOW(dtype, symbol);
   444 		 */
       
   445 		if (isnan(*(symbol->const_value_real)))
       
   446 			STAGE3_ERROR(0, symbol, symbol, "Overflow in constant expression.");
       
   447 	}
       
   448 
       
   449 	return NULL;
       
   450 }
       
   451 
       
   452 
       
   453 void *constant_folding_c::visit(mul_expression_c *symbol) {
   470 void *constant_folding_c::visit(mul_expression_c *symbol) {
   454 	symbol->l_exp->accept(*this);
   471 	symbol->l_exp->accept(*this);
   455 	symbol->r_exp->accept(*this);
   472 	symbol->r_exp->accept(*this);
   456 	if (DO_OPER(integer)) {
   473 	DO_BIN_OPER(uint64, *);
   457 		symbol->const_value_integer = (int64_t*) malloc(sizeof(int64_t));
   474 	DO_BIN_OPER( int64, *);
   458 		*(symbol->const_value_integer) = *(symbol->l_exp->const_value_integer) * *(symbol->r_exp->const_value_integer);
   475 	DO_BIN_OPER(real64, *);
   459 	}
   476 	CHECK_OVERFLOW_MUL(uint64);
   460 	if (DO_OPER(real)) {
   477 	CHECK_OVERFLOW_MUL( int64);
   461 		symbol->const_value_real = (real64_t*) malloc(sizeof(real64_t));
   478 	CHECK_OVERFLOW_real64;
   462 		*(symbol->const_value_real) = *(symbol->l_exp->const_value_real) * *(symbol->r_exp->const_value_real);
   479 	return NULL;
   463 		/*
   480 }
   464 		 * According to the IEEE standard, NaN value is used as:
   481 
   465 		 *   - representation of a number that has underflowed
   482 
   466 		 *   - representation of number that has overflowed
   483 
   467 		 *   - number is a higher precision format
   484 /* TODO!!! */
   468 		 *   - A complex number
   485 #define CHECK_OVERFLOW_DIV(dtype)\
   469 		 */
   486 	if (VALID_CVALUE(dtype, symbol))                                                                                                             \
   470 		if (isnan(*(symbol->const_value_real)))
   487 		if (false)                                                                                                                                   \
   471 			STAGE3_ERROR(0, symbol, symbol, "Overflow in constant expression.");
   488 			SET_OVFLOW(dtype, symbol);
   472 	}
       
   473 
       
   474 	return NULL;
       
   475 }
       
   476 
       
   477 
       
   478 void *constant_folding_c::visit(div_expression_c *symbol) {
   489 void *constant_folding_c::visit(div_expression_c *symbol) {
   479 	symbol->l_exp->accept(*this);
   490 	symbol->l_exp->accept(*this);
   480 	symbol->r_exp->accept(*this);
   491 	symbol->r_exp->accept(*this);
   481 	if (DO_OPER(integer)) {
   492 	if (ISZERO_CVALUE(uint64, symbol->r_exp))  {NEW_CVALUE(uint64, symbol); SET_OVFLOW(uint64, symbol);} else {DO_BIN_OPER(uint64, /); CHECK_OVERFLOW_DIV(uint64)};
   482 		if (*(symbol->r_exp->const_value_integer) == 0)
   493 	if (ISZERO_CVALUE( int64, symbol->r_exp))  {NEW_CVALUE( int64, symbol); SET_OVFLOW( int64, symbol);} else {DO_BIN_OPER( int64, /); CHECK_OVERFLOW_DIV( int64)};
   483 			STAGE3_ERROR(0, symbol, symbol, "Division by zero in constant expression.");
   494 	if (ISZERO_CVALUE(real64, symbol->r_exp))  {NEW_CVALUE(real64, symbol); SET_OVFLOW(real64, symbol);} else {DO_BIN_OPER(real64, /); CHECK_OVERFLOW_real64;};
   484 		symbol->const_value_integer = (int64_t*) malloc(sizeof(int64_t));
   495 	return NULL;
   485 		*(symbol->const_value_integer) = *(symbol->l_exp->const_value_integer) / *(symbol->r_exp->const_value_integer);
   496 }
   486 	}
   497 
   487 	if (DO_OPER(real)) {
   498 
   488 		if (*(symbol->r_exp->const_value_real) == 0)
   499 /* TODO!!! */
   489 			STAGE3_ERROR(0, symbol, symbol, "Division by zero in constant expression.");
   500 #define CHECK_OVERFLOW_MOD(dtype)\
   490 		symbol->const_value_real = (real64_t*) malloc(sizeof(real64_t));
   501 	if (VALID_CVALUE(dtype, symbol))                                                                                                             \
   491 		*(symbol->const_value_real) = *(symbol->l_exp->const_value_real) / *(symbol->r_exp->const_value_real);
   502 		if (false)                                                                                                                                   \
   492 		/*
   503 			SET_OVFLOW(dtype, symbol);
   493 		 * According to the IEEE standard, NaN value is used as:
       
   494 		 *   - representation of a number that has underflowed
       
   495 		 *   - representation of number that has overflowed
       
   496 		 *   - number is a higher precision format
       
   497 		 *   - A complex number
       
   498 		 */
       
   499 		if (isnan(*(symbol->const_value_real)))
       
   500 			STAGE3_ERROR(0, symbol, symbol, "Overflow in constant expression.");
       
   501 	}
       
   502 
       
   503 	return NULL;
       
   504 }
       
   505 
       
   506 
       
   507 void *constant_folding_c::visit(mod_expression_c *symbol) {
   504 void *constant_folding_c::visit(mod_expression_c *symbol) {
   508 	symbol->l_exp->accept(*this);
   505 	symbol->l_exp->accept(*this);
   509 	symbol->r_exp->accept(*this);
   506 	symbol->r_exp->accept(*this);
   510 	if (DO_OPER(integer)) {
   507 	if (ISZERO_CVALUE(uint64, symbol->r_exp))  {NEW_CVALUE(uint64, symbol); SET_OVFLOW(uint64, symbol);} else {DO_BIN_OPER(uint64, %); CHECK_OVERFLOW_MOD(uint64)};
   511 		if (*(symbol->r_exp->const_value_integer) == 0)
   508 	if (ISZERO_CVALUE( int64, symbol->r_exp))  {NEW_CVALUE( int64, symbol); SET_OVFLOW( int64, symbol);} else {DO_BIN_OPER( int64, %); CHECK_OVERFLOW_MOD( int64)};
   512 			STAGE3_ERROR(0, symbol, symbol, "Division by zero in constant expression.");
       
   513 		symbol->const_value_integer = (int64_t*) malloc(sizeof(int64_t));
       
   514 		*(symbol->const_value_integer) = *(symbol->l_exp->const_value_integer) % *(symbol->r_exp->const_value_integer);
       
   515 
       
   516 	}
       
   517 
       
   518 	return NULL;
   509 	return NULL;
   519 }
   510 }
   520 
   511 
   521 
   512 
   522 void *constant_folding_c::visit(power_expression_c *symbol) {
   513 void *constant_folding_c::visit(power_expression_c *symbol) {
   523 	symbol->l_exp->accept(*this);
   514 	symbol->l_exp->accept(*this);
   524 	symbol->r_exp->accept(*this);
   515 	symbol->r_exp->accept(*this);
   525 	if ((NULL != symbol->l_exp->const_value_real) && (NULL != symbol->r_exp->const_value_integer)) {
   516 	/* NOTE: If the const_value in symbol->r_exp is within the limits of both int64 and uint64, then we do both operations.
   526 		symbol->const_value_real = (real64_t*) malloc(sizeof(real64_t));
   517 	 *       That is OK, as the result should be identicial (we do create an unnecessary CVALUE variable, but who cares?).
   527 		*(symbol->const_value_real) = pow(*(symbol->l_exp->const_value_real), *(symbol->r_exp->const_value_integer));
   518 	 *       If only one is valid, then that is the oper we will do!
   528 		/*
   519 	 */
   529 		 * According to the IEEE standard, NaN value is used as:
   520 	if (VALID_CVALUE(real64, symbol->l_exp) && VALID_CVALUE( int64, symbol->r_exp)) {
   530 		 *   - representation of a number that has underflowed
   521 		NEW_CVALUE(real64, symbol);
   531 		 *   - representation of number that has overflowed
   522 		SET_CVALUE(real64, symbol, pow(GET_CVALUE(real64, symbol->l_exp), GET_CVALUE( int64, symbol->r_exp)));
   532 		 *   - number is a higher precision format
   523 	}
   533 		 *   - A complex number
   524 	if (VALID_CVALUE(real64, symbol->l_exp) && VALID_CVALUE(uint64, symbol->r_exp)) {
   534 		 */
   525 		NEW_CVALUE(real64, symbol);
   535 		if (isnan(*(symbol->const_value_real)))
   526 		SET_CVALUE(real64, symbol, pow(GET_CVALUE(real64, symbol->l_exp), GET_CVALUE(uint64, symbol->r_exp)));
   536 			STAGE3_ERROR(0, symbol, symbol, "Overflow in constant expression.");
   527 	}
   537 	}
   528 	CHECK_OVERFLOW_real64;
   538 
   529 	return NULL;
   539 	return NULL;
   530 }
   540 }
   531 
   541 
   532 
   542 
   533 /* TODO!!! */
       
   534 #define CHECK_OVERFLOW_NEG(dtype)\
       
   535 	if (VALID_CVALUE(dtype, symbol))                                                                                                             \
       
   536 		if (false)                                                                                                                                   \
       
   537 			SET_OVFLOW(dtype, symbol);
   543 void *constant_folding_c::visit(neg_expression_c *symbol) {
   538 void *constant_folding_c::visit(neg_expression_c *symbol) {
   544 	symbol->exp->accept(*this);
   539 	symbol->exp->accept(*this);
   545 	if (NULL != symbol->exp->const_value_integer) {
   540 	if (VALID_CVALUE( int64, symbol->exp)) {
   546 		symbol->const_value_integer = (int64_t*) malloc(sizeof(int64_t));
   541 		NEW_CVALUE( int64, symbol);
   547 		*(symbol->const_value_integer) = - *(symbol->exp->const_value_integer);
   542 		SET_CVALUE( int64, symbol, - GET_CVALUE( int64, symbol->exp));
   548 	}
   543 	}
   549 	if (NULL != symbol->exp->const_value_real) {
   544 	if (VALID_CVALUE(real64, symbol->exp)) {
   550 		symbol->const_value_real = (real64_t*) malloc(sizeof(real64_t));
   545 		NEW_CVALUE(real64, symbol);
   551 		*(symbol->const_value_real) = - *(symbol->exp->const_value_real);
   546 		SET_CVALUE(real64, symbol, - GET_CVALUE(real64, symbol->exp));
   552 	}
   547 	}
       
   548 	CHECK_OVERFLOW_NEG( int64);
       
   549 	CHECK_OVERFLOW_real64;
   553 	return NULL;
   550 	return NULL;
   554 }
   551 }
   555 
   552 
   556 
   553 
   557 
   554 
   558 void *constant_folding_c::visit(not_expression_c *symbol) {
   555 void *constant_folding_c::visit(not_expression_c *symbol) {
   559 	symbol->exp->accept(*this);
   556 	symbol->exp->accept(*this);
   560 	if (NULL != symbol->exp->const_value_bool) {
   557 	if (VALID_CVALUE(  bool, symbol->exp)) {
   561 		symbol->const_value_bool = (bool*) malloc(sizeof(bool));
   558 		NEW_CVALUE(  bool, symbol);
   562 		*(symbol->const_value_bool) = !*(symbol->exp->const_value_bool);
   559 		SET_CVALUE(  bool, symbol,  ! GET_CVALUE(  bool, symbol->exp));
   563 	}
   560 	}
   564 
   561 	if (VALID_CVALUE(uint64, symbol->exp)) {
   565 	return NULL;
   562 		NEW_CVALUE(uint64, symbol);
   566 }
   563 		SET_CVALUE(uint64, symbol,  ~ GET_CVALUE(uint64, symbol->exp));
   567 
   564 	}
   568 
   565 	return NULL;
   569 
   566 }
       
   567 
       
   568