Пример #1
0
//! Takes an AST node subclass and returns an appropriate DataTarget object that contains
//! the same information. Supported AST node types are:
//! - SymbolASTNode
//! - NaturalLocationASTNode
//! - AddressRangeASTNode
//!
//! \exception elftosb::semantic_error Thrown if a semantic problem is found with
//!		the target node.
DataTarget * ConversionController::createTargetFromNode(ASTNode * targetNode)
{
	assert(targetNode);
	
	DataTarget * target = NULL;
	SymbolASTNode * symbolNode;
	NaturalLocationASTNode * naturalNode;
	AddressRangeASTNode * addressNode;
	
	if (symbolNode = dynamic_cast<SymbolASTNode*>(targetNode))
	{
		SourceFile * sourceFile = getSourceFromName(symbolNode->getSource(), symbolNode->getFirstLine());
		std::string * symbolName = symbolNode->getSymbolName();
		
		// symbol name is optional
		if (symbolName)
		{
			if (!sourceFile->supportsNamedSymbols())
			{
				throw std::runtime_error(format_string("line %d: source does not support symbols", symbolNode->getFirstLine()));
			}
			
			target = sourceFile->createDataTargetForSymbol(*symbolName);
			if (!target)
			{
				throw std::runtime_error(format_string("line %d: source does not have a symbol with that name", symbolNode->getFirstLine()));
			}
		}
		else
		{
			// no symbol name was specified so use entry point
			target = sourceFile->createDataTargetForEntryPoint();
			if (!target)
			{
				throw std::runtime_error(format_string("line %d: source does not have an entry point", symbolNode->getFirstLine()));
			}
		}
	}
	else if (naturalNode = dynamic_cast<NaturalLocationASTNode*>(targetNode))
	{
		// the target is the source's natural location
		target = new NaturalDataTarget();
	}
	else if (addressNode = dynamic_cast<AddressRangeASTNode*>(targetNode))
	{
		// evaluate begin address
		ExprASTNode * beginExpr = dynamic_cast<ExprASTNode*>(addressNode->getBegin());
		if (!beginExpr)
		{
			throw semantic_error("address range must always have a beginning expression");
		}
		IntConstExprASTNode * beginIntExpr = dynamic_cast<IntConstExprASTNode*>(beginExpr->reduce(m_context));
		if (!beginIntExpr)
		{
			throw semantic_error("address range begin did not evaluate to an integer");
		}
		uint32_t beginAddress = static_cast<uint32_t>(beginIntExpr->getValue());
		
		// evaluate end address
		ExprASTNode * endExpr = dynamic_cast<ExprASTNode*>(addressNode->getEnd());
		uint32_t endAddress = 0;
		bool hasEndAddress = false;
		if (endExpr)
		{
			IntConstExprASTNode * endIntExpr = dynamic_cast<IntConstExprASTNode*>(endExpr->reduce(m_context));
			if (!endIntExpr)
			{
				throw semantic_error("address range end did not evaluate to an integer");
			}
			endAddress = static_cast<uint32_t>(endIntExpr->getValue());
			hasEndAddress = true;
		}
		
		// create target
		if (hasEndAddress)
		{
			target = new ConstantDataTarget(beginAddress, endAddress);
		}
		else
		{
			target = new ConstantDataTarget(beginAddress);
		}
	}
	else
	{
		throw semantic_error("unexpected load target node type");
	}
	
	return target;
}