void dDAGFunctionStatementFlow::CompileCIL(dCIL& cil)
{
	//	m_backPatchStart = cil.GetLast();
	//	m_currentBreakLabel = cil.NewLabel();
	//	m_currentContinueLabel = "";
	
	dString loopBeginLabel (cil.NewLabel());
	dCILInstrLabel* const entryLabel = new dCILInstrLabel(cil, loopBeginLabel);
	entryLabel->Trace();

	if (m_loopBodyStmt) {
		m_loopBodyStmt->CompileCIL(cil);
	}

	dDAGFunctionStatement* const posFixStmt = GetPostFixStatement();
	if (posFixStmt) {
		dAssert(0);
		posFixStmt->CompileCIL(cil);
	}

	if (m_testExpression) {
		m_testExpression->CompileCIL(cil);

		dCILInstrConditional* const conditional = new dCILInstrConditional(cil, dCILInstrConditional::m_if, m_testExpression->m_result.m_label, m_testExpression->m_result.GetType(), entryLabel->GetArg0().m_label, cil.NewLabel());
		conditional->Trace();

		dCILInstrLabel* const exitLabel = new dCILInstrLabel(cil, conditional->GetArg2().m_label);
		exitLabel->Trace();
		conditional->SetTargets (entryLabel, exitLabel);

	} else {
		dAssert (0);
	}

}
bool dFlowControlBlock::ApplySubExpressionsElimination(dCIL& program)
{
	bool ret = false;
	const dCIL::dListNode* const lastNode = m_end->GetNext();
	_ASSERTE (lastNode);
	for (dCIL::dListNode* node = m_leader; node != lastNode; node = node->GetNext()) {
		dTreeAdressStmt& stmt = node->GetInfo();
		if (stmt.m_instruction == dTreeAdressStmt::m_assigment) {
			dCIL::dListNode* next = NULL;
			for (dCIL::dListNode* node1 = node->GetNext(); node1 != lastNode; node1 = next) {
				dTreeAdressStmt& stmt1 = node1->GetInfo();
				next = node1->GetNext();
				if (stmt.m_arg0.m_label == stmt1.m_arg0.m_label) {
					break;
				}
				if ((stmt.m_instruction == stmt1.m_instruction) && (stmt.m_operator == stmt1.m_operator) &&	(stmt.m_arg1.m_label == stmt1.m_arg1.m_label) && (stmt.m_arg2.m_label == stmt1.m_arg2.m_label)) {
					for (dCIL::dListNode* node2 = node1->GetNext(); node2 != lastNode; node2 = node2->GetNext()) {
						dTreeAdressStmt& stmt2 = node2->GetInfo();
						if (stmt2.m_arg0.m_label == stmt1.m_arg0.m_label) {
							ret = true;
							stmt2.m_arg0.m_label = stmt.m_arg0.m_label;
						}
						if (stmt2.m_arg1.m_label == stmt1.m_arg0.m_label) {
							ret = true;
							stmt2.m_arg1.m_label = stmt.m_arg0.m_label;
						}
						if (stmt2.m_arg2.m_label == stmt1.m_arg0.m_label) {
							ret = true;
							stmt2.m_arg2.m_label = stmt.m_arg0.m_label;
						}
					}

					if (stmt1.m_arg0.m_label[0] == 't') {
						program.Remove(node1);
//Trace();
					}
				} 
			}
		}
	}
	return ret;
}
void dDAGFunctionNode::ConvertToTarget (dCIL& cil)
{
	cil.RegisterAllocation (m_functionStart);
}
void dDAGFunctionNode::CompileCIL(dCIL& cil)  
{
	dAssert (m_body);
	dDAGClassNode* const myClass = GetClass();

	cil.ResetTemporaries();
	dString returnVariable (cil.NewTemp());

	dString functionName (myClass->GetFunctionName (m_name, m_parameters));
	dCILInstrFunction* const function = new dCILInstrFunction (cil, functionName, m_returnType->GetArgType());
	m_functionStart = function->GetNode();

	if (!m_isStatic) {
		dAssert (0);
//		dList<dDAGParameterNode*>::dListNode* const argNode = m_parameters.GetFirst();
//		dDAGParameterNode* const arg = argNode->GetInfo();
//		m_opertatorThis = arg->m_result.m_label;
	}

	// emit the function arguments
	for (dList<dDAGParameterNode*>::dListNode* argNode = m_parameters.GetFirst(); argNode; argNode = argNode->GetNext()) {
		dDAGParameterNode* const arg = argNode->GetInfo();
		arg->m_result = function->AddParameter (arg->m_name, arg->m_type->GetArgType())->GetInfo();
	}
	function->Trace();

	dCILInstrLabel* const entryPoint = new dCILInstrLabel(cil, cil.NewLabel());
	entryPoint->Trace();

	for (dList<dDAGParameterNode*>::dListNode* argNode = m_parameters.GetFirst(); argNode; argNode = argNode->GetNext()) {
		dDAGParameterNode* const arg = argNode->GetInfo();

		dTree<dCILInstr::dArg, dString>::dTreeNode* const varNameNode = m_body->FindVariable(arg->m_name);
		dAssert (varNameNode);
		dCILInstrArgument* const localVariable = new dCILInstrArgument(cil, varNameNode->GetInfo().m_label, varNameNode->GetInfo().GetType());
		localVariable->Trace();
	}


	for (dList<dDAGParameterNode*>::dListNode* argNode = m_parameters.GetFirst(); argNode; argNode = argNode->GetNext()) {
		dDAGParameterNode* const arg = argNode->GetInfo();
		dTree<dCILInstr::dArg, dString>::dTreeNode* const varNameNode = m_body->FindVariable(arg->m_name);
		dAssert (varNameNode);
		//dCILInstrStore* const store = new dCILInstrStore(cil, varNameNode->GetInfo().m_label, varNameNode->GetInfo().GetType(), arg->m_name, arg->GetType()->GetArgType());
		dString localVariableAliasName(cil.NewTemp());
		dCILInstrMove* const store = new dCILInstrMove(cil, localVariableAliasName, arg->GetType()->GetArgType(), varNameNode->GetInfo().m_label, varNameNode->GetInfo().GetType());
		//arg->m_result =  store->GetArg0();
		varNameNode->GetInfo().m_label = localVariableAliasName;
		store->Trace();
	}


	m_body->CompileCIL(cil);
	if (!m_returnType->GetArgType().m_isPointer && (m_returnType->GetArgType().m_intrinsicType == dCILInstr::m_void)) {
		 if (!cil.GetLast()->GetInfo()->GetAsReturn()) {
			dCILInstrReturn* const ret = new dCILInstrReturn(cil, "", dCILInstr::dArgType (dCILInstr::m_void));
			ret->Trace();
		}
	}

	new dCILInstrFunctionEnd(function);
//	cil.Trace();
}
void dDAGExpressionNodeVariable::CompileCIL(dCIL& cil)
{
	size_t pos =  m_name.find (D_SCOPE_PREFIX, 0, strlen (D_SCOPE_PREFIX));
	if (pos != 0) {
		bool state = RenameLocalVariable(m_name);
		if (!state) {
			DTRACE (("undefined local variable\n"));
			_ASSERTE (0);
		}
	}


	if (m_dimExpressions.GetCount()) {
		dDAGDimensionNode* const dim = m_dimExpressions.GetFirst()->GetInfo();
		dim->CompileCIL(cil);
		dCIL::dListNode* const dimInstruction = cil.NewStatement();
		dTreeAdressStmt& addressIndex = dimInstruction->GetInfo();
		addressIndex.m_instruction = dTreeAdressStmt::m_assigment;
		addressIndex.m_arg0.m_label = cil.NewTemp();
		addressIndex.m_arg1.m_label = dim->m_result; 

		string result = addressIndex.m_arg0.m_label;
		dTRACE_INTRUCTION (&addressIndex);

		for (dList<dDAGDimensionNode*>::dListNode* node = m_dimExpressions.GetFirst()->GetNext(); node; node = node->GetNext()) {
			dDAGDimensionNode* const dim = node->GetInfo();
			dim->CompileCIL(cil);
			
			dTreeAdressStmt& stmtMul = cil.NewStatement()->GetInfo();
			stmtMul.m_instruction = dTreeAdressStmt::m_assigment;
			stmtMul.m_operator = dTreeAdressStmt::m_mul;
			stmtMul.m_arg0.m_label = cil.NewTemp();
			stmtMul.m_arg1.m_label = result;
			stmtMul.m_arg2.m_label = dim->m_arraySize;

			dTRACE_INTRUCTION (&stmtMul);

			dTreeAdressStmt& stmtAdd = cil.NewStatement()->GetInfo();
			stmtAdd.m_instruction = dTreeAdressStmt::m_assigment;
			stmtAdd.m_operator = dTreeAdressStmt::m_add;
			stmtAdd.m_arg0.m_label = cil.NewTemp();
			stmtAdd.m_arg1.m_label = stmtMul.m_arg0.m_label;
			stmtAdd.m_arg2.m_label = dim->m_result;

			result = stmtAdd.m_arg0.m_label;

			dTRACE_INTRUCTION (&stmtAdd);
		}

		dTreeAdressStmt& dimSize = cil.NewStatement()->GetInfo();
		dimSize.m_instruction = dTreeAdressStmt::m_assigment;
		dimSize.m_operator = dTreeAdressStmt::m_mul;
		dimSize.m_arg0.m_label = cil.NewTemp();
		dimSize.m_arg1.m_label = result; 
		dimSize.m_arg2.m_label = "4"; 
		dTRACE_INTRUCTION (&dimSize);

		result = dimSize.m_arg0.m_label;

		_ASSERTE (m_parent);
		if (m_parent->GetTypeId() == dDAGFunctionStatementAssigment::GetRttiType()) {
			dDAGFunctionStatementAssigment* const asmt = (dDAGFunctionStatementAssigment*) m_parent;
			if (asmt->m_leftVariable == this) {
				//m_result = m_name + '[' + result + ']';
				m_result = result;
			} else {
				// emit an indirect addressing mode
				dTreeAdressStmt& tmp = cil.NewStatement()->GetInfo();
//				m_result = m_name + '[' + addressIndex.m_arg0.m_label + ']';
//				tmp.m_instruction = dTreeAdressStmt::m_assigment;
//				tmp.m_arg0.m_label = cil.NewTemp();
//				tmp.m_arg1.m_label = m_name + '[' + result + ']';
				tmp.m_instruction = dTreeAdressStmt::m_load;
				tmp.m_arg0.m_label = cil.NewTemp();
				tmp.m_arg1.m_label = m_name;
				tmp.m_arg2.m_label = result;
				dTRACE_INTRUCTION (&tmp);
				m_result = tmp.m_arg0.m_label; 
			}
			
		} else {
			// emit an indirect addressing mode
			dTreeAdressStmt& tmp = cil.NewStatement()->GetInfo();
//			m_result = m_name + '[' + addressIndex.m_arg0.m_label + ']';
//			tmp.m_instruction = dTreeAdressStmt::m_assigment;
//			tmp.m_arg0.m_label = cil.NewTemp();;
//			tmp.m_arg1.m_label = m_name + '[' + result + ']';
			tmp.m_instruction = dTreeAdressStmt::m_load;
			tmp.m_arg0.m_label = cil.NewTemp();
			tmp.m_arg1.m_label = m_name;
			tmp.m_arg2.m_label = result;
			dTRACE_INTRUCTION (&tmp);
			m_result = tmp.m_arg0.m_label; 
		}
	} else {
		m_result = m_name;
	}

}
void dDAGExpressionNodeAssigment::CompileCIL(dCIL& cil)  
{
	m_expression->CompileCIL(cil); 
	if (m_leftVariable->m_dimExpressions.GetCount()) {
		
		dDAGDimensionNode* const dim = m_leftVariable->m_dimExpressions.GetFirst()->GetInfo();
		dim->CompileCIL(cil);

		dString result = dim->m_result.m_label;
		for (dList<dDAGDimensionNode*>::dListNode* node = m_leftVariable->m_dimExpressions.GetFirst()->GetNext(); node; node = node->GetNext()) {
			dAssert (0);
			dDAGDimensionNode* const dim = node->GetInfo();
			dim->CompileCIL(cil);
#if 0			
			dCILInstr& stmtMul = cil.NewStatement()->GetInfo();
			stmtMul.m_instruction = dCILInstr::m_assigment;
			stmtMul.m_operator = dCILInstr::m_mul;
			stmtMul.m_arg0.m_label = cil.NewTemp();
			stmtMul.m_arg1.m_label = result;
			stmtMul.m_arg2.m_label = dim->m_arraySize;

			DTRACE_INTRUCTION (&stmtMul);

			dCILInstr& stmtAdd = cil.NewStatement()->GetInfo();
			stmtAdd.m_instruction = dCILInstr::m_assigment;
			stmtAdd.m_operator = dCILInstr::m_add;
			stmtAdd.m_arg0.m_label = cil.NewTemp();
			stmtAdd.m_arg1.m_label = stmtMul.m_arg0.m_label;
			stmtAdd.m_arg2 = dim->m_result;

			result = stmtAdd.m_arg0.m_label;

			DTRACE_INTRUCTION (&stmtAdd);
#endif
		}

		dAssert (m_leftVariable->m_parent);
		dTree<dCILInstr::dArg, dString>::dTreeNode* const variable = dDAG::FindLocalVariable(m_leftVariable->m_name);
		dAssert (variable);

		dCILInstr::dArg arg0 (LoadLocalVariable(cil, m_expression->m_result));
		dCILInstr::dArg arg1 (LoadLocalVariable(cil, variable->GetInfo()));

		int size = arg0.GetSizeInByte();
		dCILInstrIntergerLogical* const mulOffset = new dCILInstrIntergerLogical(cil, dCILThreeArgInstr::m_mul,cil.NewTemp(), dCILInstr::dArgType(dCILInstr::m_int), result, dCILInstr::dArgType(dCILInstr::m_int), dString(size), dCILInstr::m_constInt);
		mulOffset->Trace();

		dCILInstrIntergerLogical* const address = new dCILInstrIntergerLogical(cil, dCILThreeArgInstr::m_add, cil.NewTemp(), arg1.GetType(), arg1.m_label, arg1.GetType(), mulOffset->GetArg0().m_label, mulOffset->GetArg0().GetType());
		address->Trace();

		dCILInstrStore* const store = new dCILInstrStore(cil, address->GetArg0().m_label, address->GetArg0().GetType(), arg0.m_label, arg0.GetType());
		store->Trace();
		m_result = arg0;
		
	} else {
		m_leftVariable->CompileCIL(cil); 
		dCILInstr::dArg arg1 (LoadLocalVariable(cil, m_expression->m_result));
		dCILInstrMove* const move = new dCILInstrMove (cil, m_leftVariable->m_result.m_label, m_leftVariable->m_result.GetType(), arg1.m_label, arg1.GetType());
		move->Trace();
	}
}
bool dFlowControlBlock::ApplyCopyPropagation(dCIL& program)
{
	bool ret = false;

	const dCIL::dListNode* const lastNode = m_end->GetNext();
	_ASSERTE (lastNode);
	dCIL::dListNode* next = NULL;
	for (dCIL::dListNode* node = m_leader; node != lastNode; node = next) {
		dTreeAdressStmt& stmt = node->GetInfo();
		next = node->GetNext();
		if (stmt.m_instruction == dTreeAdressStmt::m_assigment) {
			bool alive = true;
			if (stmt.m_operator == dTreeAdressStmt::m_nothing) {
				for (dCIL::dListNode* node1 = node->GetNext(); node1 != lastNode; node1 = node1->GetNext()) {
					dTreeAdressStmt& stmt1 = node1->GetInfo();
					switch (stmt1.m_instruction) 
					{
						case dTreeAdressStmt::m_assigment:
						{
							if (stmt1.m_arg1.m_label == stmt.m_arg0.m_label) {
								alive = false;
								ret = true;
								stmt1.m_arg1.m_label = stmt.m_arg1.m_label;
							}
							if (stmt1.m_arg2.m_label == stmt.m_arg0.m_label) {
								alive = false;
								ret = true;
								stmt1.m_arg2.m_label = stmt.m_arg1.m_label;
							}
							
							break;
						}
						case dTreeAdressStmt::m_if:
							_ASSERTE (0);
					}
				}
			} else {
				for (dCIL::dListNode* node1 = node->GetNext(); node1 != lastNode; node1 = node1->GetNext()) {
					dTreeAdressStmt& stmt1 = node1->GetInfo();
					switch (stmt1.m_instruction) 
					{
						case dTreeAdressStmt::m_assigment:
						{
							if (stmt1.m_operator == dTreeAdressStmt::m_nothing) {
								if (stmt1.m_arg1.m_label == stmt.m_arg0.m_label) {
									alive = false;
									ret = true;
									stmt1.m_operator = stmt.m_operator;
									stmt1.m_arg1.m_label = stmt.m_arg1.m_label;
									stmt1.m_arg2.m_label = stmt.m_arg2.m_label;
								}
							}
							break;
						}


						case dTreeAdressStmt::m_if:
						{
							if (program.m_conditinals[stmt.m_operator]) {
								switch (stmt1.m_operator) 
								{
									case dTreeAdressStmt::m_equal:
									{
										if (stmt1.m_arg1.m_label == "0") {
											alive = false;
											ret = true;
											stmt1.m_operator = program.m_operatorComplement[stmt.m_operator];
											stmt1.m_arg0.m_label = stmt.m_arg1.m_label;
											stmt1.m_arg1.m_label = stmt.m_arg2.m_label;
										}
										break;
									}

									case dTreeAdressStmt::m_different:
									{
										if (stmt1.m_arg1.m_label == "0") {
											alive = false;
											ret = true;
											stmt1.m_operator = stmt.m_operator;
											stmt1.m_arg0.m_label = stmt.m_arg1.m_label;
											stmt1.m_arg1.m_label = stmt.m_arg2.m_label;
										}
										break;
									}

									default:
										break;
								}
							}
						}
					}
				}
			}
			if (!alive && (stmt.m_arg0.m_label[0] == 't')) {
				if (m_leader == node) {
					m_leader = node->GetNext();
				}
				program.Remove(node);
			}
		} else if (stmt.m_instruction == dTreeAdressStmt::m_load) {
			bool alive = true;
			for (dCIL::dListNode* node1 = node->GetNext(); alive && (node1 != lastNode); node1 = node1->GetNext()) {
				dTreeAdressStmt& stmt1 = node1->GetInfo();
				alive |= stmt1.m_instruction != dTreeAdressStmt::m_store;  
				if (alive && (stmt1.m_instruction == dTreeAdressStmt::m_assigment) && 
							 (stmt1.m_operator == dTreeAdressStmt::m_nothing) && (stmt1.m_arg1.m_label == stmt.m_arg0.m_label)) {
					alive = false;
					ret = true;
					stmt1.m_instruction = dTreeAdressStmt::m_load;
					stmt1.m_arg1.m_label = stmt.m_arg1.m_label;
					stmt1.m_arg2.m_label = stmt.m_arg2.m_label;
					if (stmt.m_arg0.m_label[0] == 't') {
						if (m_leader == node) {
							m_leader = node->GetNext();
						}
						program.Remove(node);
					}
				}
			}
		}
	}
	return ret;
}