1 /*
2  * File:  ElftosbAST.cpp
3  *
4  * Copyright (c) Freescale Semiconductor, Inc. All rights reserved.
5  * See included license file for license details.
6  */
7 
8 #include "ElftosbAST.h"
9 #include <stdexcept>
10 #include <math.h>
11 #include <assert.h>
12 #include "ElftosbErrors.h"
13 #include "format_string.h"
14 
15 using namespace elftosb;
16 
17 #pragma mark = ASTNode =
18 
printTree(int indent) const19 void ASTNode::printTree(int indent) const
20 {
21           printIndent(indent);
22           printf("%s\n", nodeName().c_str());
23 }
24 
printIndent(int indent) const25 void ASTNode::printIndent(int indent) const
26 {
27           int i;
28           for (i=0; i<indent; ++i)
29           {
30                     printf("   ");
31           }
32 }
33 
setLocation(token_loc_t & first,token_loc_t & last)34 void ASTNode::setLocation(token_loc_t & first, token_loc_t & last)
35 {
36           m_location.m_firstLine = first.m_firstLine;
37           m_location.m_lastLine = last.m_lastLine;
38 }
39 
setLocation(ASTNode * first,ASTNode * last)40 void ASTNode::setLocation(ASTNode * first, ASTNode * last)
41 {
42           m_location.m_firstLine = first->getLocation().m_firstLine;
43           m_location.m_lastLine = last->getLocation().m_lastLine;
44 }
45 
46 #pragma mark = ListASTNode =
47 
ListASTNode(const ListASTNode & other)48 ListASTNode::ListASTNode(const ListASTNode & other)
49 :         ASTNode(other), m_list()
50 {
51           // deep copy each item of the original's list
52           const_iterator it = other.begin();
53           for (; it != other.end(); ++it)
54           {
55                     m_list.push_back((*it)->clone());
56           }
57 }
58 
59 //! Deletes child node in the list.
60 //!
~ListASTNode()61 ListASTNode::~ListASTNode()
62 {
63           iterator it = begin();
64           for (; it != end(); it++)
65           {
66                     delete *it;
67           }
68 }
69 
70 //! If \a node is NULL then the list is left unmodified.
71 //!
72 //! The list node's location is automatically updated after the node is added by a call
73 //! to updateLocation().
appendNode(ASTNode * node)74 void ListASTNode::appendNode(ASTNode * node)
75 {
76           if (node)
77           {
78                     m_list.push_back(node);
79                     updateLocation();
80           }
81 }
82 
printTree(int indent) const83 void ListASTNode::printTree(int indent) const
84 {
85           ASTNode::printTree(indent);
86 
87           int n = 0;
88           const_iterator it = begin();
89           for (; it != end(); it++, n++)
90           {
91                     printIndent(indent + 1);
92                     printf("%d:\n", n);
93                     (*it)->printTree(indent + 2);
94           }
95 }
96 
updateLocation()97 void ListASTNode::updateLocation()
98 {
99           token_loc_t current = { 0 };
100           const_iterator it = begin();
101           for (; it != end(); it++)
102           {
103                     const ASTNode * node = *it;
104                     const token_loc_t & loc = node->getLocation();
105 
106                     // handle first node
107                     if (current.m_firstLine == 0)
108                     {
109                               current = loc;
110                               continue;
111                     }
112 
113                     if (loc.m_firstLine < current.m_firstLine)
114                     {
115                               current.m_firstLine = loc.m_firstLine;
116                     }
117 
118                     if (loc.m_lastLine > current.m_lastLine)
119                     {
120                               current.m_lastLine = loc.m_lastLine;
121                     }
122           }
123 
124           setLocation(current);
125 }
126 
127 #pragma mark = CommandFileASTNode =
128 
CommandFileASTNode()129 CommandFileASTNode::CommandFileASTNode()
130 :         ASTNode(), m_options(), m_constants(), m_sources(), m_sections()
131 {
132 }
133 
CommandFileASTNode(const CommandFileASTNode & other)134 CommandFileASTNode::CommandFileASTNode(const CommandFileASTNode & other)
135 :         ASTNode(other), m_options(), m_constants(), m_sources(), m_sections()
136 {
137           m_options = dynamic_cast<ListASTNode*>(other.m_options->clone());
138           m_constants = dynamic_cast<ListASTNode*>(other.m_constants->clone());
139           m_sources = dynamic_cast<ListASTNode*>(other.m_sources->clone());
140           m_sections = dynamic_cast<ListASTNode*>(other.m_sections->clone());
141 }
142 
printTree(int indent) const143 void CommandFileASTNode::printTree(int indent) const
144 {
145           ASTNode::printTree(indent);
146 
147           printIndent(indent + 1);
148           printf("options:\n");
149           if (m_options) m_options->printTree(indent + 2);
150 
151           printIndent(indent + 1);
152           printf("constants:\n");
153           if (m_constants) m_constants->printTree(indent + 2);
154 
155           printIndent(indent + 1);
156           printf("sources:\n");
157           if (m_sources) m_sources->printTree(indent + 2);
158 
159           printIndent(indent + 1);
160           printf("sections:\n");
161           if (m_sections) m_sections->printTree(indent + 2);
162 }
163 
164 #pragma mark = ExprASTNode =
165 
resultIntSize(int_size_t a,int_size_t b)166 int_size_t ExprASTNode::resultIntSize(int_size_t a, int_size_t b)
167 {
168           int_size_t result;
169           switch (a)
170           {
171                     case kWordSize:
172                               result = kWordSize;
173                               break;
174                     case kHalfWordSize:
175                               if (b == kWordSize)
176                               {
177                                         result = kWordSize;
178                               }
179                               else
180                               {
181                                         result = kHalfWordSize;
182                               }
183                               break;
184                     case kByteSize:
185                               if (b == kWordSize)
186                               {
187                                         result = kWordSize;
188                               }
189                               else if (b == kHalfWordSize)
190                               {
191                                         result = kHalfWordSize;
192                               }
193                               else
194                               {
195                                         result = kByteSize;
196                               }
197                               break;
198           }
199 
200           return result;
201 }
202 
203 #pragma mark = IntConstExprASTNode =
204 
IntConstExprASTNode(const IntConstExprASTNode & other)205 IntConstExprASTNode::IntConstExprASTNode(const IntConstExprASTNode & other)
206 :         ExprASTNode(other), m_value(other.m_value), m_size(other.m_size)
207 {
208 }
209 
printTree(int indent) const210 void IntConstExprASTNode::printTree(int indent) const
211 {
212           printIndent(indent);
213           char sizeChar='?';
214           switch (m_size)
215           {
216                     case kWordSize:
217                               sizeChar = 'w';
218                               break;
219                     case kHalfWordSize:
220                               sizeChar = 'h';
221                               break;
222                     case kByteSize:
223                               sizeChar = 'b';
224                               break;
225           }
226           printf("%s(%d:%c)\n", nodeName().c_str(), m_value, sizeChar);
227 }
228 
229 #pragma mark = VariableExprASTNode =
230 
VariableExprASTNode(const VariableExprASTNode & other)231 VariableExprASTNode::VariableExprASTNode(const VariableExprASTNode & other)
232 :         ExprASTNode(other), m_variable()
233 {
234           m_variable = new std::string(*other.m_variable);
235 }
236 
printTree(int indent) const237 void VariableExprASTNode::printTree(int indent) const
238 {
239           printIndent(indent);
240           printf("%s(%s)\n", nodeName().c_str(), m_variable->c_str());
241 }
242 
reduce(EvalContext & context)243 ExprASTNode * VariableExprASTNode::reduce(EvalContext & context)
244 {
245           if (!context.isVariableDefined(*m_variable))
246           {
247                     throw std::runtime_error(format_string("line %d: undefined variable '%s'", getFirstLine(), m_variable->c_str()));
248           }
249 
250           uint32_t value = context.getVariableValue(*m_variable);
251           int_size_t size = context.getVariableSize(*m_variable);
252           return new IntConstExprASTNode(value, size);
253 }
254 
255 #pragma mark = SymbolRefExprASTNode =
256 
SymbolRefExprASTNode(const SymbolRefExprASTNode & other)257 SymbolRefExprASTNode::SymbolRefExprASTNode(const SymbolRefExprASTNode & other)
258 :         ExprASTNode(other), m_symbol(NULL)
259 {
260           if (other.m_symbol)
261           {
262                     m_symbol = dynamic_cast<SymbolASTNode*>(other.m_symbol->clone());
263           }
264 }
265 
printTree(int indent) const266 void SymbolRefExprASTNode::printTree(int indent) const
267 {
268 }
269 
reduce(EvalContext & context)270 ExprASTNode * SymbolRefExprASTNode::reduce(EvalContext & context)
271 {
272           EvalContext::SourceFileManager * manager = context.getSourceFileManager();
273           if (!manager)
274           {
275                     throw std::runtime_error("no source manager available");
276           }
277 
278           if (!m_symbol)
279           {
280                     throw semantic_error("no symbol provided");
281           }
282 
283           // Get the name of the symbol
284           std::string * symbolName = m_symbol->getSymbolName();
285 //        if (!symbolName)
286 //        {
287 //                  throw semantic_error(format_string("line %d: no symbol name provided", getFirstLine()));
288 //        }
289 
290           // Get the source file.
291           std::string * sourceName = m_symbol->getSource();
292           SourceFile * sourceFile;
293 
294           if (sourceName)
295           {
296                     sourceFile = manager->getSourceFile(*sourceName);
297                     if (!sourceFile)
298                     {
299                               throw semantic_error(format_string("line %d: no source file named %s", getFirstLine(), sourceName->c_str()));
300                     }
301           }
302           else
303           {
304                     sourceFile = manager->getDefaultSourceFile();
305                     if (!sourceFile)
306                     {
307                               throw semantic_error(format_string("line %d: no default source file is set", getFirstLine()));
308                     }
309           }
310 
311           // open the file if it hasn't already been
312           if (!sourceFile->isOpen())
313           {
314                     sourceFile->open();
315           }
316 
317           // Make sure the source file supports symbols before going any further
318           if (symbolName && !sourceFile->supportsNamedSymbols())
319           {
320                     throw semantic_error(format_string("line %d: source file %s does not support symbols", getFirstLine(), sourceFile->getPath().c_str()));
321           }
322 
323     if (!symbolName && !sourceFile->hasEntryPoint())
324     {
325         throw semantic_error(format_string("line %d: source file %s does not have an entry point", getFirstLine(), sourceFile->getPath().c_str()));
326     }
327 
328           // Returns a const expr node with the symbol's value.
329           uint32_t value;
330     if (symbolName)
331     {
332         value = sourceFile->getSymbolValue(*symbolName);
333     }
334     else
335     {
336         value = sourceFile->getEntryPointAddress();
337     }
338           return new IntConstExprASTNode(value);
339 }
340 
341 #pragma mark = NegativeExprASTNode =
342 
NegativeExprASTNode(const NegativeExprASTNode & other)343 NegativeExprASTNode::NegativeExprASTNode(const NegativeExprASTNode & other)
344 :         ExprASTNode(other), m_expr()
345 {
346           m_expr = dynamic_cast<ExprASTNode*>(other.m_expr->clone());
347 }
348 
printTree(int indent) const349 void NegativeExprASTNode::printTree(int indent) const
350 {
351           ExprASTNode::printTree(indent);
352           if (m_expr) m_expr->printTree(indent + 1);
353 }
354 
reduce(EvalContext & context)355 ExprASTNode * NegativeExprASTNode::reduce(EvalContext & context)
356 {
357           if (!m_expr)
358           {
359                     return this;
360           }
361 
362           m_expr = m_expr->reduce(context);
363           IntConstExprASTNode * intConst = dynamic_cast<IntConstExprASTNode*>(m_expr.get());
364           if (intConst)
365           {
366               int32_t value = -(int32_t)intConst->getValue();
367                     return new IntConstExprASTNode((uint32_t)value, intConst->getSize());
368           }
369           else
370           {
371                     return this;
372           }
373 }
374 
375 #pragma mark = BooleanNotExprASTNode =
376 
BooleanNotExprASTNode(const BooleanNotExprASTNode & other)377 BooleanNotExprASTNode::BooleanNotExprASTNode(const BooleanNotExprASTNode & other)
378 :         ExprASTNode(other), m_expr()
379 {
380           m_expr = dynamic_cast<ExprASTNode*>(other.m_expr->clone());
381 }
382 
printTree(int indent) const383 void BooleanNotExprASTNode::printTree(int indent) const
384 {
385           ExprASTNode::printTree(indent);
386           if (m_expr) m_expr->printTree(indent + 1);
387 }
388 
reduce(EvalContext & context)389 ExprASTNode * BooleanNotExprASTNode::reduce(EvalContext & context)
390 {
391           if (!m_expr)
392           {
393                     return this;
394           }
395 
396           m_expr = m_expr->reduce(context);
397           IntConstExprASTNode * intConst = dynamic_cast<IntConstExprASTNode*>(m_expr.get());
398           if (intConst)
399           {
400               int32_t value = !((int32_t)intConst->getValue());
401                     return new IntConstExprASTNode((uint32_t)value, intConst->getSize());
402           }
403           else
404           {
405                     throw semantic_error(format_string("line %d: expression did not evaluate to an integer", m_expr->getFirstLine()));
406           }
407 }
408 
409 #pragma mark = SourceFileFunctionASTNode =
410 
SourceFileFunctionASTNode(const SourceFileFunctionASTNode & other)411 SourceFileFunctionASTNode::SourceFileFunctionASTNode(const SourceFileFunctionASTNode & other)
412 :         ExprASTNode(other), m_functionName(), m_sourceFile()
413 {
414           m_functionName = new std::string(*other.m_functionName);
415           m_sourceFile = new std::string(*other.m_sourceFile);
416 }
417 
printTree(int indent) const418 void SourceFileFunctionASTNode::printTree(int indent) const
419 {
420           ExprASTNode::printTree(indent);
421           printIndent(indent+1);
422 
423           // for some stupid reason the msft C++ compiler barfs on the following line if the ".get()" parts are remove,
424           // even though the first line of reduce() below has the same expression, just in parentheses. stupid compiler.
425           if (m_functionName.get() && m_sourceFile.get())
426           {
427                     printf("%s ( %s )\n", m_functionName->c_str(), m_sourceFile->c_str());
428           }
429 }
430 
reduce(EvalContext & context)431 ExprASTNode * SourceFileFunctionASTNode::reduce(EvalContext & context)
432 {
433           if (!(m_functionName && m_sourceFile))
434           {
435                     throw std::runtime_error("unset function name or source file");
436           }
437 
438           // Get source file manager from evaluation context. This will be the
439           // conversion controller itself.
440           EvalContext::SourceFileManager * mgr = context.getSourceFileManager();
441           if (!mgr)
442           {
443                     throw std::runtime_error("source file manager is not set");
444           }
445 
446           // Perform function
447           uint32_t functionResult = 0;
448           if (*m_functionName == "exists")
449           {
450                     functionResult = static_cast<uint32_t>(mgr->hasSourceFile(*m_sourceFile));
451           }
452 
453           // Return function result as an expression node
454           return new IntConstExprASTNode(functionResult);
455 }
456 
457 #pragma mark = DefinedOperatorASTNode =
458 
DefinedOperatorASTNode(const DefinedOperatorASTNode & other)459 DefinedOperatorASTNode::DefinedOperatorASTNode(const DefinedOperatorASTNode & other)
460 :         ExprASTNode(other), m_constantName()
461 {
462           m_constantName = new std::string(*other.m_constantName);
463 }
464 
printTree(int indent) const465 void DefinedOperatorASTNode::printTree(int indent) const
466 {
467           ExprASTNode::printTree(indent);
468           printIndent(indent+1);
469 
470           if (m_constantName)
471           {
472                     printf("defined ( %s )\n", m_constantName->c_str());
473           }
474 }
475 
reduce(EvalContext & context)476 ExprASTNode * DefinedOperatorASTNode::reduce(EvalContext & context)
477 {
478           assert(m_constantName);
479 
480           // Return function result as an expression node
481           return new IntConstExprASTNode(context.isVariableDefined(m_constantName) ? 1 : 0);
482 }
483 
484 #pragma mark = SizeofOperatorASTNode =
485 
SizeofOperatorASTNode(const SizeofOperatorASTNode & other)486 SizeofOperatorASTNode::SizeofOperatorASTNode(const SizeofOperatorASTNode & other)
487 :         ExprASTNode(other), m_constantName(), m_symbol()
488 {
489           m_constantName = new std::string(*other.m_constantName);
490           m_symbol = dynamic_cast<SymbolASTNode*>(other.m_symbol->clone());
491 }
492 
printTree(int indent) const493 void SizeofOperatorASTNode::printTree(int indent) const
494 {
495           ExprASTNode::printTree(indent);
496 
497           printIndent(indent+1);
498 
499           if (m_constantName)
500           {
501                     printf("sizeof: %s\n", m_constantName->c_str());
502           }
503           else if (m_symbol)
504           {
505                     printf("sizeof:\n");
506                     m_symbol->printTree(indent + 2);
507           }
508 }
509 
reduce(EvalContext & context)510 ExprASTNode * SizeofOperatorASTNode::reduce(EvalContext & context)
511 {
512           // One or the other must be defined.
513           assert(m_constantName || m_symbol);
514 
515           EvalContext::SourceFileManager * manager = context.getSourceFileManager();
516           assert(manager);
517 
518           unsigned sizeInBytes = 0;
519           SourceFile * sourceFile;
520 
521           if (m_symbol)
522           {
523                     // Get the symbol name.
524                     std::string * symbolName = m_symbol->getSymbolName();
525                     assert(symbolName);
526 
527                     // Get the source file, using the default if one is not specified.
528                     std::string * sourceName = m_symbol->getSource();
529                     if (sourceName)
530                     {
531                               sourceFile = manager->getSourceFile(*sourceName);
532                               if (!sourceFile)
533                               {
534                                         throw semantic_error(format_string("line %d: invalid source file: %s", getFirstLine(), sourceName->c_str()));
535                               }
536                     }
537                     else
538                     {
539                               sourceFile = manager->getDefaultSourceFile();
540                               if (!sourceFile)
541                               {
542                                         throw semantic_error(format_string("line %d: no default source file is set", getFirstLine()));
543                               }
544                     }
545 
546                     // Get the size of the symbol.
547                     if (sourceFile->hasSymbol(*symbolName))
548                     {
549                               sizeInBytes = sourceFile->getSymbolSize(*symbolName);
550                     }
551           }
552           else if (m_constantName)
553           {
554                     // See if the "constant" is really a constant or if it's a source name.
555                     if (manager->hasSourceFile(m_constantName))
556                     {
557                               sourceFile = manager->getSourceFile(m_constantName);
558                               if (sourceFile)
559                               {
560                                         sizeInBytes = sourceFile->getSize();
561                               }
562                     }
563                     else
564                     {
565                               // Regular constant.
566                               if (!context.isVariableDefined(*m_constantName))
567                               {
568                                         throw semantic_error(format_string("line %d: cannot get size of undefined constant %s", getFirstLine(), m_constantName->c_str()));
569                               }
570 
571                               int_size_t intSize = context.getVariableSize(*m_constantName);
572                               switch (intSize)
573                               {
574                                         case kWordSize:
575                                                   sizeInBytes = sizeof(uint32_t);
576                                                   break;
577                                         case kHalfWordSize:
578                                                   sizeInBytes = sizeof(uint16_t);
579                                                   break;
580                                         case kByteSize:
581                                                   sizeInBytes = sizeof(uint8_t);
582                                                   break;
583                               }
584                     }
585           }
586 
587           // Return function result as an expression node
588           return new IntConstExprASTNode(sizeInBytes);
589 }
590 
591 #pragma mark = BinaryOpExprASTNode =
592 
BinaryOpExprASTNode(const BinaryOpExprASTNode & other)593 BinaryOpExprASTNode::BinaryOpExprASTNode(const BinaryOpExprASTNode & other)
594 :         ExprASTNode(other), m_left(), m_op(other.m_op), m_right()
595 {
596           m_left = dynamic_cast<ExprASTNode*>(other.m_left->clone());
597           m_right = dynamic_cast<ExprASTNode*>(other.m_right->clone());
598 }
599 
printTree(int indent) const600 void BinaryOpExprASTNode::printTree(int indent) const
601 {
602           ExprASTNode::printTree(indent);
603 
604           printIndent(indent + 1);
605           printf("left:\n");
606           if (m_left) m_left->printTree(indent + 2);
607 
608           printIndent(indent + 1);
609           printf("op: %s\n", getOperatorName().c_str());
610 
611           printIndent(indent + 1);
612           printf("right:\n");
613           if (m_right) m_right->printTree(indent + 2);
614 }
615 
getOperatorName() const616 std::string BinaryOpExprASTNode::getOperatorName() const
617 {
618           switch (m_op)
619           {
620                     case kAdd:
621                               return "+";
622                     case kSubtract:
623                               return "-";
624                     case kMultiply:
625                               return "*";
626                     case kDivide:
627                               return "/";
628                     case kModulus:
629                               return "%";
630                     case kPower:
631                               return "**";
632                     case kBitwiseAnd:
633                               return "&";
634                     case kBitwiseOr:
635                               return "|";
636                     case kBitwiseXor:
637                               return "^";
638                     case kShiftLeft:
639                               return "<<";
640                     case kShiftRight:
641                               return ">>";
642                     case kLessThan:
643                               return "<";
644                     case kGreaterThan:
645                               return ">";
646                     case kLessThanEqual:
647                               return "<=";
648                     case kGreaterThanEqual:
649                               return ">";
650                     case kEqual:
651                               return "==";
652                     case kNotEqual:
653                               return "!=";
654                     case kBooleanAnd:
655                               return "&&";
656                     case kBooleanOr:
657                               return "||";
658           }
659 
660           return "???";
661 }
662 
663 //! \todo Fix power operator under windows!!!
664 //!
reduce(EvalContext & context)665 ExprASTNode * BinaryOpExprASTNode::reduce(EvalContext & context)
666 {
667           if (!m_left || !m_right)
668           {
669                     return this;
670           }
671 
672           IntConstExprASTNode * leftIntConst = NULL;
673           IntConstExprASTNode * rightIntConst = NULL;
674           uint32_t leftValue;
675           uint32_t rightValue;
676           uint32_t result = 0;
677 
678           // Always reduce the left hand side.
679           m_left = m_left->reduce(context);
680           leftIntConst = dynamic_cast<IntConstExprASTNode*>(m_left.get());
681           if (!leftIntConst)
682           {
683                     throw semantic_error(format_string("left hand side of %s operator failed to evaluate to an integer", getOperatorName().c_str()));
684           }
685           leftValue = leftIntConst->getValue();
686 
687           // Boolean && and || operators are handled separately so that we can perform
688           // short-circuit evaluation.
689           if (m_op == kBooleanAnd || m_op == kBooleanOr)
690           {
691                     // Reduce right hand side only if required to evaluate the boolean operator.
692                     if ((m_op == kBooleanAnd && leftValue != 0) || (m_op == kBooleanOr && leftValue == 0))
693                     {
694                               m_right = m_right->reduce(context);
695                               rightIntConst = dynamic_cast<IntConstExprASTNode*>(m_right.get());
696                               if (!rightIntConst)
697                               {
698                                         throw semantic_error(format_string("right hand side of %s operator failed to evaluate to an integer", getOperatorName().c_str()));
699                               }
700                               rightValue = rightIntConst->getValue();
701 
702                               // Perform the boolean operation.
703                               switch (m_op)
704                               {
705                                         case kBooleanAnd:
706                                                   result = leftValue && rightValue;
707                                                   break;
708 
709                                         case kBooleanOr:
710                                                   result = leftValue && rightValue;
711                                                   break;
712                               }
713                     }
714                     else if (m_op == kBooleanAnd)
715                     {
716                               // The left hand side is false, so the && operator's result must be false
717                               // without regard to the right hand side.
718                               result = 0;
719                     }
720                     else if (m_op == kBooleanOr)
721                     {
722                               // The left hand value is true so the || result is automatically true.
723                               result = 1;
724                     }
725           }
726           else
727           {
728                     // Reduce right hand side always for most operators.
729                     m_right = m_right->reduce(context);
730                     rightIntConst = dynamic_cast<IntConstExprASTNode*>(m_right.get());
731                     if (!rightIntConst)
732                     {
733                               throw semantic_error(format_string("right hand side of %s operator failed to evaluate to an integer", getOperatorName().c_str()));
734                     }
735                     rightValue = rightIntConst->getValue();
736 
737                     switch (m_op)
738                     {
739                               case kAdd:
740                                         result = leftValue + rightValue;
741                                         break;
742                               case kSubtract:
743                                         result = leftValue - rightValue;
744                                         break;
745                               case kMultiply:
746                                         result = leftValue * rightValue;
747                                         break;
748                               case kDivide:
749                                         result = leftValue / rightValue;
750                                         break;
751                               case kModulus:
752                                         result = leftValue % rightValue;
753                                         break;
754                               case kPower:
755                               #ifdef WIN32
756                                         result = 0;
757                               #else
758                                         result = lroundf(powf(float(leftValue), float(rightValue)));
759                               #endif
760                                         break;
761                               case kBitwiseAnd:
762                                         result = leftValue & rightValue;
763                                         break;
764                               case kBitwiseOr:
765                                         result = leftValue | rightValue;
766                                         break;
767                               case kBitwiseXor:
768                                         result = leftValue ^ rightValue;
769                                         break;
770                               case kShiftLeft:
771                                         result = leftValue << rightValue;
772                                         break;
773                               case kShiftRight:
774                                         result = leftValue >> rightValue;
775                                         break;
776                               case kLessThan:
777                                         result = leftValue < rightValue;
778                                         break;
779                               case kGreaterThan:
780                                         result = leftValue > rightValue;
781                                         break;
782                               case kLessThanEqual:
783                                         result = leftValue <= rightValue;
784                                         break;
785                               case kGreaterThanEqual:
786                                         result = leftValue >= rightValue;
787                                         break;
788                               case kEqual:
789                                         result = leftValue == rightValue;
790                                         break;
791                               case kNotEqual:
792                                         result = leftValue != rightValue;
793                                         break;
794                     }
795           }
796 
797           // Create the result value.
798           int_size_t resultSize;
799           if (leftIntConst && rightIntConst)
800           {
801                     resultSize = resultIntSize(leftIntConst->getSize(), rightIntConst->getSize());
802           }
803           else if (leftIntConst)
804           {
805                     resultSize = leftIntConst->getSize();
806           }
807           else
808           {
809                     // This shouldn't really be possible, but just in case.
810                     resultSize = kWordSize;
811           }
812           return new IntConstExprASTNode(result, resultSize);
813 }
814 
815 #pragma mark = IntSizeExprASTNode =
816 
IntSizeExprASTNode(const IntSizeExprASTNode & other)817 IntSizeExprASTNode::IntSizeExprASTNode(const IntSizeExprASTNode & other)
818 :         ExprASTNode(other), m_expr(), m_size(other.m_size)
819 {
820           m_expr = dynamic_cast<ExprASTNode*>(other.m_expr->clone());
821 }
822 
printTree(int indent) const823 void IntSizeExprASTNode::printTree(int indent) const
824 {
825           ExprASTNode::printTree(indent);
826 
827           char sizeChar='?';
828           switch (m_size)
829           {
830                     case kWordSize:
831                               sizeChar = 'w';
832                               break;
833                     case kHalfWordSize:
834                               sizeChar = 'h';
835                               break;
836                     case kByteSize:
837                               sizeChar = 'b';
838                               break;
839           }
840           printIndent(indent + 1);
841           printf("size: %c\n", sizeChar);
842 
843           printIndent(indent + 1);
844           printf("expr:\n");
845           if (m_expr) m_expr->printTree(indent + 2);
846 }
847 
reduce(EvalContext & context)848 ExprASTNode * IntSizeExprASTNode::reduce(EvalContext & context)
849 {
850           if (!m_expr)
851           {
852                     return this;
853           }
854 
855           m_expr = m_expr->reduce(context);
856           IntConstExprASTNode * intConst = dynamic_cast<IntConstExprASTNode*>(m_expr.get());
857           if (!intConst)
858           {
859                     return this;
860           }
861 
862           return new IntConstExprASTNode(intConst->getValue(), m_size);
863 }
864 
865 #pragma mark = ExprConstASTNode =
866 
ExprConstASTNode(const ExprConstASTNode & other)867 ExprConstASTNode::ExprConstASTNode(const ExprConstASTNode & other)
868 :         ConstASTNode(other), m_expr()
869 {
870           m_expr = dynamic_cast<ExprASTNode*>(other.m_expr->clone());
871 }
872 
printTree(int indent) const873 void ExprConstASTNode::printTree(int indent) const
874 {
875           ConstASTNode::printTree(indent);
876           if (m_expr) m_expr->printTree(indent + 1);
877 }
878 
879 #pragma mark = StringConstASTNode =
880 
StringConstASTNode(const StringConstASTNode & other)881 StringConstASTNode::StringConstASTNode(const StringConstASTNode & other)
882 :         ConstASTNode(other), m_value()
883 {
884           m_value = new std::string(other.m_value);
885 }
886 
printTree(int indent) const887 void StringConstASTNode::printTree(int indent) const
888 {
889           printIndent(indent);
890           printf("%s(%s)\n", nodeName().c_str(), m_value->c_str());
891 }
892 
893 #pragma mark = BlobConstASTNode =
894 
BlobConstASTNode(const BlobConstASTNode & other)895 BlobConstASTNode::BlobConstASTNode(const BlobConstASTNode & other)
896 :         ConstASTNode(other), m_blob()
897 {
898           m_blob = new Blob(*other.m_blob);
899 }
900 
printTree(int indent) const901 void BlobConstASTNode::printTree(int indent) const
902 {
903           printIndent(indent);
904 
905           const uint8_t * dataPtr = m_blob->getData();
906           unsigned dataLen = m_blob->getLength();
907           printf("%s(%p:%d)\n", nodeName().c_str(), dataPtr, dataLen);
908 }
909 
910 #pragma mark = IVTConstASTNode =
911 
IVTConstASTNode(const IVTConstASTNode & other)912 IVTConstASTNode::IVTConstASTNode(const IVTConstASTNode & other)
913 :         ConstASTNode(other), m_fields()
914 {
915           m_fields = dynamic_cast<ListASTNode*>(other.m_fields->clone());
916 }
917 
printTree(int indent) const918 void IVTConstASTNode::printTree(int indent) const
919 {
920           printIndent(indent);
921           printf("%s:\n", nodeName().c_str());
922     if (m_fields)
923     {
924         m_fields->printTree(indent + 1);
925     }
926 }
927 
928 #pragma mark = AssignmentASTNode =
929 
AssignmentASTNode(const AssignmentASTNode & other)930 AssignmentASTNode::AssignmentASTNode(const AssignmentASTNode & other)
931 :         ASTNode(other), m_ident(), m_value()
932 {
933           m_ident = new std::string(*other.m_ident);
934           m_value = dynamic_cast<ConstASTNode*>(other.m_value->clone());
935 }
936 
printTree(int indent) const937 void AssignmentASTNode::printTree(int indent) const
938 {
939           printIndent(indent);
940           printf("%s(%s)\n", nodeName().c_str(), m_ident->c_str());
941 
942           if (m_value) m_value->printTree(indent + 1);
943 }
944 
945 #pragma mark = SourceDefASTNode =
946 
SourceDefASTNode(const SourceDefASTNode & other)947 SourceDefASTNode::SourceDefASTNode(const SourceDefASTNode & other)
948 :         ASTNode(other), m_name()
949 {
950           m_name = new std::string(*other.m_name);
951 }
952 
953 #pragma mark = PathSourceDefASTNode =
954 
PathSourceDefASTNode(const PathSourceDefASTNode & other)955 PathSourceDefASTNode::PathSourceDefASTNode(const PathSourceDefASTNode & other)
956 :         SourceDefASTNode(other), m_path()
957 {
958           m_path = new std::string(*other.m_path);
959 }
960 
printTree(int indent) const961 void PathSourceDefASTNode::printTree(int indent) const
962 {
963           SourceDefASTNode::printTree(indent);
964 
965           printIndent(indent+1);
966           printf("path: %s\n", m_path->c_str());
967 
968           printIndent(indent+1);
969           printf("attributes:\n");
970           if (m_attributes)
971           {
972                     m_attributes->printTree(indent+2);
973           }
974 }
975 
976 #pragma mark = ExternSourceDefASTNode =
977 
ExternSourceDefASTNode(const ExternSourceDefASTNode & other)978 ExternSourceDefASTNode::ExternSourceDefASTNode(const ExternSourceDefASTNode & other)
979 :         SourceDefASTNode(other), m_expr()
980 {
981           m_expr = dynamic_cast<ExprASTNode*>(other.m_expr->clone());
982 }
983 
printTree(int indent) const984 void ExternSourceDefASTNode::printTree(int indent) const
985 {
986           SourceDefASTNode::printTree(indent);
987 
988           printIndent(indent+1);
989           printf("expr:\n");
990           if (m_expr) m_expr->printTree(indent + 2);
991 
992           printIndent(indent+1);
993           printf("attributes:\n");
994           if (m_attributes)
995           {
996                     m_attributes->printTree(indent+2);
997           }
998 }
999 
1000 #pragma mark = SectionContentsASTNode =
1001 
SectionContentsASTNode(const SectionContentsASTNode & other)1002 SectionContentsASTNode::SectionContentsASTNode(const SectionContentsASTNode & other)
1003 :         ASTNode(other), m_sectionExpr()
1004 {
1005           m_sectionExpr = dynamic_cast<ExprASTNode*>(other.m_sectionExpr->clone());
1006 }
1007 
printTree(int indent) const1008 void SectionContentsASTNode::printTree(int indent) const
1009 {
1010           ASTNode::printTree(indent);
1011 
1012           printIndent(indent + 1);
1013           printf("section#:\n");
1014           if (m_sectionExpr) m_sectionExpr->printTree(indent + 2);
1015 }
1016 
1017 #pragma mark = DataSectionContentsASTNode =
1018 
DataSectionContentsASTNode(const DataSectionContentsASTNode & other)1019 DataSectionContentsASTNode::DataSectionContentsASTNode(const DataSectionContentsASTNode & other)
1020 :         SectionContentsASTNode(other), m_contents()
1021 {
1022           m_contents = dynamic_cast<ASTNode*>(other.m_contents->clone());
1023 }
1024 
printTree(int indent) const1025 void DataSectionContentsASTNode::printTree(int indent) const
1026 {
1027           SectionContentsASTNode::printTree(indent);
1028 
1029           if (m_contents)
1030           {
1031                     m_contents->printTree(indent + 1);
1032           }
1033 }
1034 
1035 #pragma mark = BootableSectionContentsASTNode =
1036 
BootableSectionContentsASTNode(const BootableSectionContentsASTNode & other)1037 BootableSectionContentsASTNode::BootableSectionContentsASTNode(const BootableSectionContentsASTNode & other)
1038 :         SectionContentsASTNode(other), m_statements()
1039 {
1040           m_statements = dynamic_cast<ListASTNode*>(other.m_statements->clone());
1041 }
1042 
printTree(int indent) const1043 void BootableSectionContentsASTNode::printTree(int indent) const
1044 {
1045           SectionContentsASTNode::printTree(indent);
1046 
1047           printIndent(indent + 1);
1048           printf("statements:\n");
1049           if (m_statements) m_statements->printTree(indent + 2);
1050 }
1051 
1052 #pragma mark = IfStatementASTNode =
1053 
1054 //! \warning Be careful; this method could enter an infinite loop if m_nextIf feeds
1055 //!                 back onto itself. m_nextIf must be NULL at some point down the next if list.
IfStatementASTNode(const IfStatementASTNode & other)1056 IfStatementASTNode::IfStatementASTNode(const IfStatementASTNode & other)
1057 :         StatementASTNode(),
1058           m_conditionExpr(),
1059           m_ifStatements(),
1060           m_nextIf(),
1061           m_elseStatements()
1062 {
1063           m_conditionExpr = dynamic_cast<ExprASTNode*>(other.m_conditionExpr->clone());
1064           m_ifStatements = dynamic_cast<ListASTNode*>(other.m_ifStatements->clone());
1065           m_nextIf = dynamic_cast<IfStatementASTNode*>(other.m_nextIf->clone());
1066           m_elseStatements = dynamic_cast<ListASTNode*>(other.m_elseStatements->clone());
1067 }
1068 
1069 #pragma mark = ModeStatementASTNode =
1070 
ModeStatementASTNode(const ModeStatementASTNode & other)1071 ModeStatementASTNode::ModeStatementASTNode(const ModeStatementASTNode & other)
1072 :         StatementASTNode(other), m_modeExpr()
1073 {
1074           m_modeExpr = dynamic_cast<ExprASTNode*>(other.m_modeExpr->clone());
1075 }
1076 
printTree(int indent) const1077 void ModeStatementASTNode::printTree(int indent) const
1078 {
1079           StatementASTNode::printTree(indent);
1080           printIndent(indent + 1);
1081           printf("mode:\n");
1082           if (m_modeExpr) m_modeExpr->printTree(indent + 2);
1083 }
1084 
1085 #pragma mark = MessageStatementASTNode =
1086 
MessageStatementASTNode(const MessageStatementASTNode & other)1087 MessageStatementASTNode::MessageStatementASTNode(const MessageStatementASTNode & other)
1088 :         StatementASTNode(other), m_type(other.m_type), m_message()
1089 {
1090           m_message = new std::string(*other.m_message);
1091 }
1092 
printTree(int indent) const1093 void MessageStatementASTNode::printTree(int indent) const
1094 {
1095           StatementASTNode::printTree(indent);
1096           printIndent(indent + 1);
1097           printf("%s: %s\n", getTypeName(), m_message->c_str());
1098 }
1099 
getTypeName() const1100 const char * MessageStatementASTNode::getTypeName() const
1101 {
1102           switch (m_type)
1103           {
1104                     case kInfo:
1105                               return "info";
1106 
1107                     case kWarning:
1108                               return "warning";
1109 
1110                     case kError:
1111                               return "error";
1112           }
1113 
1114           return "unknown";
1115 }
1116 
1117 #pragma mark = LoadStatementASTNode =
1118 
LoadStatementASTNode(const LoadStatementASTNode & other)1119 LoadStatementASTNode::LoadStatementASTNode(const LoadStatementASTNode & other)
1120 :         StatementASTNode(other), m_data(), m_target(), m_isDCDLoad(other.m_isDCDLoad)
1121 {
1122           m_data = other.m_data->clone();
1123           m_target = other.m_target->clone();
1124 }
1125 
printTree(int indent) const1126 void LoadStatementASTNode::printTree(int indent) const
1127 {
1128           StatementASTNode::printTree(indent);
1129 
1130           printIndent(indent + 1);
1131           printf("data:\n");
1132           if (m_data) m_data->printTree(indent + 2);
1133 
1134           printIndent(indent + 1);
1135           printf("target:\n");
1136           if (m_target) m_target->printTree(indent + 2);
1137 }
1138 
1139 #pragma mark = CallStatementASTNode =
1140 
CallStatementASTNode(const CallStatementASTNode & other)1141 CallStatementASTNode::CallStatementASTNode(const CallStatementASTNode & other)
1142 :         StatementASTNode(other), m_type(other.m_type), m_target(), m_arg()
1143 {
1144           m_target = other.m_target->clone();
1145           m_arg = other.m_arg->clone();
1146 }
1147 
printTree(int indent) const1148 void CallStatementASTNode::printTree(int indent) const
1149 {
1150           printIndent(indent);
1151           printf("%s(%s)%s\n", nodeName().c_str(), (m_type == kCallType ? "call" : "jump"), (m_isHAB ? "/HAB" : ""));
1152 
1153           printIndent(indent + 1);
1154           printf("target:\n");
1155           if (m_target) m_target->printTree(indent + 2);
1156 
1157           printIndent(indent + 1);
1158           printf("arg:\n");
1159           if (m_arg) m_arg->printTree(indent + 2);
1160 }
1161 
1162 #pragma mark = SourceASTNode =
1163 
SourceASTNode(const SourceASTNode & other)1164 SourceASTNode::SourceASTNode(const SourceASTNode & other)
1165 :         ASTNode(other), m_name()
1166 {
1167           m_name = new std::string(*other.m_name);
1168 }
1169 
printTree(int indent) const1170 void SourceASTNode::printTree(int indent) const
1171 {
1172           printIndent(indent);
1173           printf("%s(%s)\n", nodeName().c_str(), m_name->c_str());
1174 }
1175 
1176 #pragma mark = SectionMatchListASTNode =
1177 
SectionMatchListASTNode(const SectionMatchListASTNode & other)1178 SectionMatchListASTNode::SectionMatchListASTNode(const SectionMatchListASTNode & other)
1179 :         ASTNode(other), m_sections(), m_source()
1180 {
1181           if (other.m_sections)
1182           {
1183                     m_sections = dynamic_cast<ListASTNode *>(other.m_sections->clone());
1184           }
1185 
1186           if (other.m_source)
1187           {
1188                     m_source = new std::string(*other.m_source);
1189           }
1190 }
1191 
printTree(int indent) const1192 void SectionMatchListASTNode::printTree(int indent) const
1193 {
1194           ASTNode::printTree(indent);
1195 
1196           printIndent(indent+1);
1197           printf("sections:\n");
1198           if (m_sections)
1199           {
1200                     m_sections->printTree(indent+2);
1201           }
1202 
1203           printIndent(indent+1);
1204           printf("source: ");
1205           if (m_source)
1206           {
1207                     printf("%s\n", m_source->c_str());
1208           }
1209           else
1210           {
1211                     printf("\n");
1212           }
1213 }
1214 
1215 #pragma mark = SectionASTNode =
1216 
SectionASTNode(const SectionASTNode & other)1217 SectionASTNode::SectionASTNode(const SectionASTNode & other)
1218 :         ASTNode(other), m_name(), m_source()
1219 {
1220           m_action = other.m_action;
1221 
1222           if (other.m_name)
1223           {
1224                     m_name = new std::string(*other.m_name);
1225           }
1226 
1227           if (other.m_source)
1228           {
1229                     m_source = new std::string(*other.m_source);
1230           }
1231 }
1232 
printTree(int indent) const1233 void SectionASTNode::printTree(int indent) const
1234 {
1235           printIndent(indent);
1236 
1237           const char * actionName;
1238           switch (m_action)
1239           {
1240                     case kInclude:
1241                               actionName = "include";
1242                               break;
1243                     case kExclude:
1244                               actionName = "exclude";
1245                               break;
1246           }
1247 
1248           if (m_source)
1249           {
1250                     printf("%s(%s:%s:%s)\n", nodeName().c_str(), actionName, m_name->c_str(), m_source->c_str());
1251           }
1252           else
1253           {
1254                     printf("%s(%s:%s)\n", nodeName().c_str(), actionName, m_name->c_str());
1255           }
1256 }
1257 
1258 #pragma mark = SymbolASTNode =
1259 
SymbolASTNode(const SymbolASTNode & other)1260 SymbolASTNode::SymbolASTNode(const SymbolASTNode & other)
1261 :         ASTNode(other), m_symbol(), m_source()
1262 {
1263           m_symbol = new std::string(*other.m_symbol);
1264           m_source = new std::string(*other.m_source);
1265 }
1266 
printTree(int indent) const1267 void SymbolASTNode::printTree(int indent) const
1268 {
1269           printIndent(indent);
1270 
1271           const char * symbol = NULL;
1272           if (m_symbol)
1273           {
1274                     symbol = m_symbol->c_str();
1275           }
1276 
1277           const char * source = NULL;
1278           if (m_source)
1279           {
1280                     source = m_source->c_str();
1281           }
1282 
1283           printf("%s(", nodeName().c_str());
1284           if (source)
1285           {
1286                     printf("%s", source);
1287           }
1288           else
1289           {
1290                     printf(".");
1291           }
1292           printf(":");
1293           if (symbol)
1294           {
1295                     printf("%s", symbol);
1296           }
1297           else
1298           {
1299                     printf(".");
1300           }
1301           printf(")\n");
1302 }
1303 
1304 #pragma mark = AddressRangeASTNode =
1305 
AddressRangeASTNode(const AddressRangeASTNode & other)1306 AddressRangeASTNode::AddressRangeASTNode(const AddressRangeASTNode & other)
1307 :         ASTNode(other), m_begin(), m_end()
1308 {
1309           m_begin = other.m_begin->clone();
1310           m_end = other.m_end->clone();
1311 }
1312 
printTree(int indent) const1313 void AddressRangeASTNode::printTree(int indent) const
1314 {
1315           ASTNode::printTree(indent);
1316 
1317           printIndent(indent + 1);
1318           printf("begin:\n");
1319           if (m_begin) m_begin->printTree(indent + 2);
1320 
1321           printIndent(indent + 1);
1322           printf("end:\n");
1323           if (m_end) m_end->printTree(indent + 2);
1324 }
1325 
1326 #pragma mark = FromStatementASTNode =
1327 
FromStatementASTNode(std::string * source,ListASTNode * statements)1328 FromStatementASTNode::FromStatementASTNode(std::string * source, ListASTNode * statements)
1329 :         StatementASTNode(), m_source(source), m_statements(statements)
1330 {
1331 }
1332 
FromStatementASTNode(const FromStatementASTNode & other)1333 FromStatementASTNode::FromStatementASTNode(const FromStatementASTNode & other)
1334 :         StatementASTNode(), m_source(), m_statements()
1335 {
1336           m_source = new std::string(*other.m_source);
1337           m_statements = dynamic_cast<ListASTNode*>(other.m_statements->clone());
1338 }
1339 
printTree(int indent) const1340 void FromStatementASTNode::printTree(int indent) const
1341 {
1342           ASTNode::printTree(indent);
1343 
1344           printIndent(indent + 1);
1345           printf("source: ");
1346           if (m_source) printf("%s\n", m_source->c_str());
1347 
1348           printIndent(indent + 1);
1349           printf("statements:\n");
1350           if (m_statements) m_statements->printTree(indent + 2);
1351 }
1352 
1353