stage3/array_range_check.cc
changeset 592 99a284cec1f2
parent 585 be7330d9b65c
child 594 c8092e909886
--- a/stage3/array_range_check.cc	Wed Jun 13 14:21:30 2012 +0100
+++ b/stage3/array_range_check.cc	Wed Jun 13 19:43:12 2012 +0100
@@ -44,6 +44,8 @@
 
 
 #include "array_range_check.hh"
+#include <limits>  // required for std::numeric_limits<XXX>
+
 
 #define FIRST_(symbol1, symbol2) (((symbol1)->first_order < (symbol2)->first_order)   ? (symbol1) : (symbol2))
 #define  LAST_(symbol1, symbol2) (((symbol1)->last_order  > (symbol2)->last_order)    ? (symbol1) : (symbol2))
@@ -79,13 +81,19 @@
 	current_display_error_level = 0;
 }
 
+
+
 array_range_check_c::~array_range_check_c(void) {
 }
 
+
+
 int array_range_check_c::get_error_count() {
 	return error_count;
 }
 
+
+
 void array_range_check_c::check_dimension_count(array_variable_c *symbol) {
 	int dimension_count;
 	symbol_c *var_decl;
@@ -97,6 +105,8 @@
 		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);
 }
 
+
+
 void array_range_check_c::check_bounds(array_variable_c *symbol) {
   list_c *l; /* the subscript_list */
   symbol_c *var_decl;
@@ -128,6 +138,71 @@
   }
 }
 
+
+
+
+
+
+
+
+
+/*************************/
+/* B.1 - Common elements */
+/*************************/
+/**********************/
+/* B.1.3 - Data types */
+/**********************/
+/********************************/
+/* B 1.3.3 - Derived data types */
+/********************************/
+
+/*  signed_integer DOTDOT signed_integer */
+/* dimension will be filled in during stage 3 (array_range_check_c) with the number of elements in this subrange */
+// SYM_REF2(subrange_c, lower_limit, upper_limit, unsigned long long int dimension)
+void *array_range_check_c::visit(subrange_c *symbol) {
+	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!!
+
+/* Determine the size of the array... */
+	if        (VALID_CVALUE( int64, symbol->upper_limit) && VALID_CVALUE( int64, symbol->lower_limit)) {  
+		// do the sums in such a way that no overflow is possible... even during intermediate steps used by compiler!
+		// remember that the result (dimension) is unsigned, while the operands are signed!!
+		// dimension = GET_CVALUE( int64, symbol->upper_limit) - VALID_CVALUE( int64, symbol->lower_limit);
+		if (VALID_CVALUE( int64, symbol->lower_limit) >= 0) {
+			dimension = GET_CVALUE( int64, symbol->upper_limit) - GET_CVALUE( int64, symbol->lower_limit);
+		} else {
+			dimension  = -GET_CVALUE( int64, symbol->lower_limit);
+			dimension +=  GET_CVALUE( int64, symbol->upper_limit);     
+		}
+	} else if (VALID_CVALUE(uint64, symbol->upper_limit) && VALID_CVALUE(uint64, symbol->lower_limit)) {
+		dimension = GET_CVALUE(uint64, symbol->upper_limit) - VALID_CVALUE(uint64, symbol->lower_limit); 
+	} else if (VALID_CVALUE(uint64, symbol->upper_limit) && VALID_CVALUE( int64, symbol->lower_limit)) {
+		if (VALID_CVALUE( int64, symbol->lower_limit) >= 0) {
+			dimension = GET_CVALUE( int64, symbol->upper_limit) - GET_CVALUE( int64, symbol->lower_limit);
+		} else {
+		unsigned long long int lower_ull;
+		lower_ull  = -GET_CVALUE( int64, symbol->lower_limit);
+		dimension  =  GET_CVALUE( int64, symbol->upper_limit) + lower_ull;     
+		/* TODO: check this overflow test, it does not seem to be working. I don't have to go now... Will check later. */
+		if (dimension < lower_ull)
+			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());
+		}
+	} else ERROR;
+
+	/* correct value for dimension is actually ---> dimension = upper_limit - lower_limit + 1
+	 * Up to now, we have only determined dimension = upper_limit - lower_limit
+	 * We must first check whether this last increment will cause an overflow!
+	 */
+	if (dimension == std::numeric_limits< unsigned long long int >::max())
+		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());
+	
+	/* correct value for dimension is actually ---> dimension = upper_limit - lower_limit + 1 */
+	dimension++; 
+	
+	symbol->dimension = dimension;
+	return NULL;
+}
+
+
 /*********************/
 /* B 1.4 - Variables */
 /*********************/
@@ -147,7 +222,9 @@
 /***********************/
 /* B 1.5.1 - Functions */
 /***********************/
+// SYM_REF4(function_declaration_c, derived_function_name, type_name, var_declarations_list, function_body)
 void *array_range_check_c::visit(function_declaration_c *symbol) {
+	symbol->var_declarations_list->accept(*this); // required for visiting subrange_c
 	search_varfb_instance_type = new search_varfb_instance_type_c(symbol);
 	// search_var_instance_decl = new search_var_instance_decl_c(symbol);
 	symbol->function_body->accept(*this);
@@ -161,7 +238,9 @@
 /*****************************/
 /* B 1.5.2 - Function blocks */
 /*****************************/
+// SYM_REF3(function_block_declaration_c, fblock_name, var_declarations, fblock_body)
 void *array_range_check_c::visit(function_block_declaration_c *symbol) {
+	symbol->var_declarations->accept(*this); // required for visiting subrange_c
 	search_varfb_instance_type = new search_varfb_instance_type_c(symbol);
 	// search_var_instance_decl = new search_var_instance_decl_c(symbol);
 	symbol->fblock_body->accept(*this);
@@ -175,7 +254,9 @@
 /**********************/
 /* B 1.5.3 - Programs */
 /**********************/
+// SYM_REF3(program_declaration_c, program_type_name, var_declarations, function_block_body)
 void *array_range_check_c::visit(program_declaration_c *symbol) {
+	symbol->var_declarations->accept(*this); // required for visiting subrange_c
 	search_varfb_instance_type = new search_varfb_instance_type_c(symbol);
 	// search_var_instance_decl = new search_var_instance_decl_c(symbol);
 	symbol->function_block_body->accept(*this);