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> |