Click here to Skip to main content
15,885,244 members
Articles / High Performance Computing / Vectorization

Bird Programming Language: Part 1

Rate me:
Please Sign up or sign in to vote.
4.92/5 (129 votes)
1 Jan 2013GPL312 min read 376.3K   2.7K   153  
A new general purpose language that aims to be fast, high level and simple to use.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Anonymus.x86
{
	public static class x86Extensions
	{
		public static bool DontUseThisVar(this ExpressionNode Self)
		{
			var Data = Self.ArchData as x86NodeData;
			if (Data == null) return false;

			if (Data.Output is x86PostCalcedPosition)
			{
				var AssignPos = Data.Output as x86AssignVarPos;
				if (!(AssignPos.Position is x86MemPosition))
					return false;

				var AData = AssignPos.AssignNode.ArchData as x86NodeData;
				AData.DontUseCount++;

				if (AData.DontUseCount >= 2)
				{
					AData.CanUseAssignVar_Calced = true;
					AData.CanUseAssignVar = false;
					return true;
				}
			}

			return false;
		}

		public static Identifier GetId(this ExpressionNode Self)
		{
			if (Self is IdExpressionNode)
			{
				var RId = Self as IdExpressionNode;
				return RId.Id;
			}

			var Data = Self.ArchData as x86NodeData;
			if (Data != null)
			{
				var Pos = Data.Output as x86AssignVarPos;
				if (Pos != null) return Pos.AssignVar;
			}

			return null;
		}

		public static bool SamePosition(this ExpressionNode Self, ExpressionNode Node, bool Size = true)
		{
			var SelfId = Self.GetId();
			if (SelfId == Node.GetId() && SelfId != null)
				return true;

			var S = Self.GetPosition();
			var N = Node.GetPosition();

			if (S == null || N == null) return false;
			else return S.IsEqual(N, Size);
		}

		public static x86DataPosition GetPosition(this ExpressionNode Node)
		{
			var Data = Node.ArchData as x86NodeData;
			if (Data == null) return null;

			if (Data.Output is x86PostCalcedPosition)
			{
				var Pos = Data.Output as x86PostCalcedPosition;
				return Pos.Position.Copy(Node.Type.Size);
			}
			else
			{
				return Data.Output;
			}
		}

		public static void IncRegs(this ExpressionNode Node, int Count = 1)
		{
			var Data = Node.ArchData as x86NodeData;
			if (Data.NewScope) return;
			if (Data.Index != -1) Data.Index += Count;

			foreach (var e in Node.EnumChildren)
				IncRegs(e, Count);
		}

		public static bool IsMem(this ExpressionNode Node, x86Architecture Arch)
		{
			var Data = Node.ArchData as x86NodeData;

			var RIdNode = Node as IdExpressionNode;
			if (RIdNode != null)
			{
				var Id = RIdNode.Id;
				return Id.ArchData is x86MemPosition;
			}

			if (Node is ConstExpressionNode)
				return false;

            if (Node is LinkingNode)
            {
                var LNode = Node as LinkingNode;
                var Linked = LNode.LinkedNode;
                return Linked.ArchData is x86MemPosition;
            }

			var OpNode = Node as OpExpressionNode;
			if (OpNode != null)
			{
				var Op = OpNode.Operator;
				if (Op == Operator.Member) return true;
				if (Op == Operator.Index) return true;

				if (Op == Operator.Assignment)
					return OpNode.Children[0].IsMem(Arch);

				if (Op == Operator.Call)
				{
					if (Node.Type is ValueType) return true;
				}
			}

			//-----------------------------------------------------
			var Pos = Node.GetPosition();
			if (Pos is x86MemPosition) return true;
			if (Pos is x86MultiPosition) return (Pos as x86MultiPosition).HasMemPart();
			return false;
		}

        public static bool NeedTmpReg(x86DataPosition Dst, x86DataPosition Src)
        {
            if (Dst is x86MemPosition && Src is x86MemPosition)
                return true;

            var D = Dst as x86MultiPosition;
            var S = Src as x86MultiPosition;
            if (D == null || S == null) return false;

            var MLen = D.Positions.Length;
            if (S.Positions.Length < MLen)
                MLen = S.Positions.Length;

            for (var i = 0; i < MLen; i++)
                if (D.Positions[i] is x86MemPosition && S.Positions[i] is x86MemPosition)
                    return true;

            return false;
        }

        public static bool NeedTmpReg(this ExpressionNode Self, x86Architecture Arch, x86DataPosition Src)
        {
            var SelfData = Self.ArchData as x86NodeData;
            if (SelfData.Output is x86MultiPosition && Src is x86MultiPosition)
                return NeedTmpReg(SelfData.Output, Src);

            var SrcMem = Src is x86MemPosition;
            if (Src is x86MultiPosition)
            {
                var MSrc = Src as x86MultiPosition;
                SrcMem = MSrc.HasMemPart();
            }

            return SrcMem && Self.IsMem(Arch);
        }

		public static bool NeedTmpReg(this ExpressionNode Self, x86Architecture Arch, ExpressionNode Node)
		{
			var SelfData = Self.ArchData as x86NodeData;
			var NodeData = Node.ArchData as x86NodeData;

            if (SelfData.Output is x86MultiPosition && NodeData.Output is x86MultiPosition)
                return NeedTmpReg(SelfData.Output, NodeData.Output);

			return Self.IsMem(Arch) && Node.IsMem(Arch);
		}

		public static bool _CanUseAssignVar(this ExpressionNode Node, Identifier AssignVar)
		{
			var Used = false;
			foreach (var e in Node.EnumChildren)
			{
				if (!Used && e.DataRegUsed()) Used = true;
				else if (Used && e.IdUsed(AssignVar)) return false;

				if (!e._CanUseAssignVar(AssignVar)) return false;
			}

			return true;
		}

		public static bool CanUseDataPosNoSave(this ExpressionNode Node, Type T, int Index)
		{
			var Data = Node.ArchData as x86NodeData;
			if (T.Size < Node.Type.Size && Data.Index == Index) return false;

			foreach (var e in Node.EnumChildren)
				if (!e.CanUseDataPosNoSave(T, Index)) return false;

			return true;
		}

        public static bool CanUseDataPos(this ExpressionNode Node, Type T, int Index)
		{
			var Data = Node.ArchData as x86NodeData;
			if (Data.CanUseAssignVar_Calced)
				return Data.CanUseAssignVar;

            var RetValue = Node.CanUseDataPosNoSave(T, Index);
			Data.CanUseAssignVar_Calced = true;
			Data.CanUseAssignVar = RetValue;
			return RetValue;
		}

        public static bool CanUseAssignVar(this ExpressionNode Node, Variable Var, x86RegList CantBe, int Index)
		{
			var Data = Node.ArchData as x86NodeData;
			if (Data.CanUseAssignVar_Calced)
				return Data.CanUseAssignVar;

			var RetValue = true;
            if (!Node.CanUseDataPosNoSave(Var.Type, Index)) RetValue = false;
			else if (!Node._CanUseAssignVar(Var)) RetValue = false;

			if (RetValue && CantBe != null)
			{
				var RegPos = Var.ArchData as x86RegPosition;
				if (RegPos != null && CantBe[RegPos.Index] > 0) RetValue = false;
			}

			Data.CanUseAssignVar_Calced = true;
			Data.CanUseAssignVar = RetValue;
			return RetValue;
		}

		public static bool DataRegUsed(this ExpressionNode Node)
		{
			var Data = Node.ArchData as x86NodeData;
			if (Data.Index != -1) return true;

			foreach (var e in Node.EnumChildren)
				if (e.DataRegUsed()) return true;

			return false;
		}

        public static void GetUsed(this ExpressionNode Node, x86DataAllocator Allocator, bool Root = true)
        {
            var Data = Node.ArchData as x86NodeData;
            var Scope = Data.Scope;

            if (Data.UsedRegs != null) Allocator.UsedRegs.SetUsed(Data.UsedRegs);
            if (Data.NewScope) Allocator.SetUsed(Scope.Allocator);
            else if (Root) throw new Exception("ERROR");

            foreach (var e in Node.EnumChildren)
                e.GetUsed(Allocator, false);
        }
	}

	[Flags]
	public enum x86DataCalcPos
	{
		Memory = 1,
		GeneralReg = 2,
		SSEReg = 4,
		GRegMem = GeneralReg | Memory,
		SSEMem = SSEReg | Memory,
	}

	public class x86NodeData
	{
		public bool NewScope;
		public int MulBy = 1;
		public int FPUItemsOnStack = 0;
		public int UsedFPUStack = 0;

		public int Index = int.MaxValue;
		public x86DataCalcPos DataCalcPos = x86DataCalcPos.GRegMem;
		public x86DataPosition Input;
		public x86DataPosition Output;
		public x86RegList UsedRegs;
        public x86RegList CantBe;
		public x86ExprScope Scope;
		public x86RegList PreAllocate;

		// Assign OpNode
		public bool CanUseAssignVar_Calced = false;
		public bool CanUseAssignVar;
		public int DontUseCount;

		// Root Data
		public List<x86ExprScope> AllScopes;
		public x86RegList AllUsedRegs;

		public x86NodeData(bool NewScope = false)
		{
			this.NewScope = NewScope;
		}

		public x86NodeData Copy()
		{
			var CRegs = CantBe != null ? CantBe.Copy() : null;
			var Ret = new x86NodeData(NewScope);
			Ret.CantBe = CRegs;
			return Ret;
		}
	}

	public class x86LinkedNodeData
	{
		public x86DataPosition Specified;
		public x86DataPosition Position;

		public x86LinkedNodeData(x86DataPosition Specified)
		{
			this.Specified = Specified;
		}
	}

	public class x86ExprDataPos
	{
		public x86DataPosition DataPos;
		public x86RegList CantBe;

		public int MinSize = 0;
		public int MinAlign = 0;
		public x86DataCalcPos DataCalcPos = x86DataCalcPos.GRegMem;

		public x86ExprDataPos(int RegCount)
		{
			CantBe = new x86RegList(RegCount);
		}
	}

	public class x86ExprScope
	{
		public x86Architecture Arch;
		public x86ExprScope Parent;
        public List<x86ExprScope> Children = new List<x86ExprScope>();

		public int NeededStack = 0;
		public x86DataAllocator PreAllocated;
		public x86DataAllocator Allocator;

		public bool NeedSSETmpReg = false;
		public bool NeedTmpReg = false;
		public bool NeedIndexReg = false;
		public int NeedTmpMem = 0;

		public x86DataPosition TmpReg;
		public x86DataPosition IndexReg;
		public x86DataPosition SSETmpReg;
		public x86DataPosition TmpMem;

		public Dictionary<int, x86ExprDataPos> DataPositions =
			new Dictionary<int, x86ExprDataPos>();

        public void SetUsed(x86DataPosition Pos, bool Rec = true)
        {
            Allocator.SetUsed(Pos);

            if (Rec)
            {
                foreach (var e in Children)
                    e.SetUsed(Pos, true);
            }
        }

		public void NewDataPosition(ExpressionNode Node)
		{
			var Data = Node.ArchData as x86NodeData;
			Data.Scope = this;
			var Index = Data.Index;

			if (Index != -1)
			{
				var Pos = this[Index];
				if (Pos != null)
				{
					if (Data.CantBe != null)
					{
						if (Pos.CantBe == null) Pos.CantBe = Data.CantBe.Copy();
						else Pos.CantBe.SetUsed(Data.CantBe);
					}
				}
				else
				{
					Pos = new x86ExprDataPos(Arch.RegCount);
					if (Data.CantBe != null)
						Pos.CantBe = Data.CantBe.Copy();

					DataPositions.Add(Index, Pos);
				}

				var Size = Node.Type.Size;
				var Align = Arch.GetAlign(Node.Type);

				if (Pos.MinSize < Size) Pos.MinSize = Size;
				if (Pos.MinAlign < Align) Pos.MinAlign = Align;
				Pos.DataCalcPos &= Data.DataCalcPos;
			}
		}

		public void Reset(bool Rec = true)
		{
			foreach (var e in DataPositions.Keys)
				DataPositions[e].DataPos = null;

			if (PreAllocated != null)
				Allocator.Set(PreAllocated);
			else Allocator.Reset();

			TmpReg = null;
			IndexReg = null;

			if (Rec)
			{
				foreach (var e in Children)
					e.Reset(true);
			}
		}

		public x86ExprScope(x86ExprScope Parent, IdContainer Container)
		{
			this.Arch = Container.State.Arch as x86Architecture;
            this.Allocator = new x86DataAllocator(Container);
			this.Parent = Parent;
		}

		public x86ExprDataPos this[int a]
		{
			get
			{
				x86ExprDataPos Ret;
				if (!DataPositions.TryGetValue(a, out Ret))
					return null;

				return Ret;
			}
		}

		public x86DataPosition AllocData(x86ExprDataPos P, bool Strict = true)
		{
			if (P.DataPos == null)
			{
				var CP = P.DataCalcPos;
				if (!Strict) CP |= x86DataCalcPos.Memory;

				P.DataPos = Allocator.Alloc(P.MinSize, P.MinAlign, CP, P.CantBe);
			}

			return P.DataPos;
		}

		public x86DataPosition AllocData(int Index, bool Strict = true)
		{
			var P = this[Index];
			if (P == null) throw new Exception("ERROR");
			return AllocData(P, Strict);
		}

		public x86DataPosition AllocData(int Index, int Size, bool Strict = true)
		{
			return AllocData(Index, Strict).Copy(Size);
		}

		public void AllocTmpRegs()
		{
			var R = Arch.RegSize;
			if (NeedTmpMem > 0) TmpMem = Allocator.Alloc(NeedTmpMem, NeedTmpMem, x86DataCalcPos.Memory);
			if (NeedTmpReg) TmpReg = Allocator.Alloc(R, R, x86DataCalcPos.GeneralReg);
			if (NeedIndexReg) IndexReg = Allocator.Alloc(R, R, x86DataCalcPos.GeneralReg);
			if (NeedSSETmpReg) SSETmpReg = Allocator.Alloc(16, 16, x86DataCalcPos.SSEReg);
		}
	}

	public class x86DataPosCalcer
	{
		public CompilerState State;
		public ExpressionNode ExprNode;
		public x86Architecture Arch;
		public IdContainer Container;
		public x86FuncScopeNode FuncScope;

		public x86DataPosCalcer(IdContainer Container, CompilerState State, ExpressionNode ExprNode)
		{
			this.State = State;
			this.ExprNode = ExprNode;
			this.Arch = State.Arch as x86Architecture;
			this.Container = Container;
			this.FuncScope = Container.FuncScope as x86FuncScopeNode;
		}

		public void Calc()
		{
			var Data = ExprNode.ArchData as x86NodeData;
			Data.Scope.Reset();

            Init(ExprNode);
            PreCalc(ExprNode);
            CalcLinkedNodes(ExprNode);
			CalcRec(ExprNode);

			var IdArchData = Container.ArchData as x86IdContainerData;
			var IdAllocator = IdArchData.Allocator;
			IdAllocator.UsedRegs.SetUsed(Data.AllUsedRegs);

			foreach (var e in Data.AllScopes)
				IdAllocator.SetUsed(e.Allocator);
		}

        private void Init(ExpressionNode Node)
        {
			var Data = Node.ArchData as x86NodeData;
			var Scope = Data.Scope;

			//------------------------------------------------------------
			Variable Var = null;
			if (Node.GetAssignVar(ref Var) && Var != null)
			{
                var OpNode = Node as OpExpressionNode;
                var Ch1Data = OpNode.Children[1].ArchData as x86NodeData;
                var Index = Ch1Data.Index != -1 ? Ch1Data.Index : 0;

                var D = Scope[Index];
                if (D != null && Node.CanUseAssignVar(Var, D.CantBe, Index))
				{
					D.DataPos = new x86AssignVarPos(Arch, Var, Node);
					Data.DontUseCount = 0;

					if (Var.ArchData != null)
					{
						var AVarPos = Var.ArchData as x86DataPosition;
						Scope.Allocator.UsedRegs.SetUsed(AVarPos.GetRegs());
					}
				}
			}
            else if (Data.Input != null)
            {
                var D = Scope[0];
                if (D != null && D.DataCalcPos.HasFlag(x86DataCalcPos.GeneralReg))
                {
                    var I = Data.Input;
                    D.DataPos = I;
                    Scope.Allocator.UsedRegs.SetUsed(I.GetRegs());
                }
            }

            //------------------------------------------------------------
            if (Node.LinkedNodes != null)
			{
				foreach (var LNode in Node.LinkedNodes)
				{
					var LData = LNode.ArchData as x86LinkedNodeData;
					LData.Position = null;

					var Linked = LNode.Node;
					var LinkedNData = Linked.ArchData as x86NodeData;
					var LScope = LinkedNData.Scope;

                    var Index = LinkedNData.Index != -1 ? LinkedNData.Index : 0;
                    var ExprPos = LScope[Index];

                    if (ExprPos != null && Linked.CanUseDataPos(Linked.Type, Index))
					{
						ExprPos.DataPos = new x86LinkedNodePosition(Arch, LNode);
						LinkedNData.DontUseCount = 0;
					}
				}
            }

            if (Data.NewScope) Scope.AllocTmpRegs();
            foreach (var Ch in Node.EnumChildren)
                Init(Ch);
        }

        private void PreCalc(ExpressionNode Node)
        {
            var Data = Node.ArchData as x86NodeData;
            var Scope = Data.Scope;

            if (Data.NewScope)
            {
                foreach (var Pos in Scope.DataPositions.Values)
                    if (!Pos.DataCalcPos.HasFlag(x86DataCalcPos.Memory))
                        Scope.AllocData(Pos);
            }

            foreach (var Ch in Node.EnumChildren)
                PreCalc(Ch);
        }

        private void CalcLinkedNodes(ExpressionNode Node, x86DataAllocator Allocator = null)
        {
            var Data = Node.ArchData as x86NodeData;
            var Scope = Data.Scope;
            var AllocatorCopy = (x86DataAllocator)null;

            if (Data.NewScope)
            {
                Allocator = new x86DataAllocator(Container);
                Allocator.SetUsed(Scope.Allocator);
            }

            if (Node.LinkedNodes != null)
            {
                AllocatorCopy = Allocator.Copy();

                for (var i = Node.LinkedNodes.Count - 1; i >= 0; i--)
                {
                    var LNode = Node.LinkedNodes[i];
                    var LData = LNode.ArchData as x86LinkedNodeData;

                    var Linked = LNode.Node;
                    var LinkedData = Linked.ArchData as x86NodeData;

                    if (LData.Specified != null)
                    {
                        LData.Position = LData.Specified;
                        Allocator.SetUsed(LData.Specified);
                    }
                    else
                    {
                        var Out = LinkedData.Output;
                        if (Out != null && !(Out is x86PostCalcedPosition) && Allocator.IsFree(Out))
                        {
                            Allocator.SetUsed(LinkedData.Output);
                            LData.Position = LinkedData.Output;
                        }
                        else
                        {
                            LData.Position = Allocator.Alloc(Linked.Type);
                        }

                        Scope.SetUsed(LData.Position);
                    }

                    LNode.Node.GetUsed(Allocator);
                }
            }

            foreach (var Ch in Node.EnumChildren)
                CalcLinkedNodes(Ch, Allocator);

            if (AllocatorCopy != null)
                Allocator.Set(AllocatorCopy);
        }

        private void CalcRec(ExpressionNode Node)
        {
            var Data = Node.ArchData as x86NodeData;
            var Scope = Data.Scope;

            if (Data.Index != -1)
                Data.Output = Scope.AllocData(Data.Index, Node.Type.Size, false);

            var OpNode = Node as OpExpressionNode;
            var Op = OpNode != null ? OpNode.Operator : Operator.Nothing;
            if (Op == Operator.CreateTuple)
            {
                var Ch = OpNode.Children;
                var Type = OpNode.Type as TupleType;

                for (var i = 0; i < Ch.Count; i++)
                {
                    var ChData = Ch[i].ArchData as x86NodeData;
                    var ChScope = ChData.Scope;
                    
                    var MemVar = Type.Members[i] as MemberVariable;
                    var Index = Data.Index + i + 1;
                    var ExprPos = ChScope[Index];

                    if (ExprPos != null && Ch[i].CanUseDataPos(MemVar.Type, Index))
                    {
                        var Splitable = Data.Output as x86SplitablePosition;
                        var Part = Splitable.GetPart(MemVar.Offset, MemVar.Type.Size);
                        ExprPos.DataPos = Part;
                    }
                }
            }

            foreach (var Ch in Node.EnumChildren)
                CalcRec(Ch);
        }

        bool ChkMem2Mem_Recheck;
        int ChkMem2Mem_Recheck_Index;

		public bool ChkMem2Mem()
		{
			var Ret = true;
			ChkMem2Mem_Recheck_Index = 0;

			do
			{
				ChkMem2Mem_Recheck = false;
				Ret = ChkMem2Mem_Rec(ExprNode);
				ChkMem2Mem_Recheck_Index++;
			}
			while (ChkMem2Mem_Recheck && Ret);

			return Ret;
		}

		bool ChkMem2Mem_Rec(ExpressionNode Node)
		{
			if (!ChkMem2Mem_Func(Node)) return false;
			foreach (var Ch in Node.EnumChildren)
				if (!ChkMem2Mem_Rec(Ch)) return false;

			return true;
		}

		[Flags]
		enum TmpRegAllocType
		{
			General = 1,
			Index = 2,
			SSE = 4,
			Mem = 8,
		}

		bool ChkMem2Mem_Func(ExpressionNode Node)
		{
			var NeedMove = 0;
			var RegType = TmpRegAllocType.General;
			var DontUseAssignVar = false;
			var Data = Node.ArchData as x86NodeData;

            if (Node.LinkedNodes != null)
            {
                foreach (var e in Node.LinkedNodes)
                    if (e.Node.NeedTmpReg(Arch, e.ArchData as x86DataPosition))
                    {
                        NeedMove = e.Node.Type.Size;
                        if (NeedMove % 4 == 0 && NeedMove > Arch.RegSize)
                            RegType = TmpRegAllocType.SSE;
                    }
            }

			if (Node is CastExpressionNode)
			{
				var CastNode = Node as CastExpressionNode;
				var Type = CastNode.Type;
				var SrcNode = CastNode.Child;

				if (Type is NonFltNumType)
				{
					if (SrcNode.Type is FloatType)
					{
						if (!CastNode.IsMem(Arch))
						{
							NeedMove = Type.Size;
							RegType = TmpRegAllocType.Mem;
						}
					}
				}
				else if (Type is FloatType)
				{
					if (!SrcNode.IsMem(Arch))
					{
						NeedMove = SrcNode.Type.Size;
						RegType = TmpRegAllocType.Mem;
					}
				}

				if (Data.Index != -1 && !SrcNode.SamePosition(CastNode) && CastNode.NeedTmpReg(Arch, SrcNode))
				{
					NeedMove = SrcNode.Type.Size;
					if (Type.Size == NeedMove && NeedMove % 4 == 0 && NeedMove > Arch.RegSize)
						RegType = TmpRegAllocType.SSE;
				}
			}

			else if (Node is OpExpressionNode)
			{
				var OpNode = Node as OpExpressionNode;
				var Op = OpNode.Operator;
				var Ch = OpNode.Children;
				var Type = Ch.Count > 0 ? Ch[0].Type : null;

				if (Op == Operator.CreateTuple)
				{
					if (Node.IsMem(Arch))
						foreach (var e in Ch)
							if (e.IsMem(Arch))
							{
								var S = e.Type.Size;
								if (NeedMove < S) NeedMove = S;

								if (S % 4 == 0 && S > Arch.RegSize)
									RegType |= TmpRegAllocType.SSE;
								else RegType |= TmpRegAllocType.General;
							}
				}
				else if (Op == Operator.New)
				{
					NeedMove = Node.Type.Size;
					if (NeedMove % 4 == 0 && NeedMove > Arch.RegSize)
						RegType = TmpRegAllocType.SSE;
				}
				else if (Op == Operator.Multiply && Type.Size != 1)
				{
					if (Ch[0].IsMem(Arch))
					{
						NeedMove = Type.Size;
						if (ChkMem2Mem_Recheck_Index == 0 && Ch[0].DontUseThisVar())
							DontUseAssignVar = true;
					}
				}
				else if (Op == Operator.Index)
				{
					if (Ch[0].IsMem(Arch))
					{
						NeedMove = Arch.RegSize;
						RegType = TmpRegAllocType.Index;

						if (ChkMem2Mem_Recheck_Index == 0 && Ch[0].DontUseThisVar())
							DontUseAssignVar = true;
					}
				}
				else if (Op == Operator.Member)
				{
					var RIdCh1 = Ch[1] as IdExpressionNode;
					if (RIdCh1 != null && RIdCh1.Id is MemberFunction)
						NeedMove = Arch.RegSize;
				}
				else if (Operators.IsRelEqualityOp(Op) || Operators.IsBitArithmOp(Op) || Op == Operator.Assignment)
				{
					if ((Op != Operator.Assignment || !Ch[0].SamePosition(Ch[1])) && !(Node.Type is FloatType))
						if (Ch[0].NeedTmpReg(Arch, Ch[1]))
						{
							NeedMove = Type.Size;
							if (Op == Operator.Assignment && NeedMove % 4 == 0 && NeedMove > Arch.RegSize)
								RegType = TmpRegAllocType.SSE;

							if (ChkMem2Mem_Recheck_Index == 0)
							{
								if (Ch[0].DontUseThisVar() || Ch[1].DontUseThisVar())
									DontUseAssignVar = true;
							}
						}
				}
			}

			if (NeedMove > 0)
			{
				if (ChkMem2Mem_Recheck_Index == 0)
				{
					if (DontUseAssignVar) return false;
					else ChkMem2Mem_Recheck = true;
				}
				else
				{
					var Scope = Data.Scope;
					if (RegType.HasFlag(TmpRegAllocType.Mem) && Scope.TmpMem == null)
					{
						Scope.NeedTmpMem = NeedMove;
						return false;
					}
					
					if (RegType.HasFlag(TmpRegAllocType.General) && Scope.TmpReg == null)
					{
						Scope.NeedTmpReg = true;
						return false;
					}
					
					if (RegType.HasFlag(TmpRegAllocType.Index) && Scope.IndexReg == null)
					{
						Scope.NeedIndexReg = true;
						return false;
					}
					
					if (RegType.HasFlag(TmpRegAllocType.SSE) && Scope.SSETmpReg == null)
					{
						Scope.NeedSSETmpReg = true;
						return false;
					}
				}
			}

			return true;
		}
	}

}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The GNU General Public License (GPLv3)


Written By
Software Developer
Hungary Hungary
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions