--- a/stage3/constant_folding.cc Wed Jun 06 16:39:54 2012 +0100
+++ b/stage3/constant_folding.cc Fri Jun 08 19:44:32 2012 +0100
@@ -31,13 +31,85 @@
*/
-/* Determine the value of an ST expression.
- * Filling in all symbols the correct value.
+/* Do constant folding...
+ *
+ * I.e., Determine the value of all expressions in which only constant values (i.e. literals) are used.
+ * The (constant) result of each operation is stored (annotated) in the respective operation symbol
+ * (e.g.: add_expression_c) in the abstract syntax tree,
*
* For example:
- * 2 + 3 -> returns constant_value_integer = 5
- * 22.2 - 5.0 -> returns constant_value_real = 17.2
+ * 2 + 3 -> the constant value '5' is stored in the add_expression_c symbol.
+ * 22.2 - 5.0 -> the constant value '17.2' is stored in the add_expression_c symbol.
* etc...
+ *
+ *
+ * NOTE 1 that some operations and constants can have multiple data types. For example,
+ * 1 AND 0
+ * may be either a BOOL, BYTE, WORD or LWORD.
+ *
+ * The same happens with
+ * 1 + 2
+ * which may be signed (e.g. INT) or unsigned (UINT)
+ *
+ * For the above reason, instead of storing a single constant value, we actually store 4:
+ * - bool
+ * - uint64
+ * - int64
+ * - real64
+ *
+ * Additionally, since the result of an operation may result in an overflow, we actually
+ * store the result inside a struct (defined in absyntax.hh)
+ *
+ * ** During stage 3 (semantic analysis/checking) we will be doing constant folding.
+ * * That algorithm will anotate the abstract syntax tree with the result of operations
+ * * on literals (i.e. 44 + 55 will store the result 99).
+ * * Since the same source code (e.g. 1 + 0) may actually be a BOOL or an ANY_INT,
+ * * or an ANY_BIT, we need to handle all possibilities, and determine the result of the
+ * * operation assuming each type.
+ * * For this reason, we have one entry for each possible type, with some expressions
+ * * having more than one entry filled in!
+ * **
+ * typedef enum { cs_undefined, // not defined --> 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;
+ * const_value_real64_t *const_value_real64; // when NULL --> UNDEFINED
+ *
+ * typedef struct {
+ * const_status_t status;
+ * int64_t value;
+ * } const_value_int64_t;
+ * const_value_int64_t *const_value_int64; // when NULL --> UNDEFINED
+ *
+ * typedef struct {
+ * const_status_t status;
+ * uint64_t value;
+ * } const_value_uint64_t;
+ * const_value_uint64_t *const_value_uint64; // when NULL --> UNDEFINED
+ *
+ * typedef struct {
+ * const_status_t status;
+ * bool value;
+ * } const_value_bool_t;
+ * const_value_bool_t *const_value_bool; // when NULL --> UNDEFINED
+ *
+ *
+ *
+ * NOTE 2
+ * This file does not print out any error messages!
+ * We cannot really print out error messages when we find an overflow. Since each operation
+ * (symbol in the absract syntax tree for that operation) will have up to 4 constant results,
+ * it may happen that some of them overflow, while other do not.
+ * We must wait for data type checking to determine the exact data type of each expression
+ * before we can decide whether or not we should print out an overflow error message.
+ *
+ * For this reason, this visitor merely annotates the abstract syntax tree, and leaves the
+ ` actuall printing of errors for the print_datatype_errors_c class!
*/
#include "constant_folding.hh"
@@ -76,26 +148,31 @@
-#define MALLOC(variable, data_type) \
- variable = (data_type *)malloc(sizeof(data_type)); \
- if (variable == NULL) ERROR;
-
-
-#define DO_OPER(dtype)\
- (NULL != symbol->r_exp->const_value_##dtype ) && \
- (NULL != symbol->l_exp->const_value_##dtype )
-
-
-#define CHECK_OVERFLOW_SUM(a, b, type)\
- ((((std::numeric_limits< type >::max() - a) < (b)) ? 1 : 0) || \
- (((std::numeric_limits< type >::min() + a) > (b)) ? 1 : 0))
-
-#define CHECK_OVERFLOW_SUB(a, b, type)\
- ((((std::numeric_limits< type >::max() - a) < (-b)) ? 1 : 0) || \
- (((std::numeric_limits< type >::min() + a) > (-b)) ? 1 : 0))
-
-#define SYMBOL_BOOL_VALUE (symbol->exp->const_value_bool)
-#define SYMBOL_REAL_VALUE (symbol->exp->const_value_real)
+
+
+
+
+
+
+
+
+#define NEW_CVALUE(dtype, symbol) \
+ (symbol->const_value_##dtype) = new(symbol_c::const_value_##dtype##_t); \
+ if ((symbol->const_value_##dtype) == NULL) ERROR; \
+ (symbol->const_value_##dtype)->status = symbol_c::cs_undefined;
+
+#define SET_CVALUE(dtype, symbol, new_value) ((symbol)->const_value_##dtype->value) = new_value; ((symbol)->const_value_##dtype->status) = symbol_c::cs_const_value;
+#define GET_CVALUE(dtype, symbol) ((symbol)->const_value_##dtype->value)
+#define SET_OVFLOW(dtype, symbol) ((symbol)->const_value_##dtype->status) = symbol_c::cs_overflow
+ /* 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! */
+#define VALID_CVALUE(dtype, symbol) ((NULL != (symbol)->const_value_##dtype) && (symbol_c::cs_const_value == (symbol)->const_value_##dtype->status))
+#define ISZERO_CVALUE(dtype, symbol) ((VALID_CVALUE(dtype, symbol)) && (GET_CVALUE(dtype, symbol) == 0))
+#define DO_BIN_OPER(dtype, oper)\
+ if (VALID_CVALUE(dtype, symbol->r_exp) && VALID_CVALUE(dtype, symbol->l_exp)) { \
+ NEW_CVALUE(dtype, symbol); \
+ SET_CVALUE(dtype, symbol, GET_CVALUE(dtype, symbol->l_exp) oper GET_CVALUE(dtype, symbol->r_exp)); \
+ }
+
@@ -110,7 +187,7 @@
if (! (std::numeric_limits<real64_t>::is_iec559) )
STAGE3_WARNING(&null_symbol, &null_symbol, "The platform running the compiler does not implement IEC 559 floating point numbers. "
"Any error and/or warning messages related to overflow/underflow of the result of operations on REAL/LREAL literals "
- " (i.e. constant folding) may themselves be erroneous, although are most probably correct");
+ " (i.e. constant folding) may themselves be erroneous, although are most probably correct.");
}
@@ -130,116 +207,119 @@
/* B 1.2.1 - Numeric Literals */
/******************************/
void *constant_folding_c::visit(real_c *symbol) {
- MALLOC(symbol->const_value_real, real64_t);
- *symbol->const_value_real = extract_real_value(symbol);
-
+ NEW_CVALUE(real64, symbol);
+ SET_CVALUE(real64, symbol, extract_real_value(symbol));
return NULL;
}
void *constant_folding_c::visit(integer_c *symbol) {
- int64_t *integer_value;
-
- integer_value = (int64_t *)malloc(sizeof(int64_t));
- *integer_value = extract_integer_value(symbol);
- symbol->const_value_integer = integer_value;
-
+ NEW_CVALUE( int64, symbol);
+ SET_CVALUE( int64, symbol, extract_integer_value(symbol));
+ NEW_CVALUE(uint64, symbol);
+ SET_CVALUE(uint64, symbol, extract_integer_value(symbol));
return NULL;
}
void *constant_folding_c::visit(neg_real_c *symbol) {
symbol->exp->accept(*this);
- if (NULL == symbol->exp->const_value_real)
- ERROR;
- symbol->const_value_real = (real64_t*) malloc(sizeof(real64_t));
- *symbol->const_value_real = - *(symbol->exp->const_value_real);
- return NULL;
-}
-
-
+ if (!VALID_CVALUE(real64, symbol->exp))
+ return NULL;
+ NEW_CVALUE(real64, symbol);
+ SET_CVALUE(real64, symbol, - GET_CVALUE( real64, symbol->exp));
+ return NULL;
+}
+
+/* | '-' integer {$$ = new neg_integer_c($2, locloc(@$));} */
void *constant_folding_c::visit(neg_integer_c *symbol) {
- int64_t *integer_value;
-
- integer_value = (int64_t *)malloc(sizeof(int64_t));
- *integer_value = extract_integer_value(symbol);
- symbol->const_value_integer = integer_value;
-
+ symbol->exp->accept(*this);
+ if (VALID_CVALUE(int64, symbol->exp)) {
+ NEW_CVALUE( int64, symbol);
+ SET_CVALUE( int64, symbol, - GET_CVALUE( int64, symbol->exp));
+ }
return NULL;
}
void *constant_folding_c::visit(binary_integer_c *symbol) {
-
return NULL;
}
void *constant_folding_c::visit(octal_integer_c *symbol) {
-
return NULL;
}
void *constant_folding_c::visit(hex_integer_c *symbol) {
- symbol->const_value_integer = (int64_t*) malloc(sizeof(int64_t));
- *(symbol->const_value_integer) = extract_hex_value(symbol);
-
- return NULL;
-}
-
-
+ NEW_CVALUE( int64, symbol);
+ SET_CVALUE( int64, symbol, extract_hex_value(symbol));
+ NEW_CVALUE(uint64, symbol);
+ SET_CVALUE(uint64, symbol, extract_hex_value(symbol));
+ return NULL;
+}
+
+
+/*
+integer_literal:
+ integer_type_name '#' signed_integer {$$ = new integer_literal_c($1, $3, locloc(@$));}
+| integer_type_name '#' binary_integer {$$ = new integer_literal_c($1, $3, locloc(@$));}
+| integer_type_name '#' octal_integer {$$ = new integer_literal_c($1, $3, locloc(@$));}
+| integer_type_name '#' hex_integer {$$ = new integer_literal_c($1, $3, locloc(@$));}
+*/
+// SYM_REF2(integer_literal_c, type, value)
void *constant_folding_c::visit(integer_literal_c *symbol) {
symbol->value->accept(*this);
- if (NULL == symbol->value->const_value_integer) ERROR;
- symbol->const_value_integer = (int64_t*) malloc(sizeof(int64_t));
- *(symbol->const_value_integer) = *(symbol->value->const_value_integer);
-
+ if (VALID_CVALUE( int64, symbol->value)) {
+ NEW_CVALUE( int64, symbol);
+ SET_CVALUE( int64, symbol, GET_CVALUE( int64, symbol->value));
+ }
+ if (VALID_CVALUE(uint64, symbol->value)) {
+ NEW_CVALUE(uint64, symbol);
+ SET_CVALUE(uint64, symbol, GET_CVALUE(uint64, symbol->value));
+ }
return NULL;
}
void *constant_folding_c::visit(real_literal_c *symbol) {
symbol->value->accept(*this);
- if (NULL == symbol->value->const_value_real) ERROR;
- symbol->const_value_real = (real64_t*) malloc(sizeof(real64_t));
- *symbol->const_value_real = *(symbol->value->const_value_real);
-
+ if (VALID_CVALUE(real64, symbol->value)) {
+ NEW_CVALUE(real64, symbol);
+ SET_CVALUE(real64, symbol, GET_CVALUE(real64, symbol->value));
+ }
return NULL;
}
void *constant_folding_c::visit(bit_string_literal_c *symbol) {
-
return NULL;
}
void *constant_folding_c::visit(boolean_literal_c *symbol) {
symbol->value->accept(*this);
- if (NULL == symbol->value->const_value_bool) ERROR;
- symbol->const_value_bool = (bool *)malloc(sizeof(bool));
- *(symbol->const_value_bool) = *(symbol->value->const_value_bool);
-
+ if (VALID_CVALUE(bool, symbol->value)) {
+ NEW_CVALUE(bool, symbol);
+ SET_CVALUE(bool, symbol, GET_CVALUE( bool, symbol->value));
+ }
return NULL;
}
void *constant_folding_c::visit(boolean_true_c *symbol) {
- symbol->const_value_bool = (bool *)malloc(sizeof(bool));
- *(symbol->const_value_bool) = true;
-
+ NEW_CVALUE(bool, symbol);
+ SET_CVALUE(bool, symbol, true);
return NULL;
}
void *constant_folding_c::visit(boolean_false_c *symbol) {
- symbol->const_value_bool = (bool *)malloc(sizeof(bool));
- *(symbol->const_value_bool) = false;
-
- return NULL;
-}
-
+ NEW_CVALUE(bool, symbol);
+ SET_CVALUE(bool, symbol, false);
+ return NULL;
+}
/***************************************/
@@ -251,15 +331,8 @@
void *constant_folding_c::visit(or_expression_c *symbol) {
symbol->l_exp->accept(*this);
symbol->r_exp->accept(*this);
- if (DO_OPER(bool)) {
- symbol->const_value_bool = (bool*) malloc(sizeof(bool));
- *(symbol->const_value_bool) = *(symbol->l_exp->const_value_bool) || *(symbol->r_exp->const_value_bool);
- }
- if (DO_OPER(integer)) {
- symbol->const_value_integer = (int64_t*) malloc(sizeof(int64_t));
- *(symbol->const_value_integer) = *(symbol->l_exp->const_value_integer) | *(symbol->r_exp->const_value_integer);
- }
-
+ DO_BIN_OPER(bool, ||);
+ DO_BIN_OPER(uint64, | );
return NULL;
}
@@ -267,11 +340,8 @@
void *constant_folding_c::visit(xor_expression_c *symbol) {
symbol->l_exp->accept(*this);
symbol->r_exp->accept(*this);
- if (DO_OPER(integer)) {
- symbol->const_value_bool = (bool*) malloc(sizeof(bool));
- *(symbol->const_value_bool) = *(symbol->l_exp->const_value_integer) ^ *(symbol->r_exp->const_value_integer);
- }
-
+ DO_BIN_OPER(bool, ^);
+ DO_BIN_OPER(uint64, ^);
return NULL;
}
@@ -279,15 +349,8 @@
void *constant_folding_c::visit(and_expression_c *symbol) {
symbol->l_exp->accept(*this);
symbol->r_exp->accept(*this);
- if (DO_OPER(bool)) {
- symbol->const_value_bool = (bool*) malloc(sizeof(bool));
- *(symbol->const_value_bool) = *(symbol->l_exp->const_value_bool) && *(symbol->r_exp->const_value_bool);
- }
- if (DO_OPER(integer)) {
- symbol->const_value_integer = (int64_t*) malloc(sizeof(int64_t));
- *(symbol->const_value_bool) = *(symbol->l_exp->const_value_integer) & *(symbol->r_exp->const_value_integer);
- }
-
+ DO_BIN_OPER(bool, &&);
+ DO_BIN_OPER(uint64, & );
return NULL;
}
@@ -295,19 +358,10 @@
void *constant_folding_c::visit(equ_expression_c *symbol) {
symbol->l_exp->accept(*this);
symbol->r_exp->accept(*this);
- if (DO_OPER(bool)) {
- symbol->const_value_bool = (bool*) malloc(sizeof(bool));
- *(symbol->const_value_bool) = *(symbol->l_exp->const_value_bool) == *(symbol->r_exp->const_value_bool);
- }
- if (DO_OPER(integer)) {
- symbol->const_value_bool = (bool*) malloc(sizeof(bool));
- *(symbol->const_value_bool) = *(symbol->l_exp->const_value_integer) == *(symbol->r_exp->const_value_integer);
- }
- if (DO_OPER(real)) {
- symbol->const_value_bool = (bool*) malloc(sizeof(bool));
- *(symbol->const_value_bool) = *(symbol->l_exp->const_value_real) == *(symbol->r_exp->const_value_real);
- }
-
+ DO_BIN_OPER(bool, ==);
+ DO_BIN_OPER(uint64, ==);
+ DO_BIN_OPER( int64, ==);
+ DO_BIN_OPER(real64, ==);
return NULL;
}
@@ -315,19 +369,10 @@
void *constant_folding_c::visit(notequ_expression_c *symbol) {
symbol->l_exp->accept(*this);
symbol->r_exp->accept(*this);
- if (DO_OPER(bool)) {
- symbol->const_value_bool = (bool*) malloc(sizeof(bool));
- *(symbol->const_value_bool) = *(symbol->l_exp->const_value_bool) != *(symbol->r_exp->const_value_bool);
- }
- if (DO_OPER(integer)) {
- symbol->const_value_bool = (bool*) malloc(sizeof(bool));
- *(symbol->const_value_bool) = *(symbol->l_exp->const_value_integer) != *(symbol->r_exp->const_value_integer);
- }
- if (DO_OPER(real)) {
- symbol->const_value_bool = (bool*) malloc(sizeof(bool));
- *(symbol->const_value_bool) = *(symbol->l_exp->const_value_real) != *(symbol->r_exp->const_value_real);
- }
-
+ DO_BIN_OPER(bool, !=);
+ DO_BIN_OPER(uint64, !=);
+ DO_BIN_OPER( int64, !=);
+ DO_BIN_OPER(real64, !=);
return NULL;
}
@@ -335,15 +380,10 @@
void *constant_folding_c::visit(lt_expression_c *symbol) {
symbol->l_exp->accept(*this);
symbol->r_exp->accept(*this);
- if (DO_OPER(integer)) {
- symbol->const_value_bool = (bool*) malloc(sizeof(bool));
- *(symbol->const_value_bool) = *(symbol->l_exp->const_value_integer) < *(symbol->r_exp->const_value_integer);
- }
- if (DO_OPER(real)) {
- symbol->const_value_bool = (bool*) malloc(sizeof(bool));
- *(symbol->const_value_bool) = *(symbol->l_exp->const_value_real) < *(symbol->r_exp->const_value_real);
- }
-
+ DO_BIN_OPER(bool, <);
+ DO_BIN_OPER(uint64, <);
+ DO_BIN_OPER( int64, <);
+ DO_BIN_OPER(real64, <);
return NULL;
}
@@ -351,15 +391,10 @@
void *constant_folding_c::visit(gt_expression_c *symbol) {
symbol->l_exp->accept(*this);
symbol->r_exp->accept(*this);
- if (DO_OPER(integer)) {
- symbol->const_value_bool = (bool*) malloc(sizeof(bool));
- *(symbol->const_value_bool) = *(symbol->l_exp->const_value_integer) > *(symbol->r_exp->const_value_integer);
- }
- if (DO_OPER(real)) {
- symbol->const_value_bool = (bool*) malloc(sizeof(bool));
- *(symbol->const_value_bool) = *(symbol->l_exp->const_value_real) > *(symbol->r_exp->const_value_real);
- }
-
+ DO_BIN_OPER(bool, >);
+ DO_BIN_OPER(uint64, >);
+ DO_BIN_OPER( int64, >);
+ DO_BIN_OPER(real64, >);
return NULL;
}
@@ -367,15 +402,10 @@
void *constant_folding_c::visit(le_expression_c *symbol) {
symbol->l_exp->accept(*this);
symbol->r_exp->accept(*this);
- if (DO_OPER(integer)) {
- symbol->const_value_bool = (bool*) malloc(sizeof(bool));
- *(symbol->const_value_bool) = *(symbol->l_exp->const_value_integer) <= *(symbol->r_exp->const_value_integer);
- }
- if (DO_OPER(real)) {
- symbol->const_value_bool = (bool*) malloc(sizeof(bool));
- *(symbol->const_value_bool) = *(symbol->l_exp->const_value_real) <= *(symbol->r_exp->const_value_real);
- }
-
+ DO_BIN_OPER(bool, <=);
+ DO_BIN_OPER(uint64, <=);
+ DO_BIN_OPER( int64, <=);
+ DO_BIN_OPER(real64, <=);
return NULL;
}
@@ -383,138 +413,99 @@
void *constant_folding_c::visit(ge_expression_c *symbol) {
symbol->l_exp->accept(*this);
symbol->r_exp->accept(*this);
- if (DO_OPER(integer)) {
- symbol->const_value_bool = (bool*) malloc(sizeof(bool));
- *(symbol->const_value_bool) = *(symbol->l_exp->const_value_integer) >= *(symbol->r_exp->const_value_integer);
- }
- if (DO_OPER(real)) {
- symbol->const_value_bool = (bool*) malloc(sizeof(bool));
- *(symbol->const_value_bool) = *(symbol->l_exp->const_value_real) >= *(symbol->r_exp->const_value_real);
- }
-
- return NULL;
-}
-
-
+ DO_BIN_OPER(bool, >=);
+ DO_BIN_OPER(uint64, >=);
+ DO_BIN_OPER( int64, >=);
+ DO_BIN_OPER(real64, >=);
+ return NULL;
+}
+
+
+#define CHECK_OVERFLOW_SUM(dtype)\
+ if (VALID_CVALUE(dtype, symbol)) \
+ if ((((std::numeric_limits< dtype##_t >::max() - GET_CVALUE(dtype, symbol->l_exp)) < (GET_CVALUE(dtype, symbol->r_exp))) ? 1 : 0) || \
+ (((std::numeric_limits< dtype##_t >::min() + GET_CVALUE(dtype, symbol->l_exp)) > (GET_CVALUE(dtype, symbol->r_exp))) ? 1 : 0)) \
+ SET_OVFLOW(dtype, symbol);
+#define CHECK_OVERFLOW_real64 \
+ if (VALID_CVALUE(real64, symbol)) \
+ /* NaN => underflow, overflow, number is a higher precision format, is a complex number (IEEE standard) */ \
+ if (isnan(GET_CVALUE(real64, symbol))) \
+ SET_OVFLOW(real64, symbol);
void *constant_folding_c::visit(add_expression_c *symbol) {
symbol->l_exp->accept(*this);
symbol->r_exp->accept(*this);
- if (DO_OPER(integer)) {
- if (CHECK_OVERFLOW_SUM(*(symbol->l_exp->const_value_integer), *(symbol->r_exp->const_value_integer), int64_t))
- STAGE3_ERROR(0, symbol, symbol, "Overflow in constant expression.");
- symbol->const_value_integer = (int64_t*) malloc(sizeof(int64_t));
- *(symbol->const_value_integer) = *(symbol->l_exp->const_value_integer) + *(symbol->r_exp->const_value_integer);
- }
- if (DO_OPER(real)) {
- symbol->const_value_real = (real64_t*) malloc(sizeof(real64_t));
- *(symbol->const_value_real) = *(symbol->l_exp->const_value_real) + *(symbol->r_exp->const_value_real);
- /*
- * According to the IEEE standard, NaN value is used as:
- * - representation of a number that has underflowed
- * - representation of number that has overflowed
- * - number is a higher precision format
- * - A complex number
- */
- if (isnan(*(symbol->const_value_real)))
- STAGE3_ERROR(0, symbol, symbol, "Overflow in constant expression.");
- }
-
- return NULL;
-}
-
-
+ DO_BIN_OPER(uint64, +);
+ DO_BIN_OPER( int64, +);
+ DO_BIN_OPER(real64, +);
+ CHECK_OVERFLOW_SUM(uint64);
+ CHECK_OVERFLOW_SUM( int64);
+ CHECK_OVERFLOW_real64;
+ return NULL;
+}
+
+
+#define CHECK_OVERFLOW_SUB(dtype)\
+ if (VALID_CVALUE(dtype, symbol)) \
+ if ((((std::numeric_limits< dtype##_t >::max() - GET_CVALUE(dtype, symbol->l_exp)) < (-GET_CVALUE(dtype, symbol->r_exp))) ? 1 : 0) || \
+ (((std::numeric_limits< dtype##_t >::min() + GET_CVALUE(dtype, symbol->l_exp)) > (-GET_CVALUE(dtype, symbol->r_exp))) ? 1 : 0)) \
+ SET_OVFLOW(dtype, symbol);
void *constant_folding_c::visit(sub_expression_c *symbol) {
symbol->l_exp->accept(*this);
symbol->r_exp->accept(*this);
- if (DO_OPER(integer)) {
- if (CHECK_OVERFLOW_SUB(*(symbol->l_exp->const_value_integer), *(symbol->r_exp->const_value_integer), int64_t))
- STAGE3_ERROR(0, symbol, symbol, "Overflow in constant expression.");
- symbol->const_value_integer = (int64_t*) malloc(sizeof(int64_t));
- *(symbol->const_value_integer) = *(symbol->l_exp->const_value_integer) - *(symbol->r_exp->const_value_integer);
- }
- if (DO_OPER(real)) {
- symbol->const_value_real = (real64_t*) malloc(sizeof(real64_t));
- *(symbol->const_value_real) = *(symbol->l_exp->const_value_real) - *(symbol->r_exp->const_value_real);
- /*
- * According to the IEEE standard, NaN value is used as:
- * - representation of a number that has underflowed
- * - representation of number that has overflowed
- * - number is a higher precision format
- * - A complex number
- */
- if (isnan(*(symbol->const_value_real)))
- STAGE3_ERROR(0, symbol, symbol, "Overflow in constant expression.");
- }
-
- return NULL;
-}
-
-
+ DO_BIN_OPER(uint64, -);
+ DO_BIN_OPER( int64, -);
+ DO_BIN_OPER(real64, -);
+ CHECK_OVERFLOW_SUB(uint64);
+ CHECK_OVERFLOW_SUB( int64);
+ CHECK_OVERFLOW_real64;
+ return NULL;
+}
+
+
+/* TODO!!! */
+#define CHECK_OVERFLOW_MUL(dtype)\
+ if (VALID_CVALUE(dtype, symbol)) \
+ if (false) \
+ SET_OVFLOW(dtype, symbol);
void *constant_folding_c::visit(mul_expression_c *symbol) {
symbol->l_exp->accept(*this);
symbol->r_exp->accept(*this);
- if (DO_OPER(integer)) {
- symbol->const_value_integer = (int64_t*) malloc(sizeof(int64_t));
- *(symbol->const_value_integer) = *(symbol->l_exp->const_value_integer) * *(symbol->r_exp->const_value_integer);
- }
- if (DO_OPER(real)) {
- symbol->const_value_real = (real64_t*) malloc(sizeof(real64_t));
- *(symbol->const_value_real) = *(symbol->l_exp->const_value_real) * *(symbol->r_exp->const_value_real);
- /*
- * According to the IEEE standard, NaN value is used as:
- * - representation of a number that has underflowed
- * - representation of number that has overflowed
- * - number is a higher precision format
- * - A complex number
- */
- if (isnan(*(symbol->const_value_real)))
- STAGE3_ERROR(0, symbol, symbol, "Overflow in constant expression.");
- }
-
- return NULL;
-}
-
-
+ DO_BIN_OPER(uint64, *);
+ DO_BIN_OPER( int64, *);
+ DO_BIN_OPER(real64, *);
+ CHECK_OVERFLOW_MUL(uint64);
+ CHECK_OVERFLOW_MUL( int64);
+ CHECK_OVERFLOW_real64;
+ return NULL;
+}
+
+
+
+/* TODO!!! */
+#define CHECK_OVERFLOW_DIV(dtype)\
+ if (VALID_CVALUE(dtype, symbol)) \
+ if (false) \
+ SET_OVFLOW(dtype, symbol);
void *constant_folding_c::visit(div_expression_c *symbol) {
symbol->l_exp->accept(*this);
symbol->r_exp->accept(*this);
- if (DO_OPER(integer)) {
- if (*(symbol->r_exp->const_value_integer) == 0)
- STAGE3_ERROR(0, symbol, symbol, "Division by zero in constant expression.");
- symbol->const_value_integer = (int64_t*) malloc(sizeof(int64_t));
- *(symbol->const_value_integer) = *(symbol->l_exp->const_value_integer) / *(symbol->r_exp->const_value_integer);
- }
- if (DO_OPER(real)) {
- if (*(symbol->r_exp->const_value_real) == 0)
- STAGE3_ERROR(0, symbol, symbol, "Division by zero in constant expression.");
- symbol->const_value_real = (real64_t*) malloc(sizeof(real64_t));
- *(symbol->const_value_real) = *(symbol->l_exp->const_value_real) / *(symbol->r_exp->const_value_real);
- /*
- * According to the IEEE standard, NaN value is used as:
- * - representation of a number that has underflowed
- * - representation of number that has overflowed
- * - number is a higher precision format
- * - A complex number
- */
- if (isnan(*(symbol->const_value_real)))
- STAGE3_ERROR(0, symbol, symbol, "Overflow in constant expression.");
- }
-
- return NULL;
-}
-
-
+ if (ISZERO_CVALUE(uint64, symbol->r_exp)) {NEW_CVALUE(uint64, symbol); SET_OVFLOW(uint64, symbol);} else {DO_BIN_OPER(uint64, /); CHECK_OVERFLOW_DIV(uint64)};
+ if (ISZERO_CVALUE( int64, symbol->r_exp)) {NEW_CVALUE( int64, symbol); SET_OVFLOW( int64, symbol);} else {DO_BIN_OPER( int64, /); CHECK_OVERFLOW_DIV( int64)};
+ if (ISZERO_CVALUE(real64, symbol->r_exp)) {NEW_CVALUE(real64, symbol); SET_OVFLOW(real64, symbol);} else {DO_BIN_OPER(real64, /); CHECK_OVERFLOW_real64;};
+ return NULL;
+}
+
+
+/* TODO!!! */
+#define CHECK_OVERFLOW_MOD(dtype)\
+ if (VALID_CVALUE(dtype, symbol)) \
+ if (false) \
+ SET_OVFLOW(dtype, symbol);
void *constant_folding_c::visit(mod_expression_c *symbol) {
symbol->l_exp->accept(*this);
symbol->r_exp->accept(*this);
- if (DO_OPER(integer)) {
- if (*(symbol->r_exp->const_value_integer) == 0)
- STAGE3_ERROR(0, symbol, symbol, "Division by zero in constant expression.");
- symbol->const_value_integer = (int64_t*) malloc(sizeof(int64_t));
- *(symbol->const_value_integer) = *(symbol->l_exp->const_value_integer) % *(symbol->r_exp->const_value_integer);
-
- }
-
+ if (ISZERO_CVALUE(uint64, symbol->r_exp)) {NEW_CVALUE(uint64, symbol); SET_OVFLOW(uint64, symbol);} else {DO_BIN_OPER(uint64, %); CHECK_OVERFLOW_MOD(uint64)};
+ if (ISZERO_CVALUE( int64, symbol->r_exp)) {NEW_CVALUE( int64, symbol); SET_OVFLOW( int64, symbol);} else {DO_BIN_OPER( int64, %); CHECK_OVERFLOW_MOD( int64)};
return NULL;
}
@@ -522,34 +513,40 @@
void *constant_folding_c::visit(power_expression_c *symbol) {
symbol->l_exp->accept(*this);
symbol->r_exp->accept(*this);
- if ((NULL != symbol->l_exp->const_value_real) && (NULL != symbol->r_exp->const_value_integer)) {
- symbol->const_value_real = (real64_t*) malloc(sizeof(real64_t));
- *(symbol->const_value_real) = pow(*(symbol->l_exp->const_value_real), *(symbol->r_exp->const_value_integer));
- /*
- * According to the IEEE standard, NaN value is used as:
- * - representation of a number that has underflowed
- * - representation of number that has overflowed
- * - number is a higher precision format
- * - A complex number
- */
- if (isnan(*(symbol->const_value_real)))
- STAGE3_ERROR(0, symbol, symbol, "Overflow in constant expression.");
- }
-
- return NULL;
-}
-
-
+ /* NOTE: If the const_value in symbol->r_exp is within the limits of both int64 and uint64, then we do both operations.
+ * That is OK, as the result should be identicial (we do create an unnecessary CVALUE variable, but who cares?).
+ * If only one is valid, then that is the oper we will do!
+ */
+ if (VALID_CVALUE(real64, symbol->l_exp) && VALID_CVALUE( int64, symbol->r_exp)) {
+ NEW_CVALUE(real64, symbol);
+ SET_CVALUE(real64, symbol, pow(GET_CVALUE(real64, symbol->l_exp), GET_CVALUE( int64, symbol->r_exp)));
+ }
+ if (VALID_CVALUE(real64, symbol->l_exp) && VALID_CVALUE(uint64, symbol->r_exp)) {
+ NEW_CVALUE(real64, symbol);
+ SET_CVALUE(real64, symbol, pow(GET_CVALUE(real64, symbol->l_exp), GET_CVALUE(uint64, symbol->r_exp)));
+ }
+ CHECK_OVERFLOW_real64;
+ return NULL;
+}
+
+
+/* TODO!!! */
+#define CHECK_OVERFLOW_NEG(dtype)\
+ if (VALID_CVALUE(dtype, symbol)) \
+ if (false) \
+ SET_OVFLOW(dtype, symbol);
void *constant_folding_c::visit(neg_expression_c *symbol) {
symbol->exp->accept(*this);
- if (NULL != symbol->exp->const_value_integer) {
- symbol->const_value_integer = (int64_t*) malloc(sizeof(int64_t));
- *(symbol->const_value_integer) = - *(symbol->exp->const_value_integer);
- }
- if (NULL != symbol->exp->const_value_real) {
- symbol->const_value_real = (real64_t*) malloc(sizeof(real64_t));
- *(symbol->const_value_real) = - *(symbol->exp->const_value_real);
- }
+ if (VALID_CVALUE( int64, symbol->exp)) {
+ NEW_CVALUE( int64, symbol);
+ SET_CVALUE( int64, symbol, - GET_CVALUE( int64, symbol->exp));
+ }
+ if (VALID_CVALUE(real64, symbol->exp)) {
+ NEW_CVALUE(real64, symbol);
+ SET_CVALUE(real64, symbol, - GET_CVALUE(real64, symbol->exp));
+ }
+ CHECK_OVERFLOW_NEG( int64);
+ CHECK_OVERFLOW_real64;
return NULL;
}
@@ -557,13 +554,15 @@
void *constant_folding_c::visit(not_expression_c *symbol) {
symbol->exp->accept(*this);
- if (NULL != symbol->exp->const_value_bool) {
- symbol->const_value_bool = (bool*) malloc(sizeof(bool));
- *(symbol->const_value_bool) = !*(symbol->exp->const_value_bool);
- }
-
- return NULL;
-}
-
-
-
+ if (VALID_CVALUE( bool, symbol->exp)) {
+ NEW_CVALUE( bool, symbol);
+ SET_CVALUE( bool, symbol, ! GET_CVALUE( bool, symbol->exp));
+ }
+ if (VALID_CVALUE(uint64, symbol->exp)) {
+ NEW_CVALUE(uint64, symbol);
+ SET_CVALUE(uint64, symbol, ~ GET_CVALUE(uint64, symbol->exp));
+ }
+ return NULL;
+}
+
+