Click here to Skip to main content
Click here to Skip to main content
Add your own
alternative version

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-noexe.zip
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
Bird.zip
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.zip
Examples
As.exe
AsLibs.a
PerfTest
Launcher.bmx
Squares
.bmx
Launcher.bmx
Template
Launcher.bmx
source.zip
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;
using System.Numerics;

namespace Bird.x86
{
	[Flags]
	public enum x86ExecutorType : byte
	{
		None = 0,
		General = 1,
		FPU = 2,
		SSE = 4,
		All = General | FPU | SSE,
	}

	public enum x86TypeKind : byte
	{
		Unknown,
		Signed,
		Unsigned,
		Float,
		SignedVector,
		UnsignedVector,
		FloatVector,
	}

	[Flags]
	public enum x86DataLocationType : byte
	{
		None = 0,
		Memory = 1,
		General = 2,
		OneByte = 4,
		SSEReg = 8,

		OneByteGeneral = General | OneByte,
		GRegMem = General | Memory,
		SSEMem = SSEReg | Memory,
		All = General | SSEReg | Memory,
	}

	public enum x86Operator : byte
	{
		Unknown,
		FloatZeroTesting,
		BitTestZero,
		BitTestNonZero,
		Swap,

		IsNan,
		IsNotNan,
		IsInfinite,
		IsFinite,

		IsCarryFlagSet,
		IsCarryFlagZero,
		IsParityFlagSet,
		IsParityFlagZero,
		IsZeroFlagSet,
		IsZeroFlagZero,
		IsSignFlagSet,
		IsSignFlagZero,
		IsOverflowFlagSet,
		IsOverflowFlagZero,

		Abs,
		Sqrt,
		Sin,
		Cos,
		Tan,
		Atan,
		Atan2,

		RSqrt,
		Rcp,
		RRcp,
		AndNot,
		Min,
		Max,

		Round,
		Floor,
		Ceiling,
		Truncate,
	}

	[Flags]
	public enum x86NodeFlags : ushort
	{
		None = 0,
		IdentifierByRef = 1,
		AllocateLocation = 2,
		SaveChResults = 4,
		IndexMemberNode = 8,
		RefIndexMemberNode = 16,

		LocationProcessed = 32,
		IndicesProcessed = 64,

		// Assign OpNode
		CanUseAssignVar_Calced = 256,
		CanUseAssignVar = 512,

		// RootNode
		AllocateTempData = 1024,
		EnableUsedData = 2048,
		LinkedNodesUsed = 4096,
		NonMemoryUsed = 8192,
		NeedAllocations = 16384,
		UseExistingLocs = 32768,

		//
		FlagsForRefIdentifier = IdentifierByRef |
			IndexMemberNode | RefIndexMemberNode,

		LeftByReset = IndicesProcessed,
	}

	public enum x86SameAllocationAsType : byte
	{
		None,
		Specified,
		All,
	}

	public struct x86StoredDataType
	{
		public x86TypeKind TypeKind;
		public int Precision;

		public x86StoredDataType(x86TypeKind TypeKind, int Precision)
		{
			this.TypeKind = TypeKind;
			this.Precision = Precision;
		}

		public bool IsEquivalent(x86StoredDataType Other)
		{
			return TypeKind == Other.TypeKind && Precision == Other.Precision;
		}

		public bool CheckLocation(int Size)
		{
			if (TypeKind != x86TypeKind.Unknown)
			{
				if (x86Identifiers.IsVectorTypeKind(TypeKind))
				{
					if (Size % 16 != 0) return false;
					return Size % Precision == 0;
				}
				else
				{
					return Size == Precision;
				}
			}

			return true;
		}

		public bool CheckLocation(x86DataLocation Location)
		{
			if (Location is x86SSERegLocation) return true;
			return CheckLocation(Location.Size);
		}

		public x86StoredDataType GetPart(int Offset, int Size)
		{
			if (TypeKind == x86TypeKind.Unknown || Size < Precision || Offset % Precision != 0)
				return new x86StoredDataType();

			return this;
		}

		public x86StoredDataType SelfOrDefault(int Size)
		{
			var Ret = this;
			x86Identifiers.GetDefaultStoredDataType(ref Ret, Size);
			return Ret;
		}

		public x86StoredDataType SelfOrDefault(x86DataLocation Location)
		{
			return SelfOrDefault(Location.Size);
		}

		public x86StoredDataType VectorType()
		{
			var VecTypeKind = x86Identifiers.GetVectorTypeKind(TypeKind);
			return new x86StoredDataType(VecTypeKind, Precision);
		}

		public x86StoredDataType ScalarType()
		{
			var ScalarTypeKind = x86Identifiers.GetScalarTypeKind(TypeKind);
			return new x86StoredDataType(ScalarTypeKind, Precision);
		}
	}

	public class x86NodeData
	{
		public byte FPUItemsOnStack;
		public byte UsedFPUStack;
		public byte Scale = 1;
		public int Displacement;
		public x86SameAllocationAsType SameAllocationAsType;
		public byte SameAllocationAs;
		public x86NodeFlags Flags;
		public x86DataLocationType DataCalcPos;
		public x86DataLocation PreferredOutput;
		public x86DataList UsedDataBySelf;
		public x86DataList UsedData;
		public x86DataList TempCantBe;
		public x86DataList PreAllocate;
		public x86Operator Operator;
		public x86DataProperties Properties;
		public x86NeededTempData NeededTempByPlugin;
		public x86NeededTempData NeededTempData;
		public x86TemporaryData TempData;
		public x86DataLocation Output;
		public x86DataAllocator Allocator;
		public int ExecutionNumber;

		// Call Op
		public int ParameterBytes;

		// Shift Op
		public int OriginalShiftSize;

		// Float globals
		public Variable NegateAbsBitmask;
		public Variable InfinityVariable;
		public Variable DefaultFPUControlWord;
		public Variable ControlWordForRounding;

		// Assign OpNode
		public byte DontUseCount;

		// Root Data
		public IdContainer Container;
		public x86DataList AllUsedData;
		public List<ExpressionNode> AllNodes;
		public x86DataList AllAllocated;
		public byte NumberOfFails;

		public void Reset()
		{
			FPUItemsOnStack = 0;
			UsedFPUStack = 0;
			SameAllocationAsType = x86SameAllocationAsType.None;
			Flags &= x86NodeFlags.LeftByReset;
			DataCalcPos = x86DataLocationType.None;
			PreferredOutput = null;
			UsedData = null;
			UsedDataBySelf = null;
			TempCantBe = null;
			PreAllocate = null;
			Properties = new x86DataProperties();
			NeededTempByPlugin = new x86NeededTempData();
			Output = null;

			ParameterBytes = 0;
			OriginalShiftSize = 0;
		}

		public x86DataLocation ExtractedOutput
		{
			get
			{
				var PostCalcedPos = Output as x86PostCalcedLocation;
				return PostCalcedPos == null ? Output : PostCalcedPos.Location;
			}
		}
	}

	[Flags]
	public enum x86LinkedNodeFlags
	{
		None = 0,
		OnlyUseInParent = 1,
		AllocateData = 2,
		LocationProcessed = 4,
		CreatedForCall = 8,
	}

	public class x86LinkedNodeData
	{
		public x86DataLocation Specified;
		public x86DataLocation Location;
		public x86LinkedNodeFlags Flags;

		public x86LinkedNodeData(x86DataLocation Specified = null, x86LinkedNodeFlags Flags = x86LinkedNodeFlags.None)
		{
			this.Specified = Specified;
			this.Location = null;
			this.Flags = Flags;
		}
	}

	public static class x86Identifiers
	{
		public static x86StoredDataType GetDefaultStoredDataType(int Size)
		{
			return new x86StoredDataType(x86TypeKind.Unsigned, Size);
		}

		public static void GetDefaultStoredDataType(ref x86StoredDataType StoredDataTypePart, int Size)
		{
			if (StoredDataTypePart.TypeKind == x86TypeKind.Unknown)
				StoredDataTypePart = GetDefaultStoredDataType(Size);
		}

		public static void GetDefaultStoredDataType(ref x86StoredDataType StoredDataTypePart, x86DataLocation Location)
		{
			GetDefaultStoredDataType(ref StoredDataTypePart, Location.Size);
		}

		public static bool IsScalarNonfloatTypeKind(x86TypeKind TypeKind)
		{
			return IsNonfloatTypeKind(TypeKind) && !IsVectorTypeKind(TypeKind);
		}

		public static void GetScalarStoredDataType(ref x86StoredDataType StoredDataType)
		{
			StoredDataType.TypeKind = GetScalarTypeKind(StoredDataType.TypeKind);
		}

		public static void GetVectorStoredDataType(ref x86StoredDataType StoredDataType)
		{
			StoredDataType.TypeKind = GetVectorTypeKind(StoredDataType.TypeKind);
		}

		public static x86StoredDataType GetScalarStoredDataType(x86StoredDataType StoredDataType)
		{
			StoredDataType.TypeKind = GetScalarTypeKind(StoredDataType.TypeKind);
			return StoredDataType;
		}

		public static x86StoredDataType GetVectorStoredDataType(x86StoredDataType StoredDataType)
		{
			StoredDataType.TypeKind = GetVectorTypeKind(StoredDataType.TypeKind);
			return StoredDataType;
		}

		public static x86TypeKind GetVectorTypeKind(x86TypeKind TypeKind)
		{
			if (TypeKind == x86TypeKind.Float) return x86TypeKind.FloatVector;
			if (TypeKind == x86TypeKind.Signed) return x86TypeKind.SignedVector;
			if (TypeKind == x86TypeKind.Unsigned) return x86TypeKind.UnsignedVector;
			return TypeKind;
		}

		public static x86TypeKind GetScalarTypeKind(x86TypeKind TypeKind)
		{
			if (TypeKind == x86TypeKind.FloatVector) return x86TypeKind.Float;
			if (TypeKind == x86TypeKind.SignedVector) return x86TypeKind.Signed;
			if (TypeKind == x86TypeKind.UnsignedVector) return x86TypeKind.Unsigned;
			return TypeKind;
		}

		public static bool IsVectorTypeKind(x86TypeKind TypeKind)
		{
			if (TypeKind == x86TypeKind.FloatVector) return true;
			if (TypeKind == x86TypeKind.SignedVector) return true;
			if (TypeKind == x86TypeKind.UnsignedVector) return true;
			return false;
		}

		public static bool IsNonfloatTypeKind(x86TypeKind TypeKind)
		{
			return IsSignedTypeKind(TypeKind) || IsUnsignedTypeKind(TypeKind);
		}

		public static bool IsSignedTypeKind(x86TypeKind TypeKind)
		{
			if (TypeKind == x86TypeKind.Signed) return true;
			if (TypeKind == x86TypeKind.SignedVector) return true;
			return false;
		}

		public static bool IsUnsignedTypeKind(x86TypeKind TypeKind)
		{
			if (TypeKind == x86TypeKind.Unsigned) return true;
			if (TypeKind == x86TypeKind.UnsignedVector) return true;
			return false;
		}

		public static bool IsFloatTypeKind(x86TypeKind TypeKind)
		{
			if (TypeKind == x86TypeKind.Float) return true;
			if (TypeKind == x86TypeKind.FloatVector) return true;
			return false;
		}

		public static string GetSSETypeString(Identifier Identifier)
		{
			var StoredDataType = GetStoredDataType(Identifier);
			return GetSSETypeString(StoredDataType);
		}

		public static string GetSSETypeString(x86StoredDataType StoredDataType)
		{
			var Kind = StoredDataType.TypeKind;
			var Precision = StoredDataType.Precision;

			if (Precision == -1 || Kind == x86TypeKind.Unknown)
				throw new ArgumentException(null, "Identifier");

			if (Kind == x86TypeKind.Float)
			{
				if (Precision == 4) return "ss";
				else if (Precision == 8) return "sd";
				else throw new ApplicationException();
			}
			else if (Kind == x86TypeKind.FloatVector)
			{
				if (Precision == 4) return "ps";
				else if (Precision == 8) return "pd";
				else throw new ApplicationException();
			}
			else if (IsNonfloatTypeKind(Kind))
			{
				if (Precision == 1) return "b";
				else if (Precision == 2) return "w";
				else if (Precision == 4) return "d";
				else if (Precision == 8) return "q";
				else if (Precision == 16) return "dq";
				else throw new ApplicationException();
			}
			else
			{
				throw new ApplicationException();
			}
		}

		public static int GetPrecision(Identifier Identifier)
		{
			if (Identifier.RealId is TupleType)
			{
				var Tuple = Identifier.RealId as TupleType;
				var Members = Tuple.StructuredScope.IdentifierList;
				var Size = -1;

				for (var i = 0; i < Members.Count; i++)
				{
					var MemberType = Members[i].TypeOfSelf;
					var RMemberType = MemberType.RealId as Type;

					if (Size == -1) Size = RMemberType.Size;
					else if (Size != RMemberType.Size) return -1;
				}

				return Size;
			}

			return (Identifier.RealId as Type).Size;
		}

		public static x86TypeKind GetScalarTypeKind(Identifier Identifier)
		{
			if (!(Identifier.RealId is StructType))
			{
				if (Identifier.RealId is EnumType)
				{
					var Enum = Identifier.RealId as EnumType;
					Identifier = Enum.Children[0];
				}

				if (Identifier.RealId is FloatType) return x86TypeKind.Float;
				else if (Identifier.RealId is SignedType) return x86TypeKind.Signed;
				else return x86TypeKind.Unsigned;
			}

			return x86TypeKind.Unknown;
		}

		public static x86StoredDataType GetStoredDataType(Identifier Identifier)
		{
			var Precision = GetPrecision(Identifier);
			var Kind = GetTypeKind(Identifier, true);

			if (Precision == -1 || Kind == x86TypeKind.Unknown)
				return new x86StoredDataType();
			else return new x86StoredDataType(Kind, Precision);
		}

		public static x86TypeKind GetTypeKind(Identifier Identifier, bool DontCheckPrecision = false)
		{
			var State = Identifier.Container.State;
			var Arch = State.Arch as x86Architecture;

			if (Identifier.RealId is TupleType && false)
			{
				if (!DontCheckPrecision && GetPrecision(Identifier) == -1)
					return x86TypeKind.Unknown;

				var Tuple = Identifier.RealId as TupleType;
				var Members = Tuple.StructuredScope.IdentifierList;
				var Kind = x86TypeKind.Unknown;

				for (var i = 0; i < Members.Count; i++)
				{
					var MemberType = Members[i].TypeOfSelf;
					if (Kind == x86TypeKind.Unknown)
					{
						Kind = GetScalarTypeKind(MemberType);
						if (Kind == x86TypeKind.Unknown) return x86TypeKind.Unknown;
					}
					else
					{
						if (Kind != GetScalarTypeKind(MemberType))
							return x86TypeKind.Unknown;
					}
				}

				return GetVectorTypeKind(Kind);
			}

			return GetScalarTypeKind(Identifier);
		}

		public static x86DataLocationType GetPossibleLocations(Identifier Type)
		{
			//return x86DataLocType.Memory;
			var State = Type.Container.State;
			var Arch = State.Arch as x86Architecture;

			var RType = Type.RealId as Type;
			if (RType is EnumType) RType = (RType as EnumType).TypeOfValues;

			if (RType is FloatType)
			{
				if (Arch.FloatingPointMode == x86FloatingPointMode.SSE) return x86DataLocationType.SSEMem;
				else if (Arch.FloatingPointMode == x86FloatingPointMode.FPU) return x86DataLocationType.Memory;
				else throw new NotImplementedException();
			}

			if (RType is StructType || RType is NonrefArrayType) return x86DataLocationType.Memory;
			else if (RType.Size == 1) return x86DataLocationType.OneByteGeneral | x86DataLocationType.Memory;
			else return x86DataLocationType.GRegMem;
		}

		public static x86DataLocationType GetPossibleLocations(Identifier Id, x86IdentifierData Data)
		{
			if ((Data.Flags & x86IdentifierFlags.CantBeInReg) != 0) return x86DataLocationType.Memory;
			else return GetPossibleLocations(Id.TypeOfSelf.RealId as Type);
		}

		public static int GetMemberCount(Identifier Type)
		{
			if (Type.RealId is NonrefArrayType)
			{
				var ArrType = Type.RealId as NonrefArrayType;
				return ArrType.Length;
			}
			else if (Type.RealId is StructType)
			{
				var ValueType = Type.RealId as StructType;
				var Members = ValueType.StructuredScope.IdentifierList;
				return Members.Count;
			}
			else
			{
				throw new InvalidOperationException();
			}
		}

		public static Identifier GetMemberType(Identifier Type, int Index)
		{
			if (Type.RealId is NonrefArrayType)
			{
				var ArrType = Type.RealId as NonrefArrayType;
				return ArrType.TypeOfValues;
			}
			else if (Type.RealId is StructType)
			{
				var ValueType = Type.RealId as StructType;
				var Members = ValueType.StructuredScope.IdentifierList;
				var Var = Members[Index] as MemberVariable;
				return Var.TypeOfSelf;
			}
			else
			{
				throw new InvalidOperationException();
			}
		}

		public static bool IsMovableMember(Identifier Type, int Index)
		{
			if (Type.RealId is NonrefArrayType)
			{
				return true;
			}
			else if (Type.RealId is StructType)
			{
				var ValueType = Type.RealId as StructType;
				var Members = ValueType.StructuredScope.IdentifierList;
				return Members[Index] as MemberVariable != null;
			}
			else
			{
				throw new InvalidOperationException();
			}
		}

		public static x86DataLocation GetMember(x86DataLocation Position, Identifier Type, int Index)
		{
			if (Type.RealId is NonrefArrayType)
			{
				var ArrType = Type.RealId as NonrefArrayType;
				return Position.GetPart(ArrType.ElementSize * Index, ArrType.TypeOfValues.Size);
			}
			else if (Type.RealId is StructType)
			{
				var ValueType = Type.RealId as StructType;
				var Members = ValueType.StructuredScope.IdentifierList;
				var Var = Members[Index] as MemberVariable;
				if (Var == null) throw new ApplicationException("Not movable");

				var MemberType = Var.TypeOfSelf.RealId as Type;
				return Position.GetPart(Var.Offset, MemberType.Size);
			}
			else
			{
				throw new InvalidOperationException();
			}
		}
	}

	public static class x86Expressions
	{
		public static bool NeedLoadFloat(ExpressionNode Node, bool IsDst)
		{
			if (IsImmediateValue(Node)) return true;

			if (IsDst)
			{
				if (Node is IdExpressionNode) return true;

				var OpNode = Node as OpExpressionNode;
				if (OpNode == null) return false;

				var Op = OpNode.Operator;
				if (Op == Operator.Member || Op == Operator.Index)
					return true;
			}

			return false;
		}

		public static x86ConstLocation GetNullLocation(x86Architecture Arch, IdContainer Container)
		{
			var Value = new IntegerValue(0);
			var Type = Container.GlobalContainer.CommonIds.VoidPtr;
			return new x86ConstLocation(Arch, Value, Type, 0, Type.Size);
		}

		public static bool IsImmediateValue(ExpressionNode Node)
		{
			return Node is ConstExpressionNode || Node is DataPointerNode ||
				Node is LabelExpressionNode;
		}

		public static x86DataProperties GetDataProperties(ExpressionNode Node)
		{
			var Data = Node.Data.Get<x86NodeData>();
			if ((Data.Flags & x86NodeFlags.AllocateLocation) == 0)
				throw new InvalidOperationException();

			var Type = Node.Type.RealId as Type;
			return new x86DataProperties(Type.Size, Type.Align, Data.DataCalcPos, Data.TempCantBe);
		}

		public static x86DataProperties GetDataProperties(Identifier Type)
		{
			var RType = Type.RealId as Type;
			return new x86DataProperties(RType.Size, RType.Align,
				x86Identifiers.GetPossibleLocations(Type), null);
		}

		public static bool IsCondition(OpExpressionNode Node)
		{
			if (Node.Operator == Operator.Unknown)
			{
				var Data = Node.Data.Get<x86NodeData>();
				return IsConditionOp(Data.Operator);
			}
			else
			{
				return Operators.IsBoolRet(Node.Operator);
			}
		}

		public static bool IsCondition(ExpressionNode Node)
		{
			var OpNode = Node as OpExpressionNode;
			return OpNode == null ? false : IsCondition(OpNode);
		}

		public static bool IsBitTestOp(x86Operator Op)
		{
			return Op == x86Operator.BitTestNonZero || Op == x86Operator.BitTestZero;
		}
		public static bool IsConditionOp(x86Operator Op)
		{
			return IsBitTestOp(Op) || IsFlagOp(Op) || Op == x86Operator.IsFinite || 
				Op == x86Operator.IsInfinite || Op == x86Operator.IsNotNan || Op == x86Operator.IsNan;
		}

		public static bool IsFlagOp(x86Operator Op)
		{
			return Op == x86Operator.IsCarryFlagSet || Op == x86Operator.IsCarryFlagZero ||
				Op == x86Operator.IsParityFlagSet || Op == x86Operator.IsParityFlagZero ||
				Op == x86Operator.IsZeroFlagSet || Op == x86Operator.IsZeroFlagZero ||
				Op == x86Operator.IsSignFlagSet || Op == x86Operator.IsSignFlagZero ||
				Op == x86Operator.IsOverflowFlagSet || Op == x86Operator.IsOverflowFlagZero;
		}

		public static bool IsRoundOp(x86Operator Op)
		{
			return Op == x86Operator.Round || Op == x86Operator.Floor ||
				Op == x86Operator.Ceiling || Op == x86Operator.Truncate;
		}

		public static bool IsMinMaxOp(x86Operator Op)
		{
			return Op == x86Operator.Max || Op == x86Operator.Min;
		}

		public static bool IsTwoOperandSSEOp(x86Operator Op)
		{
			return IsMinMaxOp(Op);
		}

		public static bool IsTwoOperandNumberOp(Operator Op, x86Operator x86Op)
		{
			return Operators.IsRelEquality(Op) || Operators.IsBitArithmShift(Op) || IsTwoOperandSSEOp(x86Op);
		}

		public static x86Operator Negate(x86Operator Op)
		{
			if (Op == x86Operator.BitTestZero) return x86Operator.BitTestNonZero;
			else if (Op == x86Operator.BitTestNonZero) return x86Operator.BitTestZero;

			else if (Op == x86Operator.IsNan) return x86Operator.IsNotNan;
			else if (Op == x86Operator.IsNotNan) return x86Operator.IsNan;
			else if (Op == x86Operator.IsInfinite) return x86Operator.IsFinite;
			else if (Op == x86Operator.IsFinite) return x86Operator.IsInfinite;

			else if (Op == x86Operator.IsCarryFlagSet) return x86Operator.IsCarryFlagZero;
			else if (Op == x86Operator.IsCarryFlagZero) return x86Operator.IsCarryFlagSet;
			else if (Op == x86Operator.IsParityFlagSet) return x86Operator.IsParityFlagZero;
			else if (Op == x86Operator.IsParityFlagZero) return x86Operator.IsParityFlagSet;
			else if (Op == x86Operator.IsZeroFlagSet) return x86Operator.IsZeroFlagZero;
			else if (Op == x86Operator.IsZeroFlagZero) return x86Operator.IsZeroFlagSet;
			else if (Op == x86Operator.IsSignFlagSet) return x86Operator.IsSignFlagZero;
			else if (Op == x86Operator.IsSignFlagZero) return x86Operator.IsSignFlagSet;
			else if (Op == x86Operator.IsOverflowFlagSet) return x86Operator.IsOverflowFlagZero;
			else if (Op == x86Operator.IsOverflowFlagZero) return x86Operator.IsOverflowFlagSet;
			else throw new ApplicationException();
		}

		public static void Negate(ref Operator Op, ref x86Operator Op2)
		{
			if (Op == Operator.Unknown) Op2 = Negate(Op2);
			else Op = Operators.Negate(Op);
		}

		public static bool NeedReturnPointer(Identifier Type)
		{
			return Type.RealId is NonrefArrayType || Type.RealId is StructType;
		}

		public static bool NeedReturnPointer(ExpressionNode CallNode)
		{
			var OpNode = CallNode as OpExpressionNode;
			var Op = OpNode.Operator;
			var Ch = OpNode.Children;

			var FuncType = Ch[0].Type.RealId as TypeOfFunction;
			return NeedReturnPointer(FuncType.Children[0]);
		}

		public static bool NeedSelfParameter(ExpressionNode CallNode)
		{
			var OpNode = CallNode as OpExpressionNode;
			var Op = OpNode.Operator;
			var Ch = OpNode.Children;

			if (Expressions.IsSelfSpecified(Ch[0]))
				return true;

			if (Ch[0] is IdExpressionNode)
			{
				var IdCh0 = Ch[0] as IdExpressionNode;
				if (IdCh0.Identifier is Constructor && Op == Operator.NewObject)
					return true;
			}

			return false;
		}

		public static bool NeedsInstructions(ExpressionNode Node)
		{
			if (Node.LinkedNodes.Count > 0)
				return true;

			if (Node is IdExpressionNode || Node is ConstExpressionNode || Node is LinkingNode)
			{
				return false;
			}
			else if (Node is OpExpressionNode)
			{
				var OpNode = Node as OpExpressionNode;
				var Op = OpNode.Operator;
				var Ch = OpNode.Children;

				if (Op == Operator.Index)
				{
					return NeedsInstructions(Ch[0]) ||
						   NeedsInstructions(Ch[1]);
				}
				else if (Op == Operator.Member)
				{
					return NeedsInstructions(Ch[0]);
				}
			}

			return true;
		}

		public static x86DataLocation GetLocation(x86Architecture Arch, ExpressionNode Node)
		{
			var Data = Node.Data.Get<x86NodeData>();
			var Type = Node.Type.RealId as Type;
			var Size = Type.Size;

			if (Data != null && Data.Output != null)
			{
				if (Data.Output is x86PostCalcedLocation)
					return Data.ExtractedOutput;

				return Data.Output;
			}

			else if (Node is OpExpressionNode)
			{
				var OpNode = Node as OpExpressionNode;
				var Op = OpNode.Operator;
				var Ch = OpNode.Children;

				if (Op == Operator.Assignment)
				{
					return GetLocation(Arch, Ch[0]);
				}

				else if (Op == Operator.Index)
				{
					var Address = GetLocation(Arch, Ch[0]);
					var Offset = GetLocation(Arch, Ch[1]);
					if (Address == null || Offset == null)
						return null;

					var Ch0Type = Ch[0].Type.RealId;
					var AddressTempGReg = Data.TempData.GetGRegister(x86TempGRegPurposeType.Index, 0);
					var OffsetTempGReg = Data.TempData.GetGRegister(x86TempGRegPurposeType.Index, 1);

					if (Ch0Type is PointerType)
					{
						return GetIndexerPosition(Arch, Address, AddressTempGReg, Offset, 
							OffsetTempGReg, Size, Data.Displacement, Data.Scale);
					}
					else
					{
						throw new ApplicationException();
					}
				}

				else if (Op == Operator.Member)
				{
					var IdCh1 = Ch[1] as IdExpressionNode;
					if (IdCh1 == null) throw new ApplicationException();

					if (IdCh1.Identifier is Function && !IsVirtualMember(Node))
						return GetDefaultIdLocation(Arch, IdCh1.Identifier);

					var SrcPos = GetLocation(Arch, Ch[0]);
					if (SrcPos == null) return null;

					var Ch0Type = Ch[0].Type.RealId as Type;
					var AddressTempGReg = Data.TempData.GetGRegister(x86TempGRegPurposeType.Index, 0);
					if ((Ch0Type.TypeFlags & TypeFlags.ReferenceValue) != 0)
						SrcPos = GetIndexerPosition(Arch, SrcPos, AddressTempGReg, null, null, Ch0Type.InstanceSize);

					if (SrcPos == null)
						return null;

#warning WARNING, temp solution to allow BirdCore compilation
					SrcPos = SrcPos.GetPart(0);
					SrcPos.Size = int.MaxValue;

					var Splitable = SrcPos as x86SplittableLocation;
					if (Splitable == null) throw new ApplicationException();

					if (IdCh1.Identifier is MemberVariable)
					{
						var MemVar = IdCh1.Identifier as MemberVariable;
						return Splitable.GetPart(MemVar.Offset, Size);
					}
					else if (IdCh1.Identifier is MemberFunction)
					{
						var MemFunc = IdCh1.Identifier as MemberFunction;
						var Ptrs = Splitable.GetPart(0, Size);

						var RegSize = Arch.RegSize;
						var Global = MemFunc.Container.GlobalContainer;

						var OffsetValue = new IntegerValue(MemFunc.VirtualIndex * RegSize);
						var OffsetType = Global.CommonIds.GetIdentifier(typeof(SignedType), RegSize);
						var Offset = new x86ConstLocation(Arch, OffsetValue, OffsetType, 0, RegSize);
						return GetIndexerPosition(Arch, Ptrs, AddressTempGReg, Offset, null, RegSize);
					}

					throw new ApplicationException();
				}

				else if (Op == Operator.Unknown)
				{
					if (Data.Operator == x86Operator.Swap)
					{
						var Locations = new x86DataLocation[2];
						Locations[0] = GetLocation(Arch, Ch[0]);
						Locations[1] = GetLocation(Arch, Ch[1]);

						if (Locations[0] == null || Locations[1] == null)
							return null;

						return new x86MultiLocation(Arch, Size, Locations);
					}
				}
			}

			else if (Node is ConstExpressionNode)
			{
				var ConstNode = Node as ConstExpressionNode;
				return new x86ConstLocation(Arch, ConstNode, 0, Size);
			}

			else if (Node is IdExpressionNode)
			{
				var IdNode = Node as IdExpressionNode;
				var Id = IdNode.Identifier;
				
				if (!(Id is LocalVariable))
					return GetDefaultIdLocation(Arch, Id);

				var IdData = Id.Data.Get<x86IdentifierData>();
				var IdPos = IdData.Location;
				if (IdPos == null) return null;

				if ((Data.Flags & x86NodeFlags.IdentifierByRef) != 0)
				{
					Type = Id.Container.GlobalContainer.CommonIds.GetIdentifier(typeof(SignedType), Arch.RegSize);
					var Offset = new x86ConstLocation(Arch, new IntegerValue(0), Type, 0, Arch.RegSize);
					var AddressTempGReg = Data.TempData.GetGRegister(x86TempGRegPurposeType.Index, -1);
					return GetIndexerPosition(Arch, IdPos, AddressTempGReg, Offset, null, Size);
				}

				return IdPos;
			}
			
			else if (Node is DataPointerNode)
			{
				var IdDescNode = Node as DataPointerNode;
				if (IdDescNode.DescPointerType == DataPointerType.Assembly)
					return new x86NamedLabelPosition(Arch, IdDescNode.Assembly.DescLabel);
				else if (IdDescNode.DescPointerType == DataPointerType.Identifier)
					return GetDescLocation(Arch, IdDescNode.Id);
				else if (IdDescNode.DescPointerType == DataPointerType.IncBin)
					return new x86NamedLabelPosition(Arch, IdDescNode.IncBin.Label);
				else
					throw new NotImplementedException();
			}

			else if (Node is LabelExpressionNode)
			{
				var LabelNode = Node as LabelExpressionNode;
				return new x86NamedLabelPosition(Arch, LabelNode.Label);
			}

			return null;
		}

		public static bool IsVirtualMember(ExpressionNode Node)
		{
			var Op = Expressions.GetOperator(Node);
			if (Op != Operator.Member || (Node.Flags & ExpressionFlags.DisableVirtualMember) != 0)
				return false;

			var Ch = Node.Children;
			var IdCh0 = Ch[0] as IdExpressionNode;
			var IdCh1 = Ch[1] as IdExpressionNode;

			if ((IdCh1.Identifier.Flags & IdentifierFlags.Virtual) != 0)
			{
				if (!(IdCh1.Identifier is Constructor) && Ch[0].Type.UnderlyingClassOrRealId is ClassType &&
					!(IdCh0 != null && IdCh0.Identifier is BaseVariable))
				{
					return true;
				}
			}

			return false;
		}

		public static x86DataLocation GetLocation(x86Architecture Arch, Identifier Id)
		{
			var IdData = Id.Data.Get<x86IdentifierData>();
			var IdPos = IdData == null ? null : IdData.Location;
			if (IdPos != null) return IdPos;
			return GetDefaultIdLocation(Arch, Id);
		}

		static x86DataLocation GetDefaultIdLocation(x86Architecture Arch, Identifier Id)
		{
			Id = Id.RealId;
			if (Id is Type)
			{
				return GetDescLocation(Arch, Id);
			}
			else if (Id is Function)
			{
				return new x86NamedLabelPosition(Arch, Id.AssemblyName);
			}
			else if (Id is GlobalVariable)
			{
				var Label = new x86NamedLabelPosition(Arch, Id.AssemblyName);
                var Type = Id.TypeOfSelf.RealId as Type;
                return new x86IndexLocation(Arch, 0, Type.Size, Label);
			}
			else
			{
				throw new NotImplementedException();
			}
		}

		private static x86DataLocation GetDescLocation(x86Architecture Arch, Identifier Id)
		{
			Id = Id.UnderlyingStructureOrSelf;
			var Assembly = Id.Container.AssemblyScope.Assembly;

			if (Id.DescPosition == -1)
			{
				var Label = Assembly.DescLabel + " + ?? (" + Id.AssemblyName + ")";
				return new x86NamedLabelPosition(Arch, Label);
			}
			else
			{
				var Label = Assembly.DescLabel + " + " + (Id.DescPosition + Arch.RegSize * 2);
				return new x86NamedLabelPosition(Arch, Label);
			}
		}

		private static x86MemoryLocation GetIndexerPosition(x86Architecture Arch, x86DataLocation Address, 
			x86GRegLocation AddressTempGReg, x86DataLocation Offset, x86GRegLocation OffsetTempGReg,
			int Size, int Displacement = 0, byte Scale = 1)
		{
			if (Offset != null && Address.Size != Offset.Size) 
				throw new ApplicationException();

			var Ret = new x86IndexLocation(Arch, 0, Size, null);
			if (!Ret.Add(Address, AddressTempGReg))
				return null;

			if (Offset != null && !Ret.Add(Offset, OffsetTempGReg, Scale))
				return null;

			Ret.Offset += Displacement;
			return Ret;
		}

		public static bool SamePosition(x86Architecture Arch, ExpressionNode Self, x86DataLocation N, 
			x86OverlappingMode Mode = x86OverlappingMode.Whole)
		{
			var S = x86Expressions.GetLocation(Arch, Self);
			return S == null ? false : S.Compare(N, Mode);
		}

		public static bool SamePosition(x86Architecture Arch, ExpressionNode Self, ExpressionNode Node,
			x86OverlappingMode Mode = x86OverlappingMode.Whole)
		{
			var S = x86Expressions.GetLocation(Arch, Self);
			var N = x86Expressions.GetLocation(Arch, Node);
			return S == null || N == null ? false : S.Compare(N, Mode);
		}
	}
}

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
Student
Hungary Hungary
I've been programming for 8 years. My first big project was a remake of a nice bomberman game called Dyna Blaster. When i was little i played a lot with it. Now i'm working on a new programming language and code generator.
I would like to work with someone, so feel free to contact me about it.

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