Click here to Skip to main content
15,883,901 members
Articles / Programming Languages / ASM

Bird Programming Language: Part 3

Rate me:
Please Sign up or sign in to vote.
4.88/5 (5 votes)
1 Jan 2013GPL35 min read 29.8K   282   14  
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;
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)


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