Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "tree.h"
00022 #include "power-of-two.h"
00023 #include "../utils/FormatableString.h"
00024 #include "../utils/utils.h"
00025 #include <cassert>
00026 #include <cstdlib>
00027
00028
00029 namespace Aseba
00030 {
00033
00034 Node* BlockNode::optimize(std::wostream* dump)
00035 {
00036 for (NodesVector::iterator it = children.begin(); it != children.end();)
00037 {
00038
00039 Node *optimizedChild = (*it)->optimize(dump);
00040 if (!optimizedChild)
00041 {
00042 it = children.erase(it);
00043 continue;
00044 }
00045 else
00046 *it = optimizedChild;
00047
00048
00049 if (dynamic_cast<BlockNode *>(*it) && (*it)->children.empty())
00050 {
00051 delete *it;
00052 it = children.erase(it);
00053 continue;
00054 }
00055
00056 ++it;
00057 }
00058
00059 return this;
00060 }
00061
00062 Node* AssignmentNode::optimize(std::wostream* dump)
00063 {
00064 children[0] = children[0]->optimize(dump);
00065 assert(children[0]);
00066 children[1] = children[1]->optimize(dump);
00067 assert(children[1]);
00068 return this;
00069 }
00070
00071 Node* IfWhenNode::optimize(std::wostream* dump)
00072 {
00073 children[0] = children[0]->optimize(dump);
00074 assert(children[0]);
00075
00076
00077 children[1] = children[1]->optimize(dump);
00078 Node *trueBlock = children[1];
00079
00080
00081 Node *falseBlock;
00082 if (children.size() > 2)
00083 {
00084 children[2] = children[2]->optimize(dump);
00085 falseBlock = children[2];
00086 if (children[2] == 0)
00087 children.resize(2);
00088 }
00089 else
00090 falseBlock = 0;
00091
00092
00093 if (
00094 ((trueBlock == 0) || (dynamic_cast<BlockNode*>(trueBlock) && trueBlock->children.empty())) &&
00095 ((falseBlock == 0) || (dynamic_cast<BlockNode*>(falseBlock) && falseBlock->children.empty()))
00096 )
00097 {
00098 if (dump)
00099 *dump << sourcePos.toWString() << L": if test removed because it had no associated code\n";
00100 delete this;
00101 return NULL;
00102 }
00103
00104
00105 ImmediateNode* constantExpression = dynamic_cast<ImmediateNode*>(children[0]);
00106 if (constantExpression)
00107 {
00108 if (constantExpression->value != 0)
00109 {
00110 if (dump)
00111 *dump << sourcePos.toWString() << L": if test simplified because condition was always true\n";
00112 children[1] = 0;
00113 delete this;
00114 return trueBlock;
00115 }
00116 else
00117 {
00118 if (dump)
00119 *dump << sourcePos.toWString() << L": if test simplified because condition was always false\n";
00120 if (children.size() > 2)
00121 children[2] = 0;
00122 delete this;
00123 return falseBlock;
00124 }
00125 }
00126
00127
00128 if (trueBlock == 0)
00129 children[1] = new BlockNode(sourcePos);
00130
00131
00132 BinaryArithmeticNode* operation = polymorphic_downcast<BinaryArithmeticNode*>(children[0]);
00133 FoldedIfWhenNode *foldedNode = new FoldedIfWhenNode(sourcePos);
00134 foldedNode->op = operation->op;
00135 foldedNode->edgeSensitive = edgeSensitive;
00136 foldedNode->endLine = endLine;
00137 foldedNode->children.push_back(operation->children[0]);
00138 foldedNode->children.push_back(operation->children[1]);
00139 operation->children.clear();
00140 foldedNode->children.push_back(children[1]);
00141 children[1] = 0;
00142 if (children.size() > 2)
00143 {
00144 foldedNode->children.push_back(children[2]);
00145 children[2] = 0;
00146 }
00147
00148 if (dump)
00149 *dump << sourcePos.toWString() << L": if condition folded inside node\n";
00150
00151 delete this;
00152
00153 return foldedNode;
00154 }
00155
00156 Node* FoldedIfWhenNode::optimize(std::wostream* dump)
00157 {
00158 abort();
00159 return 0;
00160 }
00161
00162 Node* WhileNode::optimize(std::wostream* dump)
00163 {
00164 children[0] = children[0]->optimize(dump);
00165 assert(children[0]);
00166
00167
00168 children[1] = children[1]->optimize(dump);
00169
00170
00171 ImmediateNode* constantExpression = dynamic_cast<ImmediateNode*>(children[0]);
00172 if (constantExpression)
00173 {
00174 if (constantExpression->value != 0)
00175 {
00176 throw TranslatableError(sourcePos, ERROR_INFINITE_LOOP);
00177 }
00178 else
00179 {
00180 if (dump)
00181 *dump << sourcePos.toWString() << L": while removed because condition is always false\n";
00182 delete this;
00183 return NULL;
00184 }
00185 }
00186
00187
00188 if ((children[1] == 0) || (dynamic_cast<BlockNode*>(children[1]) && children[1]->children.empty()))
00189 {
00190 if (dump)
00191 *dump << sourcePos.toWString() << L": while removed because it contained no statement\n";
00192 delete this;
00193 return NULL;
00194 }
00195
00196
00197 BinaryArithmeticNode* operation = polymorphic_downcast<BinaryArithmeticNode*>(children[0]);
00198 FoldedWhileNode *foldedNode = new FoldedWhileNode(sourcePos);
00199 foldedNode->op = operation->op;
00200 foldedNode->children.push_back(operation->children[0]);
00201 foldedNode->children.push_back(operation->children[1]);
00202 operation->children.clear();
00203 foldedNode->children.push_back(children[1]);
00204 children[1] = 0;
00205
00206 if (dump)
00207 *dump << sourcePos.toWString() << L": while condition folded inside node\n";
00208
00209 delete this;
00210
00211 return foldedNode;
00212 }
00213
00214 Node* FoldedWhileNode::optimize(std::wostream* dump)
00215 {
00216 abort();
00217 return 0;
00218 }
00219
00220 Node* EventDeclNode::optimize(std::wostream* dump)
00221 {
00222 return this;
00223 }
00224
00225 Node* EmitNode::optimize(std::wostream* dump)
00226 {
00227 for (NodesVector::iterator it = children.begin(); it != children.end();)
00228 {
00229
00230 *it = (*it)->optimize(dump);
00231 ++it;
00232 }
00233
00234 return this;
00235 }
00236
00237 Node* SubDeclNode::optimize(std::wostream* dump)
00238 {
00239 return this;
00240 }
00241
00242 Node* CallSubNode::optimize(std::wostream* dump)
00243 {
00244 return this;
00245 }
00246
00247 Node* BinaryArithmeticNode::optimize(std::wostream* dump)
00248 {
00249 children[0] = children[0]->optimize(dump);
00250 assert(children[0]);
00251 children[1] = children[1]->optimize(dump);
00252 assert(children[1]);
00253
00254
00255 ImmediateNode* immediateLeftChild = dynamic_cast<ImmediateNode*>(children[0]);
00256 ImmediateNode* immediateRightChild = dynamic_cast<ImmediateNode*>(children[1]);
00257 if (immediateLeftChild && immediateRightChild)
00258 {
00259 int valueOne = immediateLeftChild->value;
00260 int valueTwo = immediateRightChild->value;
00261 int result;
00262 SourcePos pos = sourcePos;
00263
00264 switch (op)
00265 {
00266 case ASEBA_OP_SHIFT_LEFT: result = valueOne << valueTwo; break;
00267 case ASEBA_OP_SHIFT_RIGHT: result = valueOne >> valueTwo; break;
00268 case ASEBA_OP_ADD: result = valueOne + valueTwo; break;
00269 case ASEBA_OP_SUB: result = valueOne - valueTwo; break;
00270 case ASEBA_OP_MULT: result = valueOne * valueTwo; break;
00271 case ASEBA_OP_DIV:
00272 if (valueTwo == 0)
00273 throw TranslatableError(sourcePos, ERROR_DIVISION_BY_ZERO);
00274 else
00275 result = valueOne / valueTwo;
00276 break;
00277 case ASEBA_OP_MOD: result = valueOne % valueTwo; break;
00278
00279 case ASEBA_OP_EQUAL: result = valueOne == valueTwo; break;
00280 case ASEBA_OP_NOT_EQUAL: result = valueOne != valueTwo; break;
00281 case ASEBA_OP_BIGGER_THAN: result = valueOne > valueTwo; break;
00282 case ASEBA_OP_BIGGER_EQUAL_THAN: result = valueOne >= valueTwo; break;
00283 case ASEBA_OP_SMALLER_THAN: result = valueOne < valueTwo; break;
00284 case ASEBA_OP_SMALLER_EQUAL_THAN: result = valueOne <= valueTwo; break;
00285
00286 case ASEBA_OP_OR: result = valueOne || valueTwo; break;
00287 case ASEBA_OP_AND: result = valueOne && valueTwo; break;
00288
00289 default: abort();
00290 }
00291
00292 if (dump)
00293 *dump << sourcePos.toWString() << L": binary arithmetic expression simplified\n";
00294 delete this;
00295 return new ImmediateNode(pos, result);
00296 }
00297
00298
00299
00300 if (op == ASEBA_OP_MULT || op == ASEBA_OP_DIV || op == ASEBA_OP_ADD || op == ASEBA_OP_SUB)
00301 {
00302 Node **survivor(0);
00303 if (op == ASEBA_OP_MULT || op == ASEBA_OP_DIV)
00304 {
00305 if (immediateRightChild && (immediateRightChild->value == 1))
00306 survivor = &children[0];
00307 if (immediateLeftChild && (immediateLeftChild->value == 1))
00308 survivor = &children[1];
00309 }
00310 else
00311 {
00312 if (immediateRightChild && (immediateRightChild->value == 0))
00313 survivor = &children[0];
00314 if (immediateLeftChild && (immediateLeftChild->value == 0))
00315 survivor = &children[1];
00316 }
00317 if (survivor)
00318 {
00319 if (dump)
00320 *dump << sourcePos.toWString() << L": operation with neutral element removed\n";
00321 Node *returNode = *survivor;
00322 *survivor = 0;
00323 delete this;
00324 return returNode;
00325 }
00326 }
00327
00328
00329 if (immediateRightChild && isPOT(immediateRightChild->value))
00330 {
00331 if (op == ASEBA_OP_MULT)
00332 {
00333 op = ASEBA_OP_SHIFT_LEFT;
00334 immediateRightChild->value = shiftFromPOT(immediateRightChild->value);
00335 if (dump)
00336 *dump << sourcePos.toWString() << L": multiplication transformed to left shift\n";
00337 }
00338 else if (op == ASEBA_OP_DIV)
00339 {
00340 if (immediateRightChild->value == 0)
00341 throw TranslatableError(sourcePos, ERROR_DIVISION_BY_ZERO);
00342 op = ASEBA_OP_SHIFT_RIGHT;
00343 immediateRightChild->value = shiftFromPOT(immediateRightChild->value);
00344 if (dump)
00345 *dump << sourcePos.toWString() << L": division transformed to right shift\n";
00346 }
00347 }
00348
00349 return this;
00350 }
00351
00353 void BinaryArithmeticNode::deMorganNotRemoval()
00354 {
00355 switch (op)
00356 {
00357
00358 case ASEBA_OP_EQUAL: op = ASEBA_OP_NOT_EQUAL; break;
00359 case ASEBA_OP_NOT_EQUAL: op = ASEBA_OP_EQUAL; break;
00360 case ASEBA_OP_BIGGER_THAN: op = ASEBA_OP_SMALLER_EQUAL_THAN; break;
00361 case ASEBA_OP_BIGGER_EQUAL_THAN: op = ASEBA_OP_SMALLER_THAN; break;
00362 case ASEBA_OP_SMALLER_THAN: op = ASEBA_OP_BIGGER_EQUAL_THAN; break;
00363 case ASEBA_OP_SMALLER_EQUAL_THAN: op = ASEBA_OP_BIGGER_THAN; break;
00364
00365 case ASEBA_OP_OR:
00366 op = ASEBA_OP_AND;
00367 polymorphic_downcast<BinaryArithmeticNode*>(children[0])->deMorganNotRemoval();
00368 polymorphic_downcast<BinaryArithmeticNode*>(children[1])->deMorganNotRemoval();
00369 break;
00370 case ASEBA_OP_AND:
00371 op = ASEBA_OP_OR;
00372 polymorphic_downcast<BinaryArithmeticNode*>(children[0])->deMorganNotRemoval();
00373 polymorphic_downcast<BinaryArithmeticNode*>(children[1])->deMorganNotRemoval();
00374 break;
00375 default: abort();
00376 };
00377 }
00378
00379 Node* UnaryArithmeticNode::optimize(std::wostream* dump)
00380 {
00381 children[0] = children[0]->optimize(dump);
00382 assert(children[0]);
00383
00384
00385 ImmediateNode* immediateChild = dynamic_cast<ImmediateNode*>(children[0]);
00386 if (immediateChild)
00387 {
00388 int result;
00389 SourcePos pos = sourcePos;
00390
00391 switch (op)
00392 {
00393 case ASEBA_UNARY_OP_SUB: result = -immediateChild->value; break;
00394 case ASEBA_UNARY_OP_ABS:
00395 if (immediateChild->value == -32768)
00396 throw TranslatableError(sourcePos, ERROR_ABS_NOT_POSSIBLE);
00397 else
00398 result = abs(immediateChild->value);
00399 break;
00400 case ASEBA_UNARY_OP_BIT_NOT: result = ~immediateChild->value; break;
00401
00402 default: abort();
00403 }
00404
00405 if (dump)
00406 *dump << sourcePos.toWString() << L": unary arithmetic expression simplified\n";
00407 delete this;
00408 return new ImmediateNode(pos, result);
00409 }
00410 else if (op == ASEBA_UNARY_OP_NOT)
00411 {
00412 BinaryArithmeticNode* binaryNodeChild(dynamic_cast<BinaryArithmeticNode*>(children[0]));
00413 if (binaryNodeChild)
00414 {
00415
00416 if (dump)
00417 *dump << sourcePos.toWString() << L": not removed using de Morgan\n";
00418 binaryNodeChild->deMorganNotRemoval();
00419 children.clear();
00420 delete this;
00421 return binaryNodeChild;
00422 }
00423 else
00424 return this;
00425 }
00426 else
00427 return this;
00428 }
00429
00430 Node* ImmediateNode::optimize(std::wostream* dump)
00431 {
00432 return this;
00433 }
00434
00435 Node* LoadNode::optimize(std::wostream* dump)
00436 {
00437 return this;
00438 }
00439
00440 Node* StoreNode::optimize(std::wostream* dump)
00441 {
00442 return this;
00443 }
00444
00445 Node* ArrayReadNode::optimize(std::wostream* dump)
00446 {
00447
00448 children[0] = children[0]->optimize(dump);
00449 assert(children[0]);
00450
00451
00452
00453 ImmediateNode* immediateChild = dynamic_cast<ImmediateNode*>(children[0]);
00454 if (immediateChild)
00455 {
00456 unsigned index = immediateChild->value;
00457 if (index >= arraySize)
00458 {
00459 throw TranslatableError(sourcePos,
00460 ERROR_ARRAY_OUT_OF_BOUND_READ).arg(index).arg(arrayName).arg(arraySize);
00461 }
00462
00463 unsigned varAddr = arrayAddr + index;
00464 SourcePos pos = sourcePos;
00465
00466 if (dump)
00467 *dump << sourcePos.toWString() << L": array access transformed to single variable access\n";
00468 delete this;
00469 return new LoadNode(pos, varAddr);
00470 }
00471 else
00472 return this;
00473 }
00474
00475 Node* ArrayWriteNode::optimize(std::wostream* dump)
00476 {
00477
00478 children[0] = children[0]->optimize(dump);
00479 assert(children[0]);
00480
00481
00482
00483 ImmediateNode* immediateChild = dynamic_cast<ImmediateNode*>(children[0]);
00484 if (immediateChild)
00485 {
00486 unsigned index = immediateChild->value;
00487 if (index >= arraySize)
00488 {
00489 throw TranslatableError(sourcePos,
00490 ERROR_ARRAY_OUT_OF_BOUND_WRITE).arg(index).arg(arrayName).arg(arraySize);
00491 }
00492
00493 unsigned varAddr = arrayAddr + index;
00494 SourcePos pos = sourcePos;
00495
00496 if (dump)
00497 *dump << sourcePos.toWString() << L": array access transformed to single variable access\n";
00498 delete this;
00499 return new StoreNode(pos, varAddr);
00500 }
00501 else
00502 return this;
00503 }
00504
00505 Node* CallNode::optimize(std::wostream* dump)
00506 {
00507 for (NodesVector::iterator it = children.begin(); it != children.end();)
00508 {
00509
00510 *it = (*it)->optimize(dump);
00511 ++it;
00512 }
00513
00514 return this;
00515 }
00516
00519 };