stage3/constant_folding.cc
changeset 577 f578f14cb97f
parent 576 8368ec909825
child 578 70c0456affca
equal deleted inserted replaced
576:8368ec909825 577:f578f14cb97f
   176 #define SET_OVFLOW(dtype, symbol)             ((symbol)->const_value_##dtype->status) = symbol_c::cs_overflow
   176 #define SET_OVFLOW(dtype, symbol)             ((symbol)->const_value_##dtype->status) = symbol_c::cs_overflow
   177     /* 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! */
   177     /* 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! */
   178 #define VALID_CVALUE(dtype, symbol)           ((NULL != (symbol)->const_value_##dtype) && (symbol_c::cs_const_value == (symbol)->const_value_##dtype->status))
   178 #define VALID_CVALUE(dtype, symbol)           ((NULL != (symbol)->const_value_##dtype) && (symbol_c::cs_const_value == (symbol)->const_value_##dtype->status))
   179 #define ISZERO_CVALUE(dtype, symbol)          ((VALID_CVALUE(dtype, symbol)) && (GET_CVALUE(dtype, symbol) == 0))
   179 #define ISZERO_CVALUE(dtype, symbol)          ((VALID_CVALUE(dtype, symbol)) && (GET_CVALUE(dtype, symbol) == 0))
   180 
   180 
   181 #define DO_BINARY_OPER(dtype, oper)\
   181 #define DO_BINARY_OPER(dtype, oper, otype)\
   182 	if (VALID_CVALUE(dtype, symbol->r_exp) && VALID_CVALUE(dtype, symbol->l_exp)) {                                \
   182 	if (VALID_CVALUE(dtype, symbol->r_exp) && VALID_CVALUE(dtype, symbol->l_exp)) {                                \
   183 		NEW_CVALUE(dtype, symbol);                                                                             \
   183 		NEW_CVALUE(dtype, symbol);                                                                             \
   184 		SET_CVALUE(dtype, symbol, GET_CVALUE(dtype, symbol->l_exp) oper GET_CVALUE(dtype, symbol->r_exp));     \
   184 		SET_CVALUE(otype, symbol, GET_CVALUE(dtype, symbol->l_exp) oper GET_CVALUE(dtype, symbol->r_exp));     \
   185 	}
   185 	}
   186 
   186 
   187 #define DO_UNARY_OPER(dtype, oper, arg)\
   187 #define DO_UNARY_OPER(dtype, oper, arg)\
   188 	if (VALID_CVALUE(dtype, arg)) {                                                                                \
   188 	if (VALID_CVALUE(dtype, arg)) {                                                                                \
   189 		NEW_CVALUE(dtype, symbol);                                                                             \
   189 		NEW_CVALUE(dtype, symbol);                                                                             \
   494 /* B 3.1 - Expressions */
   494 /* B 3.1 - Expressions */
   495 /***********************/
   495 /***********************/
   496 void *constant_folding_c::visit(or_expression_c *symbol) {
   496 void *constant_folding_c::visit(or_expression_c *symbol) {
   497 	symbol->l_exp->accept(*this);
   497 	symbol->l_exp->accept(*this);
   498 	symbol->r_exp->accept(*this);
   498 	symbol->r_exp->accept(*this);
   499 	DO_BINARY_OPER(bool,   ||);
   499 	DO_BINARY_OPER(  bool, ||, bool);
   500 	DO_BINARY_OPER(uint64, | );
   500 	DO_BINARY_OPER(uint64, | , bool);
   501 	return NULL;
   501 	return NULL;
   502 }
   502 }
   503 
   503 
   504 
   504 
   505 void *constant_folding_c::visit(xor_expression_c *symbol) {
   505 void *constant_folding_c::visit(xor_expression_c *symbol) {
   506 	symbol->l_exp->accept(*this);
   506 	symbol->l_exp->accept(*this);
   507 	symbol->r_exp->accept(*this);
   507 	symbol->r_exp->accept(*this);
   508 	DO_BINARY_OPER(bool,   ^);
   508 	DO_BINARY_OPER(  bool, ^, bool);
   509 	DO_BINARY_OPER(uint64, ^);
   509 	DO_BINARY_OPER(uint64, ^, uint64);
   510 	return NULL;
   510 	return NULL;
   511 }
   511 }
   512 
   512 
   513 
   513 
   514 void *constant_folding_c::visit(and_expression_c *symbol) {
   514 void *constant_folding_c::visit(and_expression_c *symbol) {
   515 	symbol->l_exp->accept(*this);
   515 	symbol->l_exp->accept(*this);
   516 	symbol->r_exp->accept(*this);
   516 	symbol->r_exp->accept(*this);
   517 	DO_BINARY_OPER(bool,   &&);
   517 	DO_BINARY_OPER(  bool, &&, bool);
   518 	DO_BINARY_OPER(uint64, & );
   518 	DO_BINARY_OPER(uint64, & , uint64);
   519 	return NULL;
   519 	return NULL;
   520 }
   520 }
   521 
   521 
   522 
   522 
   523 void *constant_folding_c::visit(equ_expression_c *symbol) {
   523 void *constant_folding_c::visit(equ_expression_c *symbol) {
   524 	symbol->l_exp->accept(*this);
   524 	symbol->l_exp->accept(*this);
   525 	symbol->r_exp->accept(*this);
   525 	symbol->r_exp->accept(*this);
   526 	DO_BINARY_OPER(bool,   ==);
   526 	DO_BINARY_OPER(  bool, ==, bool);
   527 	DO_BINARY_OPER(uint64, ==);
   527 	DO_BINARY_OPER(uint64, ==, bool);
   528 	DO_BINARY_OPER( int64, ==);
   528 	DO_BINARY_OPER( int64, ==, bool);
   529 	DO_BINARY_OPER(real64, ==);
   529 	DO_BINARY_OPER(real64, ==, bool);
   530 	return NULL;
   530 	return NULL;
   531 }
   531 }
   532 
   532 
   533 
   533 
   534 void *constant_folding_c::visit(notequ_expression_c *symbol) {
   534 void *constant_folding_c::visit(notequ_expression_c *symbol) {
   535 	symbol->l_exp->accept(*this);
   535 	symbol->l_exp->accept(*this);
   536 	symbol->r_exp->accept(*this);
   536 	symbol->r_exp->accept(*this);
   537 	DO_BINARY_OPER(bool,   !=);
   537 	DO_BINARY_OPER(  bool, !=, bool);
   538 	DO_BINARY_OPER(uint64, !=);
   538 	DO_BINARY_OPER(uint64, !=, bool);
   539 	DO_BINARY_OPER( int64, !=);
   539 	DO_BINARY_OPER( int64, !=, bool);
   540 	DO_BINARY_OPER(real64, !=);
   540 	DO_BINARY_OPER(real64, !=, bool);
   541 	return NULL;
   541 	return NULL;
   542 }
   542 }
   543 
   543 
   544 
   544 
   545 void *constant_folding_c::visit(lt_expression_c *symbol) {
   545 void *constant_folding_c::visit(lt_expression_c *symbol) {
   546 	symbol->l_exp->accept(*this);
   546 	symbol->l_exp->accept(*this);
   547 	symbol->r_exp->accept(*this);
   547 	symbol->r_exp->accept(*this);
   548 	DO_BINARY_OPER(bool,   <);
   548 	DO_BINARY_OPER(  bool, <, bool);
   549 	DO_BINARY_OPER(uint64, <);
   549 	DO_BINARY_OPER(uint64, <, bool);
   550 	DO_BINARY_OPER( int64, <);
   550 	DO_BINARY_OPER( int64, <, bool);
   551 	DO_BINARY_OPER(real64, <);
   551 	DO_BINARY_OPER(real64, <, bool);
   552 	return NULL;
   552 	return NULL;
   553 }
   553 }
   554 
   554 
   555 
   555 
   556 void *constant_folding_c::visit(gt_expression_c *symbol) {
   556 void *constant_folding_c::visit(gt_expression_c *symbol) {
   557 	symbol->l_exp->accept(*this);
   557 	symbol->l_exp->accept(*this);
   558 	symbol->r_exp->accept(*this);
   558 	symbol->r_exp->accept(*this);
   559 	DO_BINARY_OPER(bool,   >);
   559 	DO_BINARY_OPER(  bool, >, bool);
   560 	DO_BINARY_OPER(uint64, >);
   560 	DO_BINARY_OPER(uint64, >, bool);
   561 	DO_BINARY_OPER( int64, >);
   561 	DO_BINARY_OPER( int64, >, bool);
   562 	DO_BINARY_OPER(real64, >);
   562 	DO_BINARY_OPER(real64, >, bool);
   563 	return NULL;
   563 	return NULL;
   564 }
   564 }
   565 
   565 
   566 
   566 
   567 void *constant_folding_c::visit(le_expression_c *symbol) {
   567 void *constant_folding_c::visit(le_expression_c *symbol) {
   568 	symbol->l_exp->accept(*this);
   568 	symbol->l_exp->accept(*this);
   569 	symbol->r_exp->accept(*this);
   569 	symbol->r_exp->accept(*this);
   570 	DO_BINARY_OPER(bool,   <=);
   570 	DO_BINARY_OPER(  bool, <=, bool);
   571 	DO_BINARY_OPER(uint64, <=);
   571 	DO_BINARY_OPER(uint64, <=, bool);
   572 	DO_BINARY_OPER( int64, <=);
   572 	DO_BINARY_OPER( int64, <=, bool);
   573 	DO_BINARY_OPER(real64, <=);
   573 	DO_BINARY_OPER(real64, <=, bool);
   574 	return NULL;
   574 	return NULL;
   575 }
   575 }
   576 
   576 
   577 
   577 
   578 void *constant_folding_c::visit(ge_expression_c *symbol) {
   578 void *constant_folding_c::visit(ge_expression_c *symbol) {
   579 	symbol->l_exp->accept(*this);
   579 	symbol->l_exp->accept(*this);
   580 	symbol->r_exp->accept(*this);
   580 	symbol->r_exp->accept(*this);
   581 	DO_BINARY_OPER(bool,   >=);
   581 	DO_BINARY_OPER(  bool, >=, bool);
   582 	DO_BINARY_OPER(uint64, >=);
   582 	DO_BINARY_OPER(uint64, >=, bool);
   583 	DO_BINARY_OPER( int64, >=);
   583 	DO_BINARY_OPER( int64, >=, bool);
   584 	DO_BINARY_OPER(real64, >=);
   584 	DO_BINARY_OPER(real64, >=, bool);
   585 	return NULL;
   585 	return NULL;
   586 }
   586 }
   587 
   587 
   588 
   588 
   589 void *constant_folding_c::visit(add_expression_c *symbol) {
   589 void *constant_folding_c::visit(add_expression_c *symbol) {
   590 	symbol->l_exp->accept(*this);
   590 	symbol->l_exp->accept(*this);
   591 	symbol->r_exp->accept(*this);
   591 	symbol->r_exp->accept(*this);
   592 	DO_BINARY_OPER(uint64, +);   CHECK_OVERFLOW_uint64_SUM(symbol, symbol->l_exp, symbol->r_exp);
   592 	DO_BINARY_OPER(uint64, +, uint64);   CHECK_OVERFLOW_uint64_SUM(symbol, symbol->l_exp, symbol->r_exp);
   593 	DO_BINARY_OPER( int64, +);   CHECK_OVERFLOW_int64_SUM (symbol, symbol->l_exp, symbol->r_exp);
   593 	DO_BINARY_OPER( int64, +,  int64);   CHECK_OVERFLOW_int64_SUM (symbol, symbol->l_exp, symbol->r_exp);
   594 	DO_BINARY_OPER(real64, +);   CHECK_OVERFLOW_real64    (symbol);
   594 	DO_BINARY_OPER(real64, +, real64);   CHECK_OVERFLOW_real64    (symbol);
   595 	return NULL;
   595 	return NULL;
   596 }
   596 }
   597 
   597 
   598 
   598 
   599 void *constant_folding_c::visit(sub_expression_c *symbol) {
   599 void *constant_folding_c::visit(sub_expression_c *symbol) {
   600 	symbol->l_exp->accept(*this);
   600 	symbol->l_exp->accept(*this);
   601 	symbol->r_exp->accept(*this);
   601 	symbol->r_exp->accept(*this);
   602 	DO_BINARY_OPER(uint64, -);   CHECK_OVERFLOW_uint64_SUB(symbol, symbol->l_exp, symbol->r_exp);
   602 	DO_BINARY_OPER(uint64, -, uint64);   CHECK_OVERFLOW_uint64_SUB(symbol, symbol->l_exp, symbol->r_exp);
   603 	DO_BINARY_OPER( int64, -);   CHECK_OVERFLOW_int64_SUB (symbol, symbol->l_exp, symbol->r_exp);
   603 	DO_BINARY_OPER( int64, -,  int64);   CHECK_OVERFLOW_int64_SUB (symbol, symbol->l_exp, symbol->r_exp);
   604 	DO_BINARY_OPER(real64, -);   CHECK_OVERFLOW_real64    (symbol);
   604 	DO_BINARY_OPER(real64, -, real64);   CHECK_OVERFLOW_real64    (symbol);
   605 	return NULL;
   605 	return NULL;
   606 }
   606 }
   607 
   607 
   608 
   608 
   609 void *constant_folding_c::visit(mul_expression_c *symbol) {
   609 void *constant_folding_c::visit(mul_expression_c *symbol) {
   610 	symbol->l_exp->accept(*this);
   610 	symbol->l_exp->accept(*this);
   611 	symbol->r_exp->accept(*this);
   611 	symbol->r_exp->accept(*this);
   612 	DO_BINARY_OPER(uint64, *);   CHECK_OVERFLOW_uint64_MUL(symbol, symbol->l_exp, symbol->r_exp);
   612 	DO_BINARY_OPER(uint64, *, uint64);   CHECK_OVERFLOW_uint64_MUL(symbol, symbol->l_exp, symbol->r_exp);
   613 	DO_BINARY_OPER( int64, *);   CHECK_OVERFLOW_int64_MUL (symbol, symbol->l_exp, symbol->r_exp);
   613 	DO_BINARY_OPER( int64, *,  int64);   CHECK_OVERFLOW_int64_MUL (symbol, symbol->l_exp, symbol->r_exp);
   614 	DO_BINARY_OPER(real64, *);   CHECK_OVERFLOW_real64    (symbol);
   614 	DO_BINARY_OPER(real64, *, real64);   CHECK_OVERFLOW_real64    (symbol);
   615 	return NULL;
   615 	return NULL;
   616 }
   616 }
   617 
   617 
   618 
   618 
   619 
   619 
   620 void *constant_folding_c::visit(div_expression_c *symbol) {
   620 void *constant_folding_c::visit(div_expression_c *symbol) {
   621 	symbol->l_exp->accept(*this);
   621 	symbol->l_exp->accept(*this);
   622 	symbol->r_exp->accept(*this);
   622 	symbol->r_exp->accept(*this);
   623 	if (ISZERO_CVALUE(uint64, symbol->r_exp))  {NEW_CVALUE(uint64, symbol); SET_OVFLOW(uint64, symbol);} else {DO_BINARY_OPER(uint64, /); CHECK_OVERFLOW_uint64_DIV(symbol, symbol->l_exp, symbol->r_exp);};
   623 	if (ISZERO_CVALUE(uint64, symbol->r_exp))  {NEW_CVALUE(uint64, symbol); SET_OVFLOW(uint64, symbol);} else {DO_BINARY_OPER(uint64, /, uint64); CHECK_OVERFLOW_uint64_DIV(symbol, symbol->l_exp, symbol->r_exp);};
   624 	if (ISZERO_CVALUE( int64, symbol->r_exp))  {NEW_CVALUE( int64, symbol); SET_OVFLOW( int64, symbol);} else {DO_BINARY_OPER( int64, /); CHECK_OVERFLOW_int64_DIV(symbol, symbol->l_exp, symbol->r_exp);};
   624 	if (ISZERO_CVALUE( int64, symbol->r_exp))  {NEW_CVALUE( int64, symbol); SET_OVFLOW( int64, symbol);} else {DO_BINARY_OPER( int64, /,  int64); CHECK_OVERFLOW_int64_DIV(symbol, symbol->l_exp, symbol->r_exp);};
   625 	if (ISZERO_CVALUE(real64, symbol->r_exp))  {NEW_CVALUE(real64, symbol); SET_OVFLOW(real64, symbol);} else {DO_BINARY_OPER(real64, /); CHECK_OVERFLOW_real64(symbol);};
   625 	if (ISZERO_CVALUE(real64, symbol->r_exp))  {NEW_CVALUE(real64, symbol); SET_OVFLOW(real64, symbol);} else {DO_BINARY_OPER(real64, /, real64); CHECK_OVERFLOW_real64(symbol);};
   626 	return NULL;
   626 	return NULL;
   627 }
   627 }
   628 
   628 
   629 
   629 
   630 void *constant_folding_c::visit(mod_expression_c *symbol) {
   630 void *constant_folding_c::visit(mod_expression_c *symbol) {
   634 	 *  IF (IN2 = 0) THEN OUT:=0 ; ELSE OUT:=IN1 - (IN1/IN2)*IN2 ; END_IF
   634 	 *  IF (IN2 = 0) THEN OUT:=0 ; ELSE OUT:=IN1 - (IN1/IN2)*IN2 ; END_IF
   635 	 *
   635 	 *
   636 	 * Note that, when IN1 = INT64_MIN, and IN2 = -1, an overflow occurs in the division,
   636 	 * Note that, when IN1 = INT64_MIN, and IN2 = -1, an overflow occurs in the division,
   637 	 * so although the MOD operation should be OK, acording to the above definition, we actually have an overflow!!
   637 	 * so although the MOD operation should be OK, acording to the above definition, we actually have an overflow!!
   638 	 */
   638 	 */
   639 	if (ISZERO_CVALUE(uint64, symbol->r_exp))  {NEW_CVALUE(uint64, symbol); SET_CVALUE(uint64, symbol, 0);} else {DO_BINARY_OPER(uint64, %); CHECK_OVERFLOW_uint64_MOD(symbol, symbol->l_exp, symbol->r_exp);};
   639 	if (ISZERO_CVALUE(uint64, symbol->r_exp))  {NEW_CVALUE(uint64, symbol); SET_CVALUE(uint64, symbol, 0);} else {DO_BINARY_OPER(uint64, %, uint64); CHECK_OVERFLOW_uint64_MOD(symbol, symbol->l_exp, symbol->r_exp);};
   640 	if (ISZERO_CVALUE( int64, symbol->r_exp))  {NEW_CVALUE( int64, symbol); SET_CVALUE( int64, symbol, 0);} else {DO_BINARY_OPER( int64, %); CHECK_OVERFLOW_int64_MOD(symbol, symbol->l_exp, symbol->r_exp);};
   640 	if (ISZERO_CVALUE( int64, symbol->r_exp))  {NEW_CVALUE( int64, symbol); SET_CVALUE( int64, symbol, 0);} else {DO_BINARY_OPER( int64, %,  int64); CHECK_OVERFLOW_int64_MOD(symbol, symbol->l_exp, symbol->r_exp);};
   641 	return NULL;
   641 	return NULL;
   642 }
   642 }
   643 
   643 
   644 
   644 
   645 void *constant_folding_c::visit(power_expression_c *symbol) {
   645 void *constant_folding_c::visit(power_expression_c *symbol) {