stage3/constant_folding.cc
changeset 596 4efb11e44065
parent 592 99a284cec1f2
child 600 f5d4e9f91513
equal deleted inserted replaced
595:c41975a290ce 596:4efb11e44065
   119 #include "constant_folding.hh"
   119 #include "constant_folding.hh"
   120 #include <limits>
   120 #include <limits>
   121 #include <math.h> /* required for pow function, and HUGE_VAL, HUGE_VALF, HUGE_VALL */
   121 #include <math.h> /* required for pow function, and HUGE_VAL, HUGE_VALF, HUGE_VALL */
   122 #include <stdlib.h> /* required for malloc() */
   122 #include <stdlib.h> /* required for malloc() */
   123 
   123 
       
   124 
       
   125 #include <string.h>  /* required for strlen() */
       
   126 // #include <stdlib.h>  /* required for atoi() */
       
   127 #include <errno.h>   /* required for errno */
       
   128 
       
   129 
       
   130 
   124 #define __STDC_LIMIT_MACROS /* required for UINT64_MAX, INT64_MAX, INT64_MIN, ... */
   131 #define __STDC_LIMIT_MACROS /* required for UINT64_MAX, INT64_MAX, INT64_MIN, ... */
   125 #include <stdint.h>         /* required for UINT64_MAX, INT64_MAX, INT64_MIN, ... */
   132 #include <stdint.h>         /* required for UINT64_MAX, INT64_MAX, INT64_MIN, ... */
   126 
   133 
   127 
   134 
   128 
   135 
   213 		SET_CVALUE(dtype, symbol, oper GET_CVALUE(dtype, arg));                                                \
   220 		SET_CVALUE(dtype, symbol, oper GET_CVALUE(dtype, arg));                                                \
   214 	}
   221 	}
   215 
   222 
   216 
   223 
   217 
   224 
       
   225 
       
   226 
       
   227 /***********************************************************************/
       
   228 /***********************************************************************/
       
   229 /***********************************************************************/
       
   230 /***            convert string to numerical value                    ***/
       
   231 /***********************************************************************/
       
   232 /***********************************************************************/
       
   233 /***********************************************************************/
       
   234 
       
   235 
       
   236 
       
   237   /* To allow the compiler to be portable, we cannot assume that int64_t is mapped onto long long int,
       
   238    * so we cannot call strtoll() and strtoull() in extract_int64() and extract_uint64().
       
   239    *
       
   240    * So, we create our own strtouint64() and strtoint64() functions.
       
   241    * (We actually call them matiec_strtoint64() so they will not clash with any function
       
   242    *  that may be added to the standard library in the future).
       
   243    * We actually create several of each, and let the compiler choose which is the correct one,
       
   244    * by having it resolve the call to the overloaded function. For the C++ compiler to be able
       
   245    * to resolve this ambiguity, we need to add a dummy parameter to each function!
       
   246    *
       
   247    * TODO: support platforms in which int64_t is mapped onto int !! Is this really needed?
       
   248    */
       
   249 static  int64_t matiec_strtoint64 (         long      int *dummy, const char *nptr, char **endptr, int base) {return strtol  (nptr, endptr, base);}
       
   250 static  int64_t matiec_strtoint64 (         long long int *dummy, const char *nptr, char **endptr, int base) {return strtoll (nptr, endptr, base);}
       
   251   
       
   252 static uint64_t matiec_strtouint64(unsigned long      int *dummy, const char *nptr, char **endptr, int base) {return strtoul (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 
       
   255 
       
   256 /* extract the value of an integer from an integer_c object !! */
       
   257 /* NOTE: it must ignore underscores! */
       
   258 int64_t extract_int64_value(symbol_c *sym, bool *overflow) {
       
   259   std::string str = "";
       
   260   integer_c *integer;
       
   261   char *endptr;
       
   262   int64_t ret;
       
   263 
       
   264   if ((integer = dynamic_cast<integer_c *>(sym)) == NULL) ERROR;
       
   265   for(unsigned int i = 0; i < strlen(integer->value); i++)
       
   266     if (integer->value[i] != '_')  str += integer->value[i];
       
   267 
       
   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);
       
   270   if (overflow != NULL)
       
   271     *overflow = (errno == ERANGE);
       
   272   if ((errno != 0) && (errno != ERANGE))
       
   273     ERROR;
       
   274 
       
   275   return ret;
       
   276 }
       
   277 
       
   278 uint64_t extract_uint64_value(symbol_c *sym, bool *overflow) {
       
   279   std::string str = "";
       
   280   integer_c *integer;
       
   281   neg_integer_c * neg_integer;
       
   282   char *endptr;
       
   283   uint64_t ret;
       
   284   
       
   285   if ((integer = dynamic_cast<integer_c *>(sym)) == NULL) ERROR;
       
   286   for(unsigned int i = 0; i < strlen(integer->value); i++)
       
   287     if (integer->value[i] != '_')  str += integer->value[i];
       
   288 
       
   289   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);
       
   291   if (overflow != NULL)
       
   292     *overflow = (errno == ERANGE);
       
   293   if ((errno != 0) && (errno != ERANGE))
       
   294     ERROR;
       
   295 
       
   296   return ret;
       
   297 }
       
   298 
       
   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 
       
   320 
       
   321 /* extract the value of a real from an real_c object !! */
       
   322 /* NOTE: it must ignore underscores! */
       
   323 /* From iec_bison.yy
       
   324  *  real:
       
   325  *   real_token		{$$ = new real_c($1, locloc(@$));}
       
   326  * | fixed_point_token	{$$ = new real_c($1, locloc(@$));}
       
   327  *
       
   328  * From iec_flex.ll
       
   329  * {real}			{yylval.ID=strdup(yytext); return real_token;}
       
   330  * {fixed_point}		{yylval.ID=strdup(yytext); return fixed_point_token;}
       
   331  *
       
   332  * real		{integer}\.{integer}{exponent}
       
   333  * fixed_point		{integer}\.{integer}
       
   334  * exponent        [Ee]([+-]?){integer}
       
   335  * integer         {digit}((_?{digit})*)
       
   336  */
       
   337 real64_t extract_real_value(symbol_c *sym, bool *overflow) {
       
   338   std::string str = "";
       
   339   real_c * real_sym;
       
   340   real64_t ret;
       
   341 
       
   342   if ((real_sym = dynamic_cast<real_c *>(sym)) == NULL) ERROR;
       
   343   for(unsigned int i = 0; i < strlen(real_sym->value); i++)
       
   344     if (real_sym->value[i] != '_') str += real_sym->value[i];
       
   345     
       
   346   errno = 0; // since strtoXX() may legally return 0, we must set errno to 0 to detect errors correctly!
       
   347   #if    (real64_t  == float)
       
   348     ret = strtof(str.c_str(), NULL);
       
   349   #elif  (real64_t  == double)
       
   350     ret = strtod(str.c_str(), NULL);
       
   351   #elif  (real64_t  == long_double)
       
   352     ret = strtold(str.c_str(), NULL);
       
   353   #else 
       
   354     #error Could not determine which data type is being used for real64_t (defined in absyntax.hh). Aborting!
       
   355   #endif
       
   356   if (overflow != NULL)
       
   357     *overflow = (errno == ERANGE);
       
   358   if ((errno != 0) && (errno != ERANGE)) 
       
   359     ERROR;
       
   360 
       
   361   return ret;
       
   362 }
       
   363 
       
   364 
       
   365 
       
   366 
       
   367 
       
   368 /***********************************************************************/
       
   369 /***********************************************************************/
       
   370 /***********************************************************************/
       
   371 /***        Functions to check for overflow situation                ***/
       
   372 /***********************************************************************/
       
   373 /***********************************************************************/
       
   374 /***********************************************************************/
   218 
   375 
   219 
   376 
   220 /* NOTE:
   377 /* NOTE:
   221  *   Most of the conditions to detect overflows on signed and unsigned integer operations were adapted from
   378  *   Most of the conditions to detect overflows on signed and unsigned integer operations were adapted from
   222  *   https://www.securecoding.cert.org/confluence/display/seccode/INT32-C.+Ensure+that+operations+on+signed+integers+do+not+result+in+overflow?showComments=false
   379  *   https://www.securecoding.cert.org/confluence/display/seccode/INT32-C.+Ensure+that+operations+on+signed+integers+do+not+result+in+overflow?showComments=false
   381 
   538 
   382 
   539 
   383 
   540 
   384 
   541 
   385 
   542 
   386 
   543 /***********************************************************************/
       
   544 /***********************************************************************/
       
   545 /***********************************************************************/
       
   546 /***        The constant_folding_c                                   ***/
       
   547 /***********************************************************************/
       
   548 /***********************************************************************/
       
   549 /***********************************************************************/
   387 
   550 
   388 
   551 
   389 
   552 
   390 
   553 
   391 
   554