]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - tools/elftosb/elftosb2/ElftosbAST.cpp
merged tx6dl-devel into denx master branch
[karo-tx-uboot.git] / tools / elftosb / elftosb2 / ElftosbAST.cpp
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
19 void ASTNode::printTree(int indent) const
20 {
21         printIndent(indent);
22         printf("%s\n", nodeName().c_str());
23 }
24
25 void ASTNode::printIndent(int indent) const
26 {
27         int i;
28         for (i=0; i<indent; ++i)
29         {
30                 printf("   ");
31         }
32 }
33
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
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
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 //!
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().
74 void ListASTNode::appendNode(ASTNode * node)
75 {
76         if (node)
77         {
78                 m_list.push_back(node);
79                 updateLocation();
80         }
81 }
82
83 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
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
129 CommandFileASTNode::CommandFileASTNode()
130 :       ASTNode(), m_options(), m_constants(), m_sources(), m_sections()
131 {
132 }
133
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
143 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
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
205 IntConstExprASTNode::IntConstExprASTNode(const IntConstExprASTNode & other)
206 :       ExprASTNode(other), m_value(other.m_value), m_size(other.m_size)
207 {
208 }
209
210 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
231 VariableExprASTNode::VariableExprASTNode(const VariableExprASTNode & other)
232 :       ExprASTNode(other), m_variable()
233 {
234         m_variable = new std::string(*other.m_variable);
235 }
236
237 void VariableExprASTNode::printTree(int indent) const
238 {
239         printIndent(indent);
240         printf("%s(%s)\n", nodeName().c_str(), m_variable->c_str());
241 }
242
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
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
266 void SymbolRefExprASTNode::printTree(int indent) const
267 {
268 }
269
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
343 NegativeExprASTNode::NegativeExprASTNode(const NegativeExprASTNode & other)
344 :       ExprASTNode(other), m_expr()
345 {
346         m_expr = dynamic_cast<ExprASTNode*>(other.m_expr->clone());
347 }
348
349 void NegativeExprASTNode::printTree(int indent) const
350 {
351         ExprASTNode::printTree(indent);
352         if (m_expr) m_expr->printTree(indent + 1);
353 }
354
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
377 BooleanNotExprASTNode::BooleanNotExprASTNode(const BooleanNotExprASTNode & other)
378 :       ExprASTNode(other), m_expr()
379 {
380         m_expr = dynamic_cast<ExprASTNode*>(other.m_expr->clone());
381 }
382
383 void BooleanNotExprASTNode::printTree(int indent) const
384 {
385         ExprASTNode::printTree(indent);
386         if (m_expr) m_expr->printTree(indent + 1);
387 }
388
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
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
418 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
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
459 DefinedOperatorASTNode::DefinedOperatorASTNode(const DefinedOperatorASTNode & other)
460 :       ExprASTNode(other), m_constantName()
461 {
462         m_constantName = new std::string(*other.m_constantName);
463 }
464
465 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
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
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
493 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
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
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
600 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
616 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 //!
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
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
823 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
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
867 ExprConstASTNode::ExprConstASTNode(const ExprConstASTNode & other)
868 :       ConstASTNode(other), m_expr()
869 {
870         m_expr = dynamic_cast<ExprASTNode*>(other.m_expr->clone());
871 }
872
873 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
881 StringConstASTNode::StringConstASTNode(const StringConstASTNode & other)
882 :       ConstASTNode(other), m_value()
883 {
884         m_value = new std::string(other.m_value);
885 }
886
887 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
895 BlobConstASTNode::BlobConstASTNode(const BlobConstASTNode & other)
896 :       ConstASTNode(other), m_blob()
897 {
898         m_blob = new Blob(*other.m_blob);
899 }
900
901 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
912 IVTConstASTNode::IVTConstASTNode(const IVTConstASTNode & other)
913 :       ConstASTNode(other), m_fields()
914 {
915         m_fields = dynamic_cast<ListASTNode*>(other.m_fields->clone());
916 }
917
918 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
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
937 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
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
955 PathSourceDefASTNode::PathSourceDefASTNode(const PathSourceDefASTNode & other)
956 :       SourceDefASTNode(other), m_path()
957 {
958         m_path = new std::string(*other.m_path);
959 }
960
961 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
978 ExternSourceDefASTNode::ExternSourceDefASTNode(const ExternSourceDefASTNode & other)
979 :       SourceDefASTNode(other), m_expr()
980 {
981         m_expr = dynamic_cast<ExprASTNode*>(other.m_expr->clone());
982 }
983
984 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
1002 SectionContentsASTNode::SectionContentsASTNode(const SectionContentsASTNode & other)
1003 :       ASTNode(other), m_sectionExpr()
1004 {
1005         m_sectionExpr = dynamic_cast<ExprASTNode*>(other.m_sectionExpr->clone());
1006 }
1007
1008 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
1019 DataSectionContentsASTNode::DataSectionContentsASTNode(const DataSectionContentsASTNode & other)
1020 :       SectionContentsASTNode(other), m_contents()
1021 {
1022         m_contents = dynamic_cast<ASTNode*>(other.m_contents->clone());
1023 }
1024
1025 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
1037 BootableSectionContentsASTNode::BootableSectionContentsASTNode(const BootableSectionContentsASTNode & other)
1038 :       SectionContentsASTNode(other), m_statements()
1039 {
1040         m_statements = dynamic_cast<ListASTNode*>(other.m_statements->clone());
1041 }
1042
1043 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.
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
1071 ModeStatementASTNode::ModeStatementASTNode(const ModeStatementASTNode & other)
1072 :       StatementASTNode(other), m_modeExpr()
1073 {
1074         m_modeExpr = dynamic_cast<ExprASTNode*>(other.m_modeExpr->clone());
1075 }
1076
1077 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
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
1093 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
1100 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
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
1126 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
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
1148 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
1164 SourceASTNode::SourceASTNode(const SourceASTNode & other)
1165 :       ASTNode(other), m_name()
1166 {
1167         m_name = new std::string(*other.m_name);
1168 }
1169
1170 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
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
1192 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: ", m_source->c_str());
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
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
1233 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
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
1267 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(source);
1287         }
1288         else
1289         {
1290                 printf(".");
1291         }
1292         printf(":");
1293         if (symbol)
1294         {
1295                 printf(symbol);
1296         }
1297         else
1298         {
1299                 printf(".");
1300         }
1301         printf(")\n");
1302 }
1303
1304 #pragma mark = AddressRangeASTNode =
1305
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
1313 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
1328 FromStatementASTNode::FromStatementASTNode(std::string * source, ListASTNode * statements)
1329 :       StatementASTNode(), m_source(source), m_statements(statements)
1330 {
1331 }
1332
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
1340 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