115 * |
115 * |
116 * |
116 * |
117 * NOTE 2 |
117 * NOTE 2 |
118 * This file does not print out any error messages! |
118 * This file does not print out any error messages! |
119 * We cannot really print out error messages when we find an overflow. Since each operation |
119 * We cannot really print out error messages when we find an overflow. Since each operation |
120 * (symbol in the absract syntax tree for that operation) will have up to 4 constant results, |
120 * (symbol in the abstract syntax tree for that operation) will have up to 4 constant results, |
121 * it may happen that some of them overflow, while other do not. |
121 * it may happen that some of them overflow, while other do not. |
122 * We must wait for data type checking to determine the exact data type of each expression |
122 * We must wait for data type checking to determine the exact data type of each expression |
123 * before we can decide whether or not we should print out an overflow error message. |
123 * before we can decide whether or not we should print out an overflow error message. |
124 * |
124 * |
125 * For this reason, this visitor merely annotates the abstract syntax tree, and leaves the |
125 * For this reason, this visitor merely annotates the abstract syntax tree, and leaves the |
126 * actuall printing of errors for the print_datatype_errors_c class! |
126 * actually printing of errors for the print_datatype_errors_c class! |
|
127 * |
|
128 * NOTE 3 |
|
129 * Constant Folding class is extended with a implementation constant propagation algorithm |
|
130 * by Mario de Sousa. |
|
131 * Main idea is not to implement a general constant propagation algorithm but to reinterpret it |
|
132 * for visitor classes. |
|
133 * We declared a hash map, it contains a variables list linked with current constant values. |
|
134 * During expression evaluation we can retrieve a constant value to symbolic variables getting it from the map. |
|
135 * Also at join source points we use a meet semilattice rules to merge current values between a block |
|
136 * and adjacent block. |
|
137 * |
127 */ |
138 */ |
128 |
139 |
129 #include "constant_folding.hh" |
140 #include "constant_folding.hh" |
130 #include <stdlib.h> /* required for malloc() */ |
141 #include <stdlib.h> /* required for malloc() */ |
131 |
142 |
1258 void *constant_folding_c::visit(if_statement_c *symbol) { |
1270 void *constant_folding_c::visit(if_statement_c *symbol) { |
1259 std::map <std::string, symbol_c::const_value_t> values_incoming; |
1271 std::map <std::string, symbol_c::const_value_t> values_incoming; |
1260 std::map <std::string, symbol_c::const_value_t> values_statement_result; |
1272 std::map <std::string, symbol_c::const_value_t> values_statement_result; |
1261 std::map <std::string, symbol_c::const_value_t> values_elsestatement_result; |
1273 std::map <std::string, symbol_c::const_value_t> values_elsestatement_result; |
1262 std::map <std::string, symbol_c::const_value_t>::iterator itr; |
1274 std::map <std::string, symbol_c::const_value_t>::iterator itr; |
|
1275 |
|
1276 /* Optimize dead code */ |
|
1277 symbol->expression->accept(*this); |
|
1278 if (VALID_CVALUE(bool, symbol->expression) && GET_CVALUE(bool, symbol->expression) == false) |
|
1279 return NULL; |
|
1280 |
1263 values_incoming = values; /* save incoming status */ |
1281 values_incoming = values; /* save incoming status */ |
1264 |
|
1265 symbol->statement_list->accept(*this); |
1282 symbol->statement_list->accept(*this); |
1266 values_statement_result = values; |
1283 values_statement_result = values; |
1267 if (NULL != symbol->else_statement_list) { |
1284 if (NULL != symbol->else_statement_list) { |
1268 values = values_incoming; |
1285 values = values_incoming; |
1269 symbol->else_statement_list->accept(*this); |
1286 symbol->else_statement_list->accept(*this); |
1285 COMPUTE_MEET_SEMILATTICE ( bool, c1, c2, value); |
1302 COMPUTE_MEET_SEMILATTICE ( bool, c1, c2, value); |
1286 } else |
1303 } else |
1287 value = values_statement_result[name]; |
1304 value = values_statement_result[name]; |
1288 values[name] = value; |
1305 values[name] = value; |
1289 } |
1306 } |
1290 return NULL; |
1307 |
1291 } |
1308 return NULL; |
1292 |
1309 } |
1293 |
1310 |
1294 |
1311 /********************************/ |
|
1312 /* B 3.2.4 Iteration Statements */ |
|
1313 /********************************/ |
|
1314 void *constant_folding_c::visit(for_statement_c *symbol) { |
|
1315 std::map <std::string, symbol_c::const_value_t> values_incoming; |
|
1316 std::map <std::string, symbol_c::const_value_t> values_statement_result; |
|
1317 std::map <std::string, symbol_c::const_value_t>::iterator itr; |
|
1318 std::string varName; |
|
1319 |
|
1320 values_incoming = values; /* save incoming status */ |
|
1321 symbol->beg_expression->accept(*this); |
|
1322 symbol->end_expression->accept(*this); |
|
1323 varName = get_var_name_c::get_name(symbol->control_variable)->value; |
|
1324 values[varName] = symbol->beg_expression->const_value; |
|
1325 |
|
1326 /* Optimize dead code */ |
|
1327 if (VALID_CVALUE(int64, symbol->beg_expression) && VALID_CVALUE(int64, symbol->end_expression) && |
|
1328 GET_CVALUE(int64, symbol->beg_expression) > GET_CVALUE(int64, symbol->end_expression)) |
|
1329 return NULL; |
|
1330 |
|
1331 symbol->statement_list->accept(*this); |
|
1332 values_statement_result = values; |
|
1333 values.clear(); |
|
1334 itr = values_statement_result.begin(); |
|
1335 for ( ; itr != values_statement_result.end(); ++itr) { |
|
1336 std::string name = itr->first; |
|
1337 symbol_c::const_value_t value; |
|
1338 |
|
1339 if (values_incoming.count(name) > 0) { |
|
1340 symbol_c::const_value_t c1 = itr->second; |
|
1341 symbol_c::const_value_t c2 = values_incoming[name]; |
|
1342 COMPUTE_MEET_SEMILATTICE (real64, c1, c2, value); |
|
1343 COMPUTE_MEET_SEMILATTICE (uint64, c1, c2, value); |
|
1344 COMPUTE_MEET_SEMILATTICE ( int64, c1, c2, value); |
|
1345 COMPUTE_MEET_SEMILATTICE ( bool, c1, c2, value); |
|
1346 } else |
|
1347 value = values_statement_result[name]; |
|
1348 values[name] = value; |
|
1349 } |
|
1350 |
|
1351 return NULL; |
|
1352 } |
|
1353 |
|
1354 void *constant_folding_c::visit(while_statement_c *symbol) { |
|
1355 std::map <std::string, symbol_c::const_value_t> values_incoming; |
|
1356 std::map <std::string, symbol_c::const_value_t> values_statement_result; |
|
1357 std::map <std::string, symbol_c::const_value_t>::iterator itr; |
|
1358 |
|
1359 /* Optimize dead code */ |
|
1360 symbol->expression->accept(*this); |
|
1361 if (VALID_CVALUE(bool, symbol->expression) && GET_CVALUE(bool, symbol->expression) == false) |
|
1362 return NULL; |
|
1363 |
|
1364 values_incoming = values; /* save incoming status */ |
|
1365 symbol->statement_list->accept(*this); |
|
1366 values_statement_result = values; |
|
1367 values.clear(); |
|
1368 itr = values_statement_result.begin(); |
|
1369 for ( ; itr != values_statement_result.end(); ++itr) { |
|
1370 std::string name = itr->first; |
|
1371 symbol_c::const_value_t value; |
|
1372 |
|
1373 if (values_incoming.count(name) > 0) { |
|
1374 symbol_c::const_value_t c1 = itr->second; |
|
1375 symbol_c::const_value_t c2 = values_incoming[name]; |
|
1376 COMPUTE_MEET_SEMILATTICE (real64, c1, c2, value); |
|
1377 COMPUTE_MEET_SEMILATTICE (uint64, c1, c2, value); |
|
1378 COMPUTE_MEET_SEMILATTICE ( int64, c1, c2, value); |
|
1379 COMPUTE_MEET_SEMILATTICE ( bool, c1, c2, value); |
|
1380 } else |
|
1381 value = values_statement_result[name]; |
|
1382 values[name] = value; |
|
1383 } |
|
1384 |
|
1385 |
|
1386 return NULL; |
|
1387 } |
|
1388 |
|
1389 void *constant_folding_c::visit(repeat_statement_c *symbol) { |
|
1390 std::map <std::string, symbol_c::const_value_t> values_incoming; |
|
1391 std::map <std::string, symbol_c::const_value_t> values_statement_result; |
|
1392 std::map <std::string, symbol_c::const_value_t>::iterator itr; |
|
1393 |
|
1394 /* Optimize dead code */ |
|
1395 symbol->expression->accept(*this); |
|
1396 if (VALID_CVALUE(bool, symbol->expression) && GET_CVALUE(bool, symbol->expression) == false) |
|
1397 return NULL; |
|
1398 |
|
1399 values_incoming = values; /* save incoming status */ |
|
1400 symbol->statement_list->accept(*this); |
|
1401 values_statement_result = values; |
|
1402 values.clear(); |
|
1403 itr = values_statement_result.begin(); |
|
1404 for ( ; itr != values_statement_result.end(); ++itr) { |
|
1405 std::string name = itr->first; |
|
1406 symbol_c::const_value_t value; |
|
1407 |
|
1408 if (values_incoming.count(name) > 0) { |
|
1409 symbol_c::const_value_t c1 = itr->second; |
|
1410 symbol_c::const_value_t c2 = values_incoming[name]; |
|
1411 COMPUTE_MEET_SEMILATTICE (real64, c1, c2, value); |
|
1412 COMPUTE_MEET_SEMILATTICE (uint64, c1, c2, value); |
|
1413 COMPUTE_MEET_SEMILATTICE ( int64, c1, c2, value); |
|
1414 COMPUTE_MEET_SEMILATTICE ( bool, c1, c2, value); |
|
1415 } else |
|
1416 value = values_statement_result[name]; |
|
1417 values[name] = value; |
|
1418 } |
|
1419 |
|
1420 |
|
1421 return NULL; |
|
1422 } |
|
1423 |
|
1424 |
|
1425 |