stage3/constant_folding.cc
changeset 600 f5d4e9f91513
parent 596 4efb11e44065
child 601 683ae5444237
equal deleted inserted replaced
599:60f3edcf6a8f 600:f5d4e9f91513
   253 static uint64_t matiec_strtouint64(unsigned long long int *dummy, const char *nptr, char **endptr, int base) {return strtoull(nptr, endptr, base);}
   253 static uint64_t matiec_strtouint64(unsigned long long int *dummy, const char *nptr, char **endptr, int base) {return strtoull(nptr, endptr, base);}
   254 
   254 
   255 
   255 
   256 /* extract the value of an integer from an integer_c object !! */
   256 /* extract the value of an integer from an integer_c object !! */
   257 /* NOTE: it must ignore underscores! */
   257 /* NOTE: it must ignore underscores! */
   258 int64_t extract_int64_value(symbol_c *sym, bool *overflow) {
   258 int64_t extract_int64_value(symbol_c *sym, int base, bool *overflow) {
   259   std::string str = "";
   259   std::string str = "";
   260   integer_c *integer;
   260   integer_c *integer;
   261   char *endptr;
   261   char *endptr;
   262   int64_t ret;
   262   int64_t ret;
   263 
   263 
   264   if ((integer = dynamic_cast<integer_c *>(sym)) == NULL) ERROR;
   264   if ((integer = dynamic_cast<integer_c *>(sym)) == NULL) ERROR;
   265   for(unsigned int i = 0; i < strlen(integer->value); i++)
   265   for(unsigned int i = 0; i < strlen(integer->value); i++)
   266     if (integer->value[i] != '_')  str += integer->value[i];
   266     if (integer->value[i] != '_')  str += integer->value[i];
   267 
   267 
   268   errno = 0; // since strtoXX() may legally return 0, we must set errno to 0 to detect errors correctly!
   268   errno = 0; // since strtoXX() may legally return 0, we must set errno to 0 to detect errors correctly!
   269   ret = matiec_strtoint64((int64_t *)NULL, str.c_str(), &endptr, 10);
   269   ret = matiec_strtoint64((int64_t *)NULL, str.c_str(), &endptr, base);
   270   if (overflow != NULL)
   270   if (overflow != NULL)
   271     *overflow = (errno == ERANGE);
   271     *overflow = (errno == ERANGE);
   272   if ((errno != 0) && (errno != ERANGE))
   272   if (((errno != 0) && (errno != ERANGE)) || (*endptr != '\0'))
   273     ERROR;
   273     ERROR;
   274 
   274 
   275   return ret;
   275   return ret;
   276 }
   276 }
   277 
   277 
   278 uint64_t extract_uint64_value(symbol_c *sym, bool *overflow) {
   278 uint64_t extract_uint64_value(symbol_c *sym, int base, bool *overflow) {
   279   std::string str = "";
   279   std::string str = "";
   280   integer_c *integer;
   280   integer_c *integer;
   281   neg_integer_c * neg_integer;
       
   282   char *endptr;
   281   char *endptr;
   283   uint64_t ret;
   282   uint64_t ret;
   284   
   283   
   285   if ((integer = dynamic_cast<integer_c *>(sym)) == NULL) ERROR;
   284   if ((integer = dynamic_cast<integer_c *>(sym)) == NULL) ERROR;
   286   for(unsigned int i = 0; i < strlen(integer->value); i++)
   285   for(unsigned int i = 0; i < strlen(integer->value); i++)
   287     if (integer->value[i] != '_')  str += integer->value[i];
   286     if (integer->value[i] != '_')  str += integer->value[i];
   288 
   287 
   289   errno = 0; // since strtoXX() may legally return 0, we must set errno to 0 to detect errors correctly!
   288   errno = 0; // since strtoXX() may legally return 0, we must set errno to 0 to detect errors correctly!
   290   ret = matiec_strtouint64((uint64_t *)NULL, str.c_str(), &endptr, 10);
   289   ret = matiec_strtouint64((uint64_t *)NULL, str.c_str(), &endptr, base);
   291   if (overflow != NULL)
   290   if (overflow != NULL)
   292     *overflow = (errno == ERANGE);
   291     *overflow = (errno == ERANGE);
   293   if ((errno != 0) && (errno != ERANGE))
   292   if (((errno != 0) && (errno != ERANGE)) || (*endptr != '\0'))
   294     ERROR;
   293     ERROR;
   295 
   294 
   296   return ret;
   295   return ret;
   297 }
   296 }
   298 
   297 
   299 
       
   300 
       
   301 /* extract the value of an hex integer from an hex_integer_c object !! */
       
   302 /* NOTE: it must ignore underscores! */
       
   303 uint64_t extract_hex_value(symbol_c *sym) {
       
   304   std::string str = "";
       
   305   char *endptr;
       
   306   hex_integer_c * hex_integer;
       
   307   uint64_t ret;
       
   308 
       
   309   if ((hex_integer = dynamic_cast<hex_integer_c *>(sym)) == NULL) ERROR;
       
   310   for(unsigned int i = 3; i < strlen(hex_integer->value); i++)
       
   311     if (hex_integer->value[i] != '_') str += hex_integer->value[i];
       
   312     
       
   313   errno = 0; // since strtoXX() may legally return 0, we must set errno to 0 to detect errors correctly!
       
   314   ret = strtoull(str.c_str(), &endptr, 16);
       
   315   if (errno != 0) ERROR;
       
   316 
       
   317   return ret;
       
   318 }
       
   319 
   298 
   320 
   299 
   321 /* extract the value of a real from an real_c object !! */
   300 /* extract the value of a real from an real_c object !! */
   322 /* NOTE: it must ignore underscores! */
   301 /* NOTE: it must ignore underscores! */
   323 /* From iec_bison.yy
   302 /* From iec_bison.yy
   334  * exponent        [Ee]([+-]?){integer}
   313  * exponent        [Ee]([+-]?){integer}
   335  * integer         {digit}((_?{digit})*)
   314  * integer         {digit}((_?{digit})*)
   336  */
   315  */
   337 real64_t extract_real_value(symbol_c *sym, bool *overflow) {
   316 real64_t extract_real_value(symbol_c *sym, bool *overflow) {
   338   std::string str = "";
   317   std::string str = "";
   339   real_c * real_sym;
   318   real_c *real_sym;
       
   319   char   *endptr;
   340   real64_t ret;
   320   real64_t ret;
   341 
   321 
   342   if ((real_sym = dynamic_cast<real_c *>(sym)) == NULL) ERROR;
   322   if ((real_sym = dynamic_cast<real_c *>(sym)) == NULL) ERROR;
   343   for(unsigned int i = 0; i < strlen(real_sym->value); i++)
   323   for(unsigned int i = 0; i < strlen(real_sym->value); i++)
   344     if (real_sym->value[i] != '_') str += real_sym->value[i];
   324     if (real_sym->value[i] != '_') str += real_sym->value[i];
   345     
   325     
   346   errno = 0; // since strtoXX() may legally return 0, we must set errno to 0 to detect errors correctly!
   326   errno = 0; // since strtoXX() may legally return 0, we must set errno to 0 to detect errors correctly!
   347   #if    (real64_t  == float)
   327   #if    (real64_t  == float)
   348     ret = strtof(str.c_str(), NULL);
   328     ret = strtof(str.c_str(),  &endptr);
   349   #elif  (real64_t  == double)
   329   #elif  (real64_t  == double)
   350     ret = strtod(str.c_str(), NULL);
   330     ret = strtod(str.c_str(),  &endptr);
   351   #elif  (real64_t  == long_double)
   331   #elif  (real64_t  == long_double)
   352     ret = strtold(str.c_str(), NULL);
   332     ret = strtold(str.c_str(), &endptr);
   353   #else 
   333   #else 
   354     #error Could not determine which data type is being used for real64_t (defined in absyntax.hh). Aborting!
   334     #error Could not determine which data type is being used for real64_t (defined in absyntax.hh). Aborting!
   355   #endif
   335   #endif
   356   if (overflow != NULL)
   336   if (overflow != NULL)
   357     *overflow = (errno == ERANGE);
   337     *overflow = (errno == ERANGE);
   358   if ((errno != 0) && (errno != ERANGE)) 
   338   if (((errno != 0) && (errno != ERANGE)) || (*endptr != '\0'))
   359     ERROR;
   339     ERROR;
   360 
   340 
   361   return ret;
   341   return ret;
   362 }
   342 }
   363 
   343 
   591 }
   571 }
   592 
   572 
   593 
   573 
   594 void *constant_folding_c::visit(integer_c *symbol) {
   574 void *constant_folding_c::visit(integer_c *symbol) {
   595 	bool overflow;
   575 	bool overflow;
   596 	NEW_CVALUE( int64, symbol);	SET_CVALUE( int64, symbol, extract_int64_value(symbol, &overflow));
   576 	NEW_CVALUE( int64, symbol);	SET_CVALUE( int64, symbol, extract_int64_value (symbol, 10, &overflow));
   597 	if (overflow) SET_OVFLOW(int64, symbol);
   577 	if (overflow) SET_OVFLOW(int64, symbol);
   598 	NEW_CVALUE(uint64, symbol);	SET_CVALUE(uint64, symbol, extract_uint64_value(symbol, &overflow));
   578 	NEW_CVALUE(uint64, symbol);	SET_CVALUE(uint64, symbol, extract_uint64_value(symbol, 10, &overflow));
   599 	if (overflow) SET_OVFLOW(uint64, symbol);
   579 	if (overflow) SET_OVFLOW(uint64, symbol);
   600 	return NULL;
   580 	return NULL;
   601 }
   581 }
   602 
   582 
   603 
   583 
   616 	/* NOTE 1: INT64_MIN = -(INT64_MAX + 1)   ---> assuming two's complement representation!!!
   596 	/* NOTE 1: INT64_MIN = -(INT64_MAX + 1)   ---> assuming two's complement representation!!!
   617 	 * NOTE 2: if the user happens to want INT_MIN, that value will first be parsed as a positive integer, before being negated here.
   597 	 * NOTE 2: if the user happens to want INT_MIN, that value will first be parsed as a positive integer, before being negated here.
   618 	 * However, the positive value cannot be stored inside an int64! So, in this case, we will get the value from the uint64 cvalue.
   598 	 * However, the positive value cannot be stored inside an int64! So, in this case, we will get the value from the uint64 cvalue.
   619 	 */
   599 	 */
   620 	// if (INT64_MIN == -INT64_MAX - 1) // We do not really need to check that the platform uses two's complement
   600 	// if (INT64_MIN == -INT64_MAX - 1) // We do not really need to check that the platform uses two's complement
   621 	if (VALID_CVALUE(uint64, symbol->exp) && (GET_CVALUE(uint64, symbol->exp) == -INT64_MIN)) {
   601 	if (VALID_CVALUE(uint64, symbol->exp) && (GET_CVALUE(uint64, symbol->exp) == -INT64_MIN)) { // How do we stop the compiler from complaining about a comparison between int and unsigned int?
   622 		NEW_CVALUE(int64, symbol); // in principle, if the above condition is true, then no new cvalue was created by DO_UNARY_OPER(). Not that it would be a problem to create a new one!
   602 		NEW_CVALUE(int64, symbol); // in principle, if the above condition is true, then no new cvalue was created by DO_UNARY_OPER(). Not that it would be a problem to create a new one!
   623 		SET_CVALUE(int64, symbol, INT64_MIN);
   603 		SET_CVALUE(int64, symbol, INT64_MIN);
   624 	}
   604 	}
   625 	return NULL;
   605 	return NULL;
   626 }
   606 }
   627 
   607 
   628 
   608 
   629 void *constant_folding_c::visit(binary_integer_c *symbol) {
   609 void *constant_folding_c::visit(binary_integer_c *symbol) {
       
   610 	bool overflow;
       
   611 	NEW_CVALUE( int64, symbol);	SET_CVALUE( int64, symbol, extract_int64_value (symbol,  2, &overflow));
       
   612 	if (overflow) SET_OVFLOW(int64, symbol);
       
   613 	NEW_CVALUE(uint64, symbol);	SET_CVALUE(uint64, symbol, extract_uint64_value(symbol,  2, &overflow));
       
   614 	if (overflow) SET_OVFLOW(uint64, symbol);
   630 	return NULL;
   615 	return NULL;
   631 }
   616 }
   632 
   617 
   633 
   618 
   634 void *constant_folding_c::visit(octal_integer_c *symbol) {
   619 void *constant_folding_c::visit(octal_integer_c *symbol) {
       
   620 	bool overflow;
       
   621 	NEW_CVALUE( int64, symbol);	SET_CVALUE( int64, symbol, extract_int64_value (symbol,  8, &overflow));
       
   622 	if (overflow) SET_OVFLOW(int64, symbol);
       
   623 	NEW_CVALUE(uint64, symbol);	SET_CVALUE(uint64, symbol, extract_uint64_value(symbol,  8, &overflow));
       
   624 	if (overflow) SET_OVFLOW(uint64, symbol);
   635 	return NULL;
   625 	return NULL;
   636 }
   626 }
   637 
   627 
   638 
   628 
   639 void *constant_folding_c::visit(hex_integer_c *symbol) {
   629 void *constant_folding_c::visit(hex_integer_c *symbol) {
   640 	NEW_CVALUE( int64, symbol);	SET_CVALUE( int64, symbol, extract_hex_value(symbol));
   630 	bool overflow;
   641 	NEW_CVALUE(uint64, symbol);	SET_CVALUE(uint64, symbol, extract_hex_value(symbol));
   631 	NEW_CVALUE( int64, symbol);	SET_CVALUE( int64, symbol, extract_int64_value (symbol, 16, &overflow));
       
   632 	if (overflow) SET_OVFLOW(int64, symbol);
       
   633 	NEW_CVALUE(uint64, symbol);	SET_CVALUE(uint64, symbol, extract_uint64_value(symbol, 16, &overflow));
       
   634 	if (overflow) SET_OVFLOW(uint64, symbol);
   642 	return NULL;
   635 	return NULL;
   643 }
   636 }
   644 
   637 
   645 
   638 
   646 /*
   639 /*