stage3/narrow_candidate_datatypes.cc
changeset 836 149398f525a7
parent 834 783ef40344dd
child 838 13ea7c080018
equal deleted inserted replaced
835:182036ed6475 836:149398f525a7
  1080 
  1080 
  1081 
  1081 
  1082 /*******************/
  1082 /*******************/
  1083 /* B 2.2 Operators */
  1083 /* B 2.2 Operators */
  1084 /*******************/
  1084 /*******************/
       
  1085 /* Sets the datatype of the il_operand, and calls it recursively!
       
  1086  * 
       
  1087  * NOTE 1: the il_operand __may__ be pointing to a parenthesized list of IL instructions. 
       
  1088  * e.g.  LD 33
       
  1089  *       AND ( 45
       
  1090  *            OR 56
       
  1091  *            )
       
  1092  *       When we handle the first 'AND' IL_operator, the il_operand will point to an simple_instr_list_c.
       
  1093  *       In this case, when we call il_operand->accept(*this);, the prev_il_instruction pointer will be overwritten!
       
  1094  *
       
  1095  *       So, if yoy wish to set the prev_il_instruction->datatype = symbol->datatype;
       
  1096  *       do it __before__ calling set_il_operand_datatype() (which in turn calls il_operand->accept(*this)) !!
       
  1097  */
       
  1098 void *narrow_candidate_datatypes_c::set_il_operand_datatype(symbol_c *il_operand, symbol_c *datatype) {
       
  1099 	if (NULL == il_operand) return NULL; /* if no IL operand => error in the source code!! */
       
  1100 
       
  1101 	/* If il_operand already has a non-NULL datatype (remember, narrow algorithm runs twice over IL lists!),
       
  1102 	 * but narrow algorithm has not yet been able to determine what datatype it should take? This is strange,
       
  1103 	 * and most probably an error!
       
  1104 	 */
       
  1105 	if ((NULL != il_operand->datatype) && (NULL == datatype))
       
  1106 		ERROR;
       
  1107 
       
  1108 	/* If the il_operand's datatype has already been set previously, and
       
  1109 	 * the narrow algorithm has already determined the datatype the il_operand should take!
       
  1110 	 *   ...we just make sure that the new datatype is the same as the current il_operand's datatype
       
  1111 	 */
       
  1112 	if ((NULL != il_operand->datatype)  && (NULL != datatype)) {
       
  1113 		/* Only one of the two datatypes is an invalid_type_name_c? This implies they are diferent!! */
       
  1114 		if ((!get_datatype_info_c::is_type_valid(datatype)) ^ ((!get_datatype_info_c::is_type_valid(il_operand->datatype)))) ERROR;
       
  1115 		/* OK, so both the datatypes are valid, but are they equal? */
       
  1116 		if ( !get_datatype_info_c::is_type_equal(il_operand->datatype, datatype)) ERROR; 
       
  1117 		/* The datatypes are the same. We have nothing to do, so we simply return! */
       
  1118 		return NULL;
       
  1119 	}
       
  1120 
       
  1121 	/* Set the il_operand's datatype. Note that the new 'datatype' may even be NULL!!! */
       
  1122 	il_operand->datatype = datatype;
       
  1123 	/* Even if we are not able to determine the il_operand's datatype ('datatype' is NULL), we still visit it recursively,
       
  1124 	 * to give a chance of any complex expressions embedded in the il_operand (e.g. expressions inside array subscripts!) 
       
  1125 	 * to be narrowed too.
       
  1126 	 */
       
  1127 	il_operand->accept(*this);
       
  1128 	return NULL;
       
  1129 }
       
  1130 
       
  1131 
       
  1132 
       
  1133 
  1085 void *narrow_candidate_datatypes_c::narrow_binary_operator(const struct widen_entry widen_table[], symbol_c *symbol, bool *deprecated_operation) {
  1134 void *narrow_candidate_datatypes_c::narrow_binary_operator(const struct widen_entry widen_table[], symbol_c *symbol, bool *deprecated_operation) {
  1086 	symbol_c *prev_instruction_type, *operand_type;
  1135 	symbol_c *prev_instruction_type, *operand_type;
  1087 	int count = 0;
  1136 	int count = 0;
  1088 
       
  1089 	if (NULL == symbol->datatype)
       
  1090 		/* next IL instructions were unable to determine the datatype this instruction should produce */
       
  1091 		return NULL;
       
  1092 
  1137 
  1093         if (NULL != deprecated_operation)
  1138         if (NULL != deprecated_operation)
  1094 		*deprecated_operation = false;
  1139 		*deprecated_operation = false;
  1095 
  1140 
  1096 	if (NULL == il_operand) return NULL; /* if no IL operand => error in the source code!! */
  1141 	if (NULL == il_operand) return NULL; /* if no IL operand => error in the source code!! */
  1108 	 *
  1153 	 *
  1109 	 * NOTE 2: We do not need to call prev_il_instruction->accept(*this), as the object to which prev_il_instruction
  1154 	 * NOTE 2: We do not need to call prev_il_instruction->accept(*this), as the object to which prev_il_instruction
  1110 	 *         is pointing to will be later narrowed by the call from the for() loop of the instruction_list_c
  1155 	 *         is pointing to will be later narrowed by the call from the for() loop of the instruction_list_c
  1111 	 *         (or simple_instr_list_c), which iterates backwards.
  1156 	 *         (or simple_instr_list_c), which iterates backwards.
  1112 	 */
  1157 	 */
  1113 	for(unsigned int i = 0; i < fake_prev_il_instruction->candidate_datatypes.size(); i++) {
  1158 	if (NULL != symbol->datatype) { // next IL instructions were able to determine the datatype this instruction should produce
  1114 		for(unsigned int j = 0; j < il_operand->candidate_datatypes.size(); j++) {
  1159 		for(unsigned int i = 0; i < fake_prev_il_instruction->candidate_datatypes.size(); i++) {
  1115 			prev_instruction_type = fake_prev_il_instruction->candidate_datatypes[i];
  1160 			for(unsigned int j = 0; j < il_operand->candidate_datatypes.size(); j++) {
  1116 			operand_type = il_operand->candidate_datatypes[j];
  1161 				prev_instruction_type = fake_prev_il_instruction->candidate_datatypes[i];
  1117 			if (is_widening_compatible(widen_table, prev_instruction_type, operand_type, symbol->datatype, deprecated_operation)) {
  1162 				operand_type = il_operand->candidate_datatypes[j];
  1118 				/* set the desired datatype of the previous il instruction */
  1163 				if (is_widening_compatible(widen_table, prev_instruction_type, operand_type, symbol->datatype, deprecated_operation)) {
  1119 				set_datatype_in_prev_il_instructions(prev_instruction_type, fake_prev_il_instruction);
  1164 					/* set the desired datatype of the previous il instruction */
  1120 				/* set the datatype for the operand */
  1165 					set_datatype_in_prev_il_instructions(prev_instruction_type, fake_prev_il_instruction);
  1121 				il_operand->datatype = operand_type;
  1166 					/* set the datatype for the operand */
  1122 				il_operand->accept(*this);
  1167 					set_il_operand_datatype(il_operand, operand_type);
  1123 				
  1168 					
  1124 				/* NOTE: DO NOT search any further! Return immediately!
  1169 					/* NOTE: DO NOT search any further! Return immediately!
  1125 				 * Since we support SAFE*** datatypes, multiple entries in the widen_table may be compatible.
  1170 					 * Since we support SAFE*** datatypes, multiple entries in the widen_table may be compatible.
  1126 				 * If we try to set more than one distinct datatype on the same symbol, then the datatype will be set to
  1171 					 * If we try to set more than one distinct datatype on the same symbol, then the datatype will be set to
  1127 				 * an invalid_datatype, which is NOT what we want!
  1172 					 * an invalid_datatype, which is NOT what we want!
  1128 				 */
  1173 					 */
  1129 				return NULL;
  1174 					return NULL;
       
  1175 				}
  1130 			}
  1176 			}
  1131 		}
  1177 		}
  1132 	}
  1178 	}
       
  1179 	/* We were not able to determine the required datatype, but we still give the il_operand a chance to be narrowed! */
       
  1180 	set_il_operand_datatype(il_operand, NULL);
  1133 	return NULL;
  1181 	return NULL;
  1134 }
  1182 }
  1135 
  1183 
  1136 
  1184 
  1137 
  1185 
  1138 
  1186 
  1139 
  1187 
  1140 void *narrow_candidate_datatypes_c::handle_il_instruction(symbol_c *symbol) {
  1188 void *narrow_candidate_datatypes_c::handle_il_instruction(symbol_c *symbol) {
  1141 	if (NULL == symbol->datatype) return NULL; /* next IL instructions were unable to determine the datatype this instruction should produce */
  1189 	/*
  1142   
       
  1143 	/* NOTE 1: the il_operand __may__ be pointing to a parenthesized list of IL instructions. 
       
  1144 	 * e.g.  LD 33
       
  1145 	 *       AND ( 45
       
  1146 	 *            OR 56
       
  1147 	 *            )
       
  1148 	 *       When we handle the first 'AND' IL_operator, the il_operand will point to an simple_instr_list_c.
       
  1149 	 *       In this case, when we call il_operand->accept(*this);, the prev_il_instruction pointer will be overwritten!
       
  1150 	 *
       
  1151 	 *       We must therefore set the prev_il_instruction->datatype = symbol->datatype;
       
  1152 	 *       __before__ calling il_operand->accept(*this) !!
       
  1153 	 *
       
  1154 	 * NOTE 2: We do not need to call prev_il_instruction->accept(*this), as the object to which prev_il_instruction
  1190 	 * NOTE 2: We do not need to call prev_il_instruction->accept(*this), as the object to which prev_il_instruction
  1155 	 *         is pointing to will be later narrowed by the call from the for() loop of the instruction_list_c
  1191 	 *         is pointing to will be later narrowed by the call from the for() loop of the instruction_list_c
  1156 	 *         (or simple_instr_list_c), which iterates backwards.
  1192 	 *         (or simple_instr_list_c), which iterates backwards.
  1157 	 */
  1193 	 */
  1158 	/* set the desired datatype of the previous il instruction */
  1194 	if (NULL != symbol->datatype) // next IL instructions were able to determine the datatype this instruction should produce
  1159 	set_datatype_in_prev_il_instructions(symbol->datatype, fake_prev_il_instruction);
  1195 		/* set the desired datatype of the previous il instruction */
  1160 	  
  1196 		set_datatype_in_prev_il_instructions(symbol->datatype, fake_prev_il_instruction);
       
  1197   
  1161 	/* set the datatype for the operand */
  1198 	/* set the datatype for the operand */
  1162 	if (NULL == il_operand) return NULL; /* if no IL operand => error in the source code!! */
  1199 	set_il_operand_datatype(il_operand, symbol->datatype);
  1163 	il_operand->datatype = symbol->datatype;
  1200 	return NULL;
  1164 	il_operand->accept(*this);
  1201 }
  1165 	return NULL;
  1202 
  1166 }
  1203 
  1167 
  1204 
  1168 
  1205 
  1169 
  1206 void *narrow_candidate_datatypes_c::visit( LD_operator_c *symbol)  {return set_il_operand_datatype(il_operand, symbol->datatype);}
  1170 
  1207 void *narrow_candidate_datatypes_c::visit(LDN_operator_c *symbol)  {return set_il_operand_datatype(il_operand, symbol->datatype);}
  1171 void *narrow_candidate_datatypes_c::visit(LD_operator_c *symbol)   {
       
  1172 	if (NULL == symbol->datatype) return NULL; /* next IL instructions were unable to determine the datatype this instruction should produce */
       
  1173 
       
  1174 	/* set the datatype for the operand */
       
  1175 	if (NULL == il_operand) return NULL; /* if no IL operand => error in the source code!! */
       
  1176 	il_operand->datatype = symbol->datatype;
       
  1177 	il_operand->accept(*this);
       
  1178 	return NULL;
       
  1179 }
       
  1180 
       
  1181 
       
  1182 void *narrow_candidate_datatypes_c::visit(LDN_operator_c *symbol)  {
       
  1183 	if (NULL == symbol->datatype) return NULL; /* next IL instructions were unable to determine the datatype this instruction should produce */
       
  1184 
       
  1185 	/* set the datatype for the operand */
       
  1186 	if (NULL == il_operand) return NULL; /* if no IL operand => error in the source code!! */
       
  1187 	il_operand->datatype = symbol->datatype;
       
  1188 	il_operand->accept(*this);
       
  1189 	return NULL;
       
  1190 }
       
  1191 
  1208 
  1192 void *narrow_candidate_datatypes_c::visit(ST_operator_c *symbol) {
  1209 void *narrow_candidate_datatypes_c::visit(ST_operator_c *symbol) {
  1193 	if (symbol->candidate_datatypes.size() != 1)
  1210 	if (symbol->candidate_datatypes.size() == 1) {
  1194 		return NULL;
  1211 		symbol->datatype = symbol->candidate_datatypes[0];
  1195 
  1212 		/* set the desired datatype of the previous il instruction */
  1196 	symbol->datatype = symbol->candidate_datatypes[0];
  1213 		set_datatype_in_prev_il_instructions(symbol->datatype, fake_prev_il_instruction);
  1197 	/* set the desired datatype of the previous il instruction */
  1214 		/* In the case of the ST operator, we must set the datatype of the il_instruction_c object that points to this ST_operator_c ourselves,
  1198 	set_datatype_in_prev_il_instructions(symbol->datatype, fake_prev_il_instruction);
  1215 		 * since the following il_instruction_c objects have not done it, as is normal/standard for other instructions!
  1199 	/* In the case of the ST operator, we must set the datatype of the il_instruction_c object that points to this ST_operator_c ourselves,
  1216 		 */
  1200 	 * since the following il_instruction_c objects have not done it, as is normal/standard for other instructions!
  1217 		current_il_instruction->datatype = symbol->datatype;
  1201 	 */
  1218 	}
  1202 	current_il_instruction->datatype = symbol->datatype;
       
  1203 	
  1219 	
  1204 	/* set the datatype for the operand */
  1220 	/* set the datatype for the operand */
  1205 	if (NULL == il_operand) return NULL; /* if no IL operand => error in the source code!! */
  1221 	set_il_operand_datatype(il_operand, symbol->datatype);
  1206 	il_operand->datatype = symbol->datatype;
       
  1207 	il_operand->accept(*this);
       
  1208 
       
  1209 	return NULL;
  1222 	return NULL;
  1210 }
  1223 }
  1211 
  1224 
  1212 void *narrow_candidate_datatypes_c::visit(STN_operator_c *symbol) {
  1225 void *narrow_candidate_datatypes_c::visit(STN_operator_c *symbol) {
  1213 	if (symbol->candidate_datatypes.size() != 1)
  1226 	if (symbol->candidate_datatypes.size() == 1) {
  1214 		return NULL;
  1227 		symbol->datatype = symbol->candidate_datatypes[0];
       
  1228 		/* set the desired datatype of the previous il instruction */
       
  1229 		set_datatype_in_prev_il_instructions(symbol->datatype, fake_prev_il_instruction);
       
  1230 		/* In the case of the ST operator, we must set the datatype of the il_instruction_c object that points to this ST_operator_c ourselves,
       
  1231 		 * since the following il_instruction_c objects have not done it, as is normal/standard for other instructions!
       
  1232 		 */
       
  1233 		current_il_instruction->datatype = symbol->datatype;
       
  1234 	}
  1215 	
  1235 	
  1216 	symbol->datatype = symbol->candidate_datatypes[0];
       
  1217 	/* set the desired datatype of the previous il instruction */
       
  1218 	set_datatype_in_prev_il_instructions(symbol->datatype, fake_prev_il_instruction);
       
  1219 	/* In the case of the ST operator, we must set the datatype of the il_instruction_c object that points to this ST_operator_c ourselves,
       
  1220 	 * since the following il_instruction_c objects have not done it, as is normal/standard for other instructions!
       
  1221 	 */
       
  1222 	current_il_instruction->datatype = symbol->datatype;
       
  1223 
       
  1224 	/* set the datatype for the operand */
  1236 	/* set the datatype for the operand */
  1225 	if (NULL == il_operand) return NULL; /* if no IL operand => error in the source code!! */
  1237 	set_il_operand_datatype(il_operand, symbol->datatype);
  1226 	il_operand->datatype = symbol->datatype;
       
  1227 	il_operand->accept(*this);
       
  1228 	return NULL;
  1238 	return NULL;
  1229 }
  1239 }
  1230 
  1240 
  1231 void *narrow_candidate_datatypes_c::visit(NOT_operator_c *symbol) {
  1241 void *narrow_candidate_datatypes_c::visit(NOT_operator_c *symbol) {
  1232 	/* NOTE: the standard allows syntax in which the NOT operator is followed by an optional <il_operand>
  1242 	/* NOTE: the standard allows syntax in which the NOT operator is followed by an optional <il_operand>