Click here to Skip to main content
12,397,059 members (63,608 online)
Click here to Skip to main content

Tagged as

Stats

236.2K views
2.5K downloads
154 bookmarked
Posted

Bird Programming Language: Part 1

, 1 Jan 2013 GPL3
A new general purpose language that aims to be fast, high level and simple to use.
Bird
Archives
crt2.o
crtbegin.o
crtend.o
libadvapi32.a
libcomctl32.a
libcomdlg32.a
libgcc.a
libgdi32.a
libglu32.a
libkernel32.a
libmingw32.a
libmingwex.a
libmoldname.a
libmsvcrt.a
libopengl32.a
libshell32.a
libstdc++.a
libuser32.a
libwinmm.a
libwsock32.a
Libraries
BirdCore
Array.bird
BigInteger.bird
BinaryRW.bird
BirdCore.a
BirdCore.blib
CategoryData.dat
Console.bird
Convert.bird
Debug.bird
Entry.bird
Environment.bird
Exception.bird
Float.bird
LEB128.bird
Math.bird
Memory.bird
Object.bird
Random.bird
Reflection.bird
StandardC.bird
Stream.bird
String.bird
ToLowerData.dat
ToUpperData.dat
Types.bird
ValueType.bird
Win32.bird
x86Helper.bird
BlitzMax
.bmx
Launcher.bmx.gui.release.win32.x86.o
appstub.release.win32.x86.a
bank.release.win32.x86.a
bankstream.release.win32.x86.a
blitz.release.win32.x86.a
BlitzMax.a
BlitzMax.bird
BlitzMax.blib
d3d7max2d.release.win32.x86.a
d3d9max2d.release.win32.x86.a
directx.release.win32.x86.a
dxgraphics.release.win32.x86.a
event.release.win32.x86.a
filesystem.release.win32.x86.a
font.release.win32.x86.a
glgraphics.release.win32.x86.a
glmax2d.release.win32.x86.a
graphics.release.win32.x86.a
hook.release.win32.x86.a
keycodes.release.win32.x86.a
Launcher.bmx
libpng.release.win32.x86.a
linkedlist.release.win32.x86.a
math.release.win32.x86.a
max2d.release.win32.x86.a
opengl.release.win32.x86.a
pixmap.release.win32.x86.a
pngloader.release.win32.x86.a
polledinput.release.win32.x86.a
standardio.release.win32.x86.a
stdc.release.win32.x86.a
stream.release.win32.x86.a
system.release.win32.x86.a
textstream.release.win32.x86.a
win32.release.win32.x86.a
zlib.release.win32.x86.a
PrgLinec.bmx
Samples
Circles
Circles.bird
CppMain.bird
Fire
Fire.bird
Higher Order Functions
C#
Higher Order Functions.v11.suo
Properties
Test.bird
msvcrt.lib
Reflection
Reflection.bird
Squares
Squares.bird
Template
Template.bird
Source
Base
Bird.v11.suo
Expressions
Identifiers
Languages
NativeCode
Properties
Recognizers
Expressions
Scopes
x86
Thumbs.db
crt2.o
crtbegin.o
crtend.o
libadvapi32.a
libcomctl32.a
libcomdlg32.a
libgcc.a
libgdi32.a
libglu32.a
libkernel32.a
libmingw32.a
libmingwex.a
libmoldname.a
libmsvcrt.a
libopengl32.a
libshell32.a
libstdc++.a
libuser32.a
libwinmm.a
libwsock32.a
Binaries
ar.exe
Bird.exe
fasm.exe
ld.exe
libiconv-2.dll
libintl-8.dll
Array.bird
BigInteger.bird
BinaryRW.bird
BirdCore.a
BirdCore.blib
CategoryData.dat
Console.bird
Convert.bird
Debug.bird
Entry.bird
Environment.bird
Exception.bird
Float.bird
LEB128.bird
Math.bird
Memory.bird
Object.bird
Random.bird
Reflection.bird
StandardC.bird
Stream.bird
String.bird
ToLowerData.dat
ToUpperData.dat
Types.bird
ValueType.bird
Win32.bird
x86Helper.bird
Launcher.bmx.gui.release.win32.x86.o
appstub.release.win32.x86.a
bank.release.win32.x86.a
bankstream.release.win32.x86.a
blitz.release.win32.x86.a
BlitzMax.a
BlitzMax.bird
BlitzMax.blib
d3d7max2d.release.win32.x86.a
d3d9max2d.release.win32.x86.a
directx.release.win32.x86.a
dxgraphics.release.win32.x86.a
event.release.win32.x86.a
filesystem.release.win32.x86.a
font.release.win32.x86.a
glgraphics.release.win32.x86.a
glmax2d.release.win32.x86.a
graphics.release.win32.x86.a
hook.release.win32.x86.a
keycodes.release.win32.x86.a
Launcher.bmx
libpng.release.win32.x86.a
linkedlist.release.win32.x86.a
math.release.win32.x86.a
max2d.release.win32.x86.a
opengl.release.win32.x86.a
pixmap.release.win32.x86.a
pngloader.release.win32.x86.a
polledinput.release.win32.x86.a
standardio.release.win32.x86.a
stdc.release.win32.x86.a
stream.release.win32.x86.a
system.release.win32.x86.a
textstream.release.win32.x86.a
win32.release.win32.x86.a
zlib.release.win32.x86.a
PrgLinec.bmx
PrgLinec.exe
Circles.bird
CppMain.bird
Fire.bird
Higher Order Functions.v11.suo
Test.bird
msvcrt.lib
Reflection.bird
Squares.bird
Template.bird
Bird.v11.suo
Thumbs.db
Examples
As.exe
AsLibs.a
PerfTest
Launcher.bmx
Squares
.bmx
Launcher.bmx
Template
Launcher.bmx
Anonymus 7_1
Anonymus.csproj.user
Anonymus.idc
Anonymus.pidb
Anonymus.suo
Anonymus.userprefs
Base
Expressions
Lib
Long
LongDivTest.bmx
ULongConv.bmx
Math
MISZ
AsLibs.a
PerfTest
Launcher.bmx
Squares
Launcher.bmx
Template
Launcher.bmx
PrgLinec.bmx
PrgLinec.exe
Properties
Scopes
Txt
Asm.docx
Code.docx
Lib.aslib
~$Code.docx
x86
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)

Share

About the Author

Dávid Kocsis
Software Developer
Hungary Hungary
No Biography provided

You may also be interested in...

| Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.160721.1 | Last Updated 1 Jan 2013
Article Copyright 2011 by Dávid Kocsis
Everything else Copyright © CodeProject, 1999-2016
Layout: fixed | fluid