xref: /netbsd-src/external/bsd/elftosb/dist/elftosb2/ElftosbAST.cpp (revision 616728154accb2da0d5a0126e1280ca29f8ba569)
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