stage3/array_range_check.cc
changeset 592 99a284cec1f2
parent 585 be7330d9b65c
child 594 c8092e909886
equal deleted inserted replaced
591:76bad7199896 592:99a284cec1f2
    42  *
    42  *
    43  */
    43  */
    44 
    44 
    45 
    45 
    46 #include "array_range_check.hh"
    46 #include "array_range_check.hh"
       
    47 #include <limits>  // required for std::numeric_limits<XXX>
       
    48 
    47 
    49 
    48 #define FIRST_(symbol1, symbol2) (((symbol1)->first_order < (symbol2)->first_order)   ? (symbol1) : (symbol2))
    50 #define FIRST_(symbol1, symbol2) (((symbol1)->first_order < (symbol2)->first_order)   ? (symbol1) : (symbol2))
    49 #define  LAST_(symbol1, symbol2) (((symbol1)->last_order  > (symbol2)->last_order)    ? (symbol1) : (symbol2))
    51 #define  LAST_(symbol1, symbol2) (((symbol1)->last_order  > (symbol2)->last_order)    ? (symbol1) : (symbol2))
    50 
    52 
    51 #define STAGE3_ERROR(error_level, symbol1, symbol2, ...) {                                                                  \
    53 #define STAGE3_ERROR(error_level, symbol1, symbol2, ...) {                                                                  \
    77 array_range_check_c::array_range_check_c(symbol_c *ignore) {
    79 array_range_check_c::array_range_check_c(symbol_c *ignore) {
    78 	error_count = 0;
    80 	error_count = 0;
    79 	current_display_error_level = 0;
    81 	current_display_error_level = 0;
    80 }
    82 }
    81 
    83 
       
    84 
       
    85 
    82 array_range_check_c::~array_range_check_c(void) {
    86 array_range_check_c::~array_range_check_c(void) {
    83 }
    87 }
       
    88 
       
    89 
    84 
    90 
    85 int array_range_check_c::get_error_count() {
    91 int array_range_check_c::get_error_count() {
    86 	return error_count;
    92 	return error_count;
    87 }
    93 }
       
    94 
       
    95 
    88 
    96 
    89 void array_range_check_c::check_dimension_count(array_variable_c *symbol) {
    97 void array_range_check_c::check_dimension_count(array_variable_c *symbol) {
    90 	int dimension_count;
    98 	int dimension_count;
    91 	symbol_c *var_decl;
    99 	symbol_c *var_decl;
    92 
   100 
    94 	array_dimension_iterator_c array_dimension_iterator(var_decl);
   102 	array_dimension_iterator_c array_dimension_iterator(var_decl);
    95 	for (dimension_count = 0; NULL != array_dimension_iterator.next(); dimension_count++);
   103 	for (dimension_count = 0; NULL != array_dimension_iterator.next(); dimension_count++);
    96 	if (dimension_count != ((list_c *)symbol->subscript_list)->n)
   104 	if (dimension_count != ((list_c *)symbol->subscript_list)->n)
    97 		STAGE3_ERROR(0, symbol, symbol, "Number of subscripts/indexes does not match the number of subscripts/indexes in the array's declaration (array has %d indexes)", dimension_count);
   105 		STAGE3_ERROR(0, symbol, symbol, "Number of subscripts/indexes does not match the number of subscripts/indexes in the array's declaration (array has %d indexes)", dimension_count);
    98 }
   106 }
       
   107 
       
   108 
    99 
   109 
   100 void array_range_check_c::check_bounds(array_variable_c *symbol) {
   110 void array_range_check_c::check_bounds(array_variable_c *symbol) {
   101   list_c *l; /* the subscript_list */
   111   list_c *l; /* the subscript_list */
   102   symbol_c *var_decl;
   112   symbol_c *var_decl;
   103 
   113 
   126       if ( GET_CVALUE(uint64, l->elements[i])   >  GET_CVALUE(uint64, dimension->upper_limit))
   136       if ( GET_CVALUE(uint64, l->elements[i])   >  GET_CVALUE(uint64, dimension->upper_limit))
   127       {STAGE3_ERROR(0, symbol, symbol, "Array access out of bounds."); continue;}
   137       {STAGE3_ERROR(0, symbol, symbol, "Array access out of bounds."); continue;}
   128   }
   138   }
   129 }
   139 }
   130 
   140 
       
   141 
       
   142 
       
   143 
       
   144 
       
   145 
       
   146 
       
   147 
       
   148 
       
   149 /*************************/
       
   150 /* B.1 - Common elements */
       
   151 /*************************/
       
   152 /**********************/
       
   153 /* B.1.3 - Data types */
       
   154 /**********************/
       
   155 /********************************/
       
   156 /* B 1.3.3 - Derived data types */
       
   157 /********************************/
       
   158 
       
   159 /*  signed_integer DOTDOT signed_integer */
       
   160 /* dimension will be filled in during stage 3 (array_range_check_c) with the number of elements in this subrange */
       
   161 // SYM_REF2(subrange_c, lower_limit, upper_limit, unsigned long long int dimension)
       
   162 void *array_range_check_c::visit(subrange_c *symbol) {
       
   163 	unsigned long long int dimension = 0; // we use unsigned long long instead of uint64_t since it might just happen to be larger than uint64_t in the platform used for compiling this code!!
       
   164 
       
   165 /* Determine the size of the array... */
       
   166 	if        (VALID_CVALUE( int64, symbol->upper_limit) && VALID_CVALUE( int64, symbol->lower_limit)) {  
       
   167 		// do the sums in such a way that no overflow is possible... even during intermediate steps used by compiler!
       
   168 		// remember that the result (dimension) is unsigned, while the operands are signed!!
       
   169 		// dimension = GET_CVALUE( int64, symbol->upper_limit) - VALID_CVALUE( int64, symbol->lower_limit);
       
   170 		if (VALID_CVALUE( int64, symbol->lower_limit) >= 0) {
       
   171 			dimension = GET_CVALUE( int64, symbol->upper_limit) - GET_CVALUE( int64, symbol->lower_limit);
       
   172 		} else {
       
   173 			dimension  = -GET_CVALUE( int64, symbol->lower_limit);
       
   174 			dimension +=  GET_CVALUE( int64, symbol->upper_limit);     
       
   175 		}
       
   176 	} else if (VALID_CVALUE(uint64, symbol->upper_limit) && VALID_CVALUE(uint64, symbol->lower_limit)) {
       
   177 		dimension = GET_CVALUE(uint64, symbol->upper_limit) - VALID_CVALUE(uint64, symbol->lower_limit); 
       
   178 	} else if (VALID_CVALUE(uint64, symbol->upper_limit) && VALID_CVALUE( int64, symbol->lower_limit)) {
       
   179 		if (VALID_CVALUE( int64, symbol->lower_limit) >= 0) {
       
   180 			dimension = GET_CVALUE( int64, symbol->upper_limit) - GET_CVALUE( int64, symbol->lower_limit);
       
   181 		} else {
       
   182 		unsigned long long int lower_ull;
       
   183 		lower_ull  = -GET_CVALUE( int64, symbol->lower_limit);
       
   184 		dimension  =  GET_CVALUE( int64, symbol->upper_limit) + lower_ull;     
       
   185 		/* TODO: check this overflow test, it does not seem to be working. I don't have to go now... Will check later. */
       
   186 		if (dimension < lower_ull)
       
   187 			STAGE3_ERROR(0, symbol, symbol, "Number of elements in array subrange exceeds maximum number of elements (%llu).", std::numeric_limits< unsigned long long int >::max());
       
   188 		}
       
   189 	} else ERROR;
       
   190 
       
   191 	/* correct value for dimension is actually ---> dimension = upper_limit - lower_limit + 1
       
   192 	 * Up to now, we have only determined dimension = upper_limit - lower_limit
       
   193 	 * We must first check whether this last increment will cause an overflow!
       
   194 	 */
       
   195 	if (dimension == std::numeric_limits< unsigned long long int >::max())
       
   196 		STAGE3_ERROR(0, symbol, symbol, "Number of elements in array subrange exceeds maximum number of elements (%llu).", std::numeric_limits< unsigned long long int >::max());
       
   197 	
       
   198 	/* correct value for dimension is actually ---> dimension = upper_limit - lower_limit + 1 */
       
   199 	dimension++; 
       
   200 	
       
   201 	symbol->dimension = dimension;
       
   202 	return NULL;
       
   203 }
       
   204 
       
   205 
   131 /*********************/
   206 /*********************/
   132 /* B 1.4 - Variables */
   207 /* B 1.4 - Variables */
   133 /*********************/
   208 /*********************/
   134 /*************************************/
   209 /*************************************/
   135 /* B 1.4.2 - Multi-element variables */
   210 /* B 1.4.2 - Multi-element variables */
   145 /* B 1.5 - Program organisation units */
   220 /* B 1.5 - Program organisation units */
   146 /**************************************/
   221 /**************************************/
   147 /***********************/
   222 /***********************/
   148 /* B 1.5.1 - Functions */
   223 /* B 1.5.1 - Functions */
   149 /***********************/
   224 /***********************/
       
   225 // SYM_REF4(function_declaration_c, derived_function_name, type_name, var_declarations_list, function_body)
   150 void *array_range_check_c::visit(function_declaration_c *symbol) {
   226 void *array_range_check_c::visit(function_declaration_c *symbol) {
       
   227 	symbol->var_declarations_list->accept(*this); // required for visiting subrange_c
   151 	search_varfb_instance_type = new search_varfb_instance_type_c(symbol);
   228 	search_varfb_instance_type = new search_varfb_instance_type_c(symbol);
   152 	// search_var_instance_decl = new search_var_instance_decl_c(symbol);
   229 	// search_var_instance_decl = new search_var_instance_decl_c(symbol);
   153 	symbol->function_body->accept(*this);
   230 	symbol->function_body->accept(*this);
   154 	delete search_varfb_instance_type;
   231 	delete search_varfb_instance_type;
   155 	// delete search_var_instance_decl;
   232 	// delete search_var_instance_decl;
   159 }
   236 }
   160 
   237 
   161 /*****************************/
   238 /*****************************/
   162 /* B 1.5.2 - Function blocks */
   239 /* B 1.5.2 - Function blocks */
   163 /*****************************/
   240 /*****************************/
       
   241 // SYM_REF3(function_block_declaration_c, fblock_name, var_declarations, fblock_body)
   164 void *array_range_check_c::visit(function_block_declaration_c *symbol) {
   242 void *array_range_check_c::visit(function_block_declaration_c *symbol) {
       
   243 	symbol->var_declarations->accept(*this); // required for visiting subrange_c
   165 	search_varfb_instance_type = new search_varfb_instance_type_c(symbol);
   244 	search_varfb_instance_type = new search_varfb_instance_type_c(symbol);
   166 	// search_var_instance_decl = new search_var_instance_decl_c(symbol);
   245 	// search_var_instance_decl = new search_var_instance_decl_c(symbol);
   167 	symbol->fblock_body->accept(*this);
   246 	symbol->fblock_body->accept(*this);
   168 	delete search_varfb_instance_type;
   247 	delete search_varfb_instance_type;
   169 	// delete search_var_instance_decl;
   248 	// delete search_var_instance_decl;
   173 }
   252 }
   174 
   253 
   175 /**********************/
   254 /**********************/
   176 /* B 1.5.3 - Programs */
   255 /* B 1.5.3 - Programs */
   177 /**********************/
   256 /**********************/
       
   257 // SYM_REF3(program_declaration_c, program_type_name, var_declarations, function_block_body)
   178 void *array_range_check_c::visit(program_declaration_c *symbol) {
   258 void *array_range_check_c::visit(program_declaration_c *symbol) {
       
   259 	symbol->var_declarations->accept(*this); // required for visiting subrange_c
   179 	search_varfb_instance_type = new search_varfb_instance_type_c(symbol);
   260 	search_varfb_instance_type = new search_varfb_instance_type_c(symbol);
   180 	// search_var_instance_decl = new search_var_instance_decl_c(symbol);
   261 	// search_var_instance_decl = new search_var_instance_decl_c(symbol);
   181 	symbol->function_block_body->accept(*this);
   262 	symbol->function_block_body->accept(*this);
   182 	delete search_varfb_instance_type;
   263 	delete search_varfb_instance_type;
   183 	// delete search_var_instance_decl;
   264 	// delete search_var_instance_decl;