using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Anonymus.x86
{
public partial class x86PlugIn : ExprPlugIn
{
public x86Architecture Arch;
public List<x86ExprScope> AllScopes;
public x86RegList AllUsedRegs;
public ExpressionNode CreateLinkingNode(ExpressionNode Node, ExpressionNode Parent, x86DataPosition AssignPos)
{
if (Parent.LinkedNodes == null)
Parent.LinkedNodes = new List<LinkedExprNode>();
var Linked = new LinkedExprNode(Node);
Linked.ArchData = new x86LinkedNodeData(AssignPos);
Parent.LinkedNodes.Add(Linked);
Node = Root.NewNode(new LinkingNode(Linked, Parent.Code));
return Node;
}
public void CalcExprScopes(ExpressionNode Node)
{
AllScopes = new List<x86ExprScope>() { };
AllUsedRegs = new x86RegList(Arch.RegCount);
CalcExprScopes_Rec(Node, null);
var Data = Node.ArchData as x86NodeData;
Data.AllScopes = AllScopes;
Data.AllUsedRegs = AllUsedRegs;
}
public void CalcExprScopes_Rec(ExpressionNode Node, x86ExprScope Scope)
{
var Data = Node.ArchData as x86NodeData;
if (Data.UsedRegs != null) AllUsedRegs.SetUsed(Data.UsedRegs);
if (Data.NewScope)
{
var NewScope = new x86ExprScope(Scope, Container);
if (Scope != null) Scope.Children.Add(NewScope);
AllScopes.Add(NewScope);
Scope = NewScope;
}
if (Node.LinkedNodes != null)
{
foreach (var e in Node.LinkedNodes)
{
var LData = e.ArchData as x86LinkedNodeData;
if (LData.Specified != null)
{
if (Scope.PreAllocated == null)
Scope.PreAllocated = new x86DataAllocator(Container);
Scope.PreAllocated.SetUsed(LData.Specified);
}
}
}
if (Data.PreAllocate != null)
{
if (Scope.PreAllocated == null)
Scope.PreAllocated = new x86DataAllocator(Container);
Scope.PreAllocated.UsedRegs.SetUsed(Data.PreAllocate);
}
Scope.NewDataPosition(Node);
foreach (var e in Node.EnumChildren)
CalcExprScopes_Rec(e, Scope);
}
public x86PlugIn(x86Architecture Arch, IdContainer Container)
: base(Container)
{
this.Arch = Arch;
}
public override PlugInRes End(ref ExpressionNode Node)
{
var Data = Node.ArchData as x86NodeData;
Data.NewScope = true;
var OpNode = Node as OpExpressionNode;
if (OpNode != null && OpNode.Operator == Operator.CreateTuple)
Data.Index = -1;
CalcExprScopes(Node);
return PlugInRes.Succeeded;
}
public PlugInRes NewOpNode_NonFloat(ref ExpressionNode Node)
{
var OpNode = Node as OpExpressionNode;
var Ch = OpNode.Children;
var Op = OpNode.Operator;
var Data = Node.ArchData as x86NodeData;
var Type = Ch[0].Type;
//--------------------------------------------------------------------------------------
if (Operators.IsMathsOp(Op))
{
if (Op == Operator.Abs)
{
var LinkedNode = new LinkedExprNode(Ch[0]);
var Zero = Root.NewNode(Expressions.GetIntValue(Container, 0, Node.Code));
if (Zero == null) return PlugInRes.Failed;
var CmpWith = Root.NewNode(new LinkingNode(LinkedNode, Node.Code));
if (CmpWith == null) return PlugInRes.Failed;
var CondCh = new List<ExpressionNode>() { Ch[0], Zero };
var Cond = new OpExpressionNode(Operator.Less, CondCh, Node.Code);
var Then = Root.NewNode(new LinkingNode(LinkedNode, Node.Code));
if (Then == null) return PlugInRes.Failed;
var Else = Root.NewNode(new LinkingNode(LinkedNode, Node.Code));
if (Else == null) return PlugInRes.Failed;
var ElseCh = new List<ExpressionNode>() { Else };
Else = Root.NewNode(new OpExpressionNode(Operator.Neg, ElseCh, Node.Code));
if (Else == null) return PlugInRes.Failed;
var NewCh = new List<ExpressionNode>() { Cond, Then, Else };
var Ret = new OpExpressionNode(Operator.Condition, NewCh, Node.Code);
Ret.LinkedNodes = new List<LinkedExprNode>() { LinkedNode };
Node = Root.NewNode(Ret);
if (Node == null) return PlugInRes.Failed;
else return PlugInRes.Ready;
}
else
{
Ch[0] = Root.NewNode(new CastExpressionNode(Node.Type, Ch[0], Node.Code));
if (Ch[0] == null) return PlugInRes.Failed;
return NewOpNode_Float(ref Node);
}
}
//--------------------------------------------------------------------------------------
if (Operators.IsShiftOp(Op))
{
if (Type.Size > Arch.RegSize)
{
var Func = (string)null;
if (Op == Operator.ShiftLeft) Func = "LongShiftLeft";
else if (Op == Operator.ShiftRight) Func = Type is UnsignedType ? "ULongShiftRight" : "LongShiftRight";
Node = Expressions.CreateCallIndexExpr(Node.Code, Root,
Operator.Call, new PString(Func), Ch);
if (Node == null) return PlugInRes.Failed;
Node.Type = OpNode.Type;
return PlugInRes.Ready;
}
else
{
Data.Index = AdjustRegs(OpNode, true);
}
}
//--------------------------------------------------------------------------------------
else if (Operators.IsBitwiseOp(Op))
{
Data.Index = AdjustRegs(OpNode, true);
}
//--------------------------------------------------------------------------------------
else if (Operators.IsArithmeticalOp(Op))
{
if (NeedSwap(Ch)) OpNode.Swap();
var CalcedNew = false;
if ((Op == Operator.Multiply || Op == Operator.Divide) && Ch[1].Type is NonFltNumType)
{
var ConstCh1 = Ch[1] as ConstExpressionNode;
if (ConstCh1 != null)
{
var V = ConstCh1.Unsigned;
if (Helper.Pow2(V) == V)
{
var NewOp = Op == Operator.Multiply ? Operator.ShiftLeft : Operator.ShiftRight;
var CNode = Root.NewNode(new ConstExpressionNode(Ch[1].Type, Helper.Pow2Sqrt(V), Node.Code));
Ch = new List<ExpressionNode>() { Ch[0], CNode };
Node = Root.NewNode(new OpExpressionNode(NewOp, Ch, Node.Code));
CalcedNew = true;
if (Node != null)
{
Data = Node.ArchData as x86NodeData;
return PlugInRes.Ready;
}
return PlugInRes.Failed;
}
}
}
if (!CalcedNew)
{
var Size = Node.Type.Size;
if (Op == Operator.Multiply || Op == Operator.Divide || Op == Operator.Modolus)
{
if (Size > Arch.RegSize)
{
var Func = (string)null;
if (Op == Operator.Multiply) Func = "LongMul";
else if (Op == Operator.Divide) Func = Type is UnsignedType ? "ULongDiv" : "LongDiv";
else if (Op == Operator.Modolus) Func = Type is UnsignedType ? "ULongMod" : "LongMod";
Node = Expressions.CreateCallIndexExpr(Node.Code, Root,
Operator.Call, new PString(Func), Ch);
if (Node == null) return PlugInRes.Failed;
Node.Type = OpNode.Type;
return PlugInRes.Ready;
}
else
{
/* imul 1:
* dst: r16/r32
* src: m16/m32/r16/r32/i16/i32
*
* imul 2 / idiv / div:
* dst: accumulator
* src: m8/m16/m32/r8/r16/r32
*
* remainder (except imul 1):
* byte: ah
* word: dx
* dword: edx
*/
Data.Index = AdjustRegs(OpNode, true);
if (Op != Operator.Multiply || Size == 1)
{
if (Ch[1] is ConstExpressionNode)
{
var C = Ch[1] as ConstExpressionNode;
Ch[1] = Container.GlobalScope.CreateConstRId(C, Root);
if (Ch[1] == null) return PlugInRes.Failed;
}
var Ch0Data = Ch[0].ArchData as x86NodeData;
var Ch1Data = Ch[1].ArchData as x86NodeData;
Ch0Data.Input = new x86RegPosition(Arch, Size, 0);
if (Op != Operator.Multiply)
{
if (Ch1Data.CantBe == null)
Ch1Data.CantBe = new x86RegList(Arch.RegCount);
if (Size == 1) Ch1Data.CantBe.SetUsed(0, 2);
else Ch1Data.CantBe.SetUsed(2, Size);
}
Data.UsedRegs = new x86RegList(Arch.RegCount);
Data.Index = -1;
Data.NewScope = true;
if (Size == 1)
{
Data.UsedRegs.SetUsed(0, 2);
var Pos = new x86RegPosition(Arch, 1, 0, Op == Operator.Modolus);
Data.Output = Pos;
}
else
{
Data.UsedRegs.SetUsed(0, Size);
Data.UsedRegs.SetUsed(2, Size);
var RegId = Op == Operator.Modolus ? 2 : 0;
var Pos = new x86RegPosition(Arch, Size, RegId);
Data.Output = Pos;
}
}
else
{
Data.DataCalcPos = x86DataCalcPos.GeneralReg;
}
}
}
else
{
Data.Index = AdjustRegs(OpNode, true);
}
}
}
//--------------------------------------------------------------------------------------
else if (Operators.IsRelEqualityOp(Op))
{
if (NeedSwap(Ch)) OpNode.Swap();
Data.Index = AdjustRegs(OpNode, false);
}
//--------------------------------------------------------------------------------------
else if (Op == Operator.Neg || Op == Operator.Complement)
{
if (Type.Size > Arch.RegSize && (Ch[0] is IdExpressionNode || Ch[0] is ConstExpressionNode))
{
var Null = Expressions.CreateConstNode(Node.Code,
new ConstData(0), Ch[0].Type, Root);
if (Null == null) return PlugInRes.Failed;
var NCh = new List<ExpressionNode>() { Null, Ch[0] };
Node = Root.NewNode(new OpExpressionNode(Operator.Subract, NCh, Node.Code));
if (Node == null) return PlugInRes.Failed;
else return PlugInRes.Ready;
}
else
{
var ChIndex = (Ch[0].ArchData as x86NodeData).Index;
if (ChIndex == -1)
{
Ch[0] = CreateMoveNode(Ch[0], 0);
if (Ch[0] == null) return PlugInRes.Failed;
Data.Index = 0;
}
else
{
Data.Index = ChIndex;
}
}
}
//--------------------------------------------------------------------------------------
else if (Op != Operator.Assignment)
{
throw new Exception("ERROR");
}
return PlugInRes.Succeeded;
}
public PlugInRes NewOpNode_Float(ref ExpressionNode Node)
{
var OpNode = Node as OpExpressionNode;
var Ch = OpNode.Children;
var Op = OpNode.Operator;
var Data = Node.ArchData as x86NodeData;
if (Op != Operator.Assignment && !AdjustConstFltNode(Ch))
return PlugInRes.Failed;
//--------------------------------------------------------------------------------------
if (Operators.IsMathsOp(Op))
{
var Ch0Data = Ch[0].ArchData as x86NodeData;
Data.Index = -1;
Data.FPUItemsOnStack = Ch0Data.FPUItemsOnStack;
if (Op == Operator.ACos)
{
Node = Expressions.CreateCallIndexExpr(Node.Code, Root,
Operator.Call, new PString("Math_ArcCosine"), Ch);
if (Node == null) return PlugInRes.Failed;
else return PlugInRes.Ready;
}
else if (Op == Operator.ASin)
{
Node = Expressions.CreateCallIndexExpr(Node.Code, Root,
Operator.Call, new PString("Math_ArcSine"), Ch);
if (Node == null) return PlugInRes.Failed;
else return PlugInRes.Ready;
}
else if (Op == Operator.ATan2)
{
if (!AdjustRegs_Float(OpNode, true))
return PlugInRes.Failed;
}
else if (Op == Operator.Tan)
{
Data.UsedFPUStack = 1;
if (Ch0Data.FPUItemsOnStack >= 8)
{
if ((Ch[0] = CreateMoveNode(Ch[0], 0, x86DataCalcPos.Memory)) == null)
return PlugInRes.Failed;
Ch[0].Type = Container.GetType(typeof(FloatType), 8);
}
}
}
//--------------------------------------------------------------------------------------
else if (Op == Operator.Assignment)
{
var RId = Ch[0] as IdExpressionNode;
var Var = RId != null ? RId.Id as LocalVariable : null;
if (!AdjustRegs_Float(OpNode, false, false)) return PlugInRes.Failed;
}
//--------------------------------------------------------------------------------------
else if (Operators.IsArithmeticalOp(Op))
{
if (NeedSwap(Ch)) OpNode.Swap();
Data.Index = -1;
if (!AdjustRegs_Float(OpNode, true)) return PlugInRes.Failed;
}
//--------------------------------------------------------------------------------------
else if (Operators.IsRelEqualityOp(Op))
{
if (NeedSwap(Ch)) OpNode.Swap();
Data.Index = -1;
//Data.NewScope = true;
if (!AdjustRegs_Float(OpNode, true)) return PlugInRes.Failed;
}
//--------------------------------------------------------------------------------------
else if (Op == Operator.Neg)
{
Data.Index = -1;
}
//--------------------------------------------------------------------------------------
else
{
throw new Exception("ERROR");
}
return PlugInRes.Succeeded;
}
public PlugInRes NewOpNode_Ptr(ref ExpressionNode Node)
{
var OpNode = Node as OpExpressionNode;
var Ch = OpNode.Children;
var Op = OpNode.Operator;
var Data = Node.ArchData as x86NodeData;
//--------------------------------------------------------------------------------------
if (Operators.IsArithmeticalOp(Op))
{
if (Op == Operator.Add)
{
var PType = Ch[0].Type as PointerType;
Ch[1] = MulBy(Ch[1], PType.Child.Size);
if (Ch[1] == null) return PlugInRes.Failed;
}
Data.Index = AdjustRegs(OpNode, true);
}
//--------------------------------------------------------------------------------------
else if (Op == Operator.Index)
{
var pType = Ch[0].Type as PointerType;
var Size = pType.Child.Size;
for (var i = 1; i < Ch.Count; i++)
{
if (Ch[i] is ConstExpressionNode) Ch[i] = MulBy(Ch[i], Size);
else (Ch[i].ArchData as x86NodeData).MulBy = Size;
}
Data.Index = -1;
}
//--------------------------------------------------------------------------------------
else if (Operators.IsRelEqualityOp(Op))
{
if (NeedSwap(Ch)) OpNode.Swap();
Data.Index = AdjustRegs(OpNode, false);
}
//--------------------------------------------------------------------------------------
else if (Op != Operator.Assignment)
{
throw new Exception("ERROR");
}
return PlugInRes.Succeeded;
}
public PlugInRes NewOpNode_Bool(ref ExpressionNode Node)
{
var OpNode = Node as OpExpressionNode;
var Ch = OpNode.Children;
var Op = OpNode.Operator;
var Data = Node.ArchData as x86NodeData;
//--------------------------------------------------------------------------------------
if (Operators.IsBoolRetOp(Op))
{
var Log = !Operators.IsRelEqualityOp(Op);
if (!Log && Ch[0] is ConstExpressionNode && !(Ch[1] is ConstExpressionNode))
OpNode.Swap();
if (Operators.IsRelEqualityOp(Op))
{
for (var i = 0; i < Ch.Count; i++)
{
var OpCh = Ch[i] as OpExpressionNode;
if (OpCh != null && Operators.IsBoolRetOp(OpCh.Operator))
{
Ch[i] = CreateMoveNode(Ch[i], 0);
if (Ch[i] == null) return PlugInRes.Failed;
}
}
}
Data.Index = AdjustRegs(OpNode, false);
}
//--------------------------------------------------------------------------------------
else if (Op == Operator.Not)
{
var False = Root.NewNode(Expressions.GetBoolValue(Container, false, Node.Code));
var nCh = new List<ExpressionNode>() { Ch[0], False };
Node = Root.NewNode(new OpExpressionNode(Operator.Equal, nCh, Node.Code));
}
//--------------------------------------------------------------------------------------
else if (Op != Operator.Assignment)
{
throw new Exception("ERROR");
}
return PlugInRes.Succeeded;
}
bool[] TupleAssignment_AlwaysLink = new bool[] { false, true };
public PlugInRes NewOpNode_Structured(ref ExpressionNode Node)
{
var OpNode = Node as OpExpressionNode;
var Ch = OpNode.Children;
var Op = OpNode.Operator;
var Data = Node.ArchData as x86NodeData;
//--------------------------------------------------------------------------------------
if (Op == Operator.Neg || Op == Operator.Complement || Operators.IsBitArithmOp(Op))
{
if (OpNode.Type is TupleType)
{
var Code = Node.Code;
Node = Expressions.ExtractTupleOp(Node, Root, (i, Args) =>
{
return Root.NewNode(new OpExpressionNode(Op, Args, Code));
});
if (Node == null) return PlugInRes.Failed;
else return PlugInRes.Ready;
}
else
{
throw new Exception("ERROR");
}
}
//--------------------------------------------------------------------------------------
else if (Op == Operator.Member)
{
if (Ch[0] is OpExpressionNode)
{
var OpCh = Ch[0] as OpExpressionNode;
var OpChOp = OpCh.Operator;
if (OpChOp == Operator.New || OpChOp == Operator.Call)
{
Ch[0] = CreateMoveNode(Ch[0], 0, x86DataCalcPos.Memory);
if (Ch[0] == null) return PlugInRes.Failed;
}
}
Data.Index = -1;
}
//--------------------------------------------------------------------------------------
else if (Op == Operator.Assignment)
{
var OpCh0 = Ch[0] as OpExpressionNode;
if (OpCh0 != null && OpCh0.Operator == Operator.CreateTuple)
{
var Code = Node.Code;
Node = Expressions.ExtractTupleOp(Node, Root, (i, Args) =>
{
return Root.NewNode(new OpExpressionNode(Operator.Assignment, Args, Code));
}, TupleAssignment_AlwaysLink);
if (Node == null) return PlugInRes.Failed;
else return PlugInRes.Ready;
}
}
//--------------------------------------------------------------------------------------
else
{
throw new Exception("ERROR");
}
return PlugInRes.Succeeded;
}
public PlugInRes NewOpNode_Type(ref ExpressionNode Node)
{
var OpNode = Node as OpExpressionNode;
var Op = OpNode.Operator;
var Ch = OpNode.Children;
var Type = Ch[0].Type.RealType;
if (Type is NonFltNumType) return NewOpNode_NonFloat(ref Node);
else if (Type is FloatType) return NewOpNode_Float(ref Node);
else if (Type is BoolType) return NewOpNode_Bool(ref Node);
else if (Type is PointerType) return NewOpNode_Ptr(ref Node);
else if (Type is StructuredType) return NewOpNode_Structured(ref Node);
else throw new Exception("ERROR");
}
public ExpressionNode NewCallOpNode(ExpressionNode Node)
{
var OpNode = Node as OpExpressionNode;
var Ch = OpNode.Children;
var Data = Node.ArchData as x86NodeData;
var FuncType = Ch[0].Type as FunctionType;
Data.Index = -1;
Data.UsedRegs = new x86RegList(Arch.RegCount);
Data.UsedFPUStack = int.MaxValue;
//--------------------------------------------------------------------------------------
for (var i = 1; i < Ch.Count; i++)
{
var ChData = Ch[i].ArchData as x86NodeData;
ChData.NewScope = true;
if (Ch[i] is ConstExpressionNode & Ch[i].Type is FloatType)
{
Ch[i] = AdjustConstFltNode(Ch[i] as ConstExpressionNode);
if (Ch[i] == null) return null;
}
}
for (var i = 0; i < Arch.RegCount; i++)
if (x86Architecture.IsVolatileReg(i, FuncType.Conv))
Data.UsedRegs.SetUsed(i, Arch.RegSize);
//--------------------------------------------------------------------------------------
var RetType = FuncType.RetType;
if (!(RetType is RefType)) RetType = RetType.RealType;
var S = RetType.Size;
var NeedMoveRetType = false;
if (RetType is FloatType)
{
Data.FPUItemsOnStack = 1;
}
else if (RetType is PointerType || RetType is BoolType || RetType is FunctionType ||
RetType is RefType || RetType is ClassType)
{
var Pos = new x86RegPosition(Arch, S, 0);
Data.Output = Pos;
}
else if (RetType is NonFltNumType)
{
x86DataPosition Pos = null;
if (S == Arch.RegSize) Pos = new x86RegPosition(Arch, S, 0);
else if (S == Arch.RegSize * 2) Pos = Arch.MultiRegPos(0, 2);
Data.Output = Pos;
}
else if (!(RetType is VoidType))
{
NeedMoveRetType = true;
}
//--------------------------------------------------------------------------------------
if (FuncType.Conv == CallConv.AsCall)
{
var Index = NeedMoveRetType ? 1 : 0;
var OpCh0 = Ch[0] as OpExpressionNode;
if (OpCh0 != null && OpCh0.Operator == Operator.Member)
Index++;
if (Index > 0)
{
Data.PreAllocate = new x86RegList(Arch.RegCount);
for (var i = 0; i < Index; i++)
{
var Reg = x86DataAllocator.RegAllocSequence[i];
Data.PreAllocate.SetUsed(Reg, Arch.RegSize);
}
}
var Types = new Type[Ch.Count - 1];
for (var i = 1; i < Ch.Count; i++)
Types[i - 1] = Ch[i].Type;
foreach (var i in Arch.EnumFirstAsCallParams(Types, Index))
{
var ChNode = Ch[i + 1];
if (ChNode is OpExpressionNode || ChNode is CastExpressionNode)
{
var P = Arch.GetArgP(ref Index, ChNode.Type.Size);
ChNode = CreateLinkingNode(ChNode, Node, P);
if (ChNode == null) return null;
Ch[i + 1] = ChNode;
}
}
}
return Node;
}
public PlugInRes NewOpNode(ref ExpressionNode Node)
{
var OpNode = Node as OpExpressionNode;
var Ch = OpNode.Children;
var Op = OpNode.Operator;
var Data = Node.ArchData as x86NodeData;
if (Op == Operator.New)
{
Data.Index = -1;
}
//--------------------------------------------------------------------------------------
else if (Op == Operator.Condition)
{
var ChData = Ch[1].ArchData as x86NodeData;
var RegId = ChData.Index == -1 ? 0 : ChData.Index;
for (var i = 1; i < 3; i++)
{
var n = Ch[i];
ChData = n.ArchData as x86NodeData;
if (ChData.Index != RegId)
{
n = CreateMoveNode(n, RegId, x86Architecture.TypePos(Ch[i].Type));
Ch[i] = n;
}
}
var Ch0Data = Ch[0].ArchData as x86NodeData;
Ch0Data.NewScope = true;
Data.Index = RegId;
}
//--------------------------------------------------------------------------------------
else if (Op == Operator.Call)
{
Node = NewCallOpNode(Node);
if (Node == null) return PlugInRes.Failed;
}
//--------------------------------------------------------------------------------------
else if (Op == Operator.Assignment)
{
Data.NewScope = true;
Data.Index = -1;
var Res = NewOpNode_Type(ref Node);
if (Res == PlugInRes.Ready || Res == PlugInRes.Failed)
return Res;
}
//--------------------------------------------------------------------------------------
else if (Op == Operator.Address)
{
Data.Index = 0;
}
//--------------------------------------------------------------------------------------
else if (Op == Operator.CreateTuple)
{
Data.Index = 0;
Data.DataCalcPos = x86DataCalcPos.Memory;
}
//--------------------------------------------------------------------------------------
else
{
var Res = NewOpNode_Type(ref Node);
if (Res == PlugInRes.Ready || Res == PlugInRes.Failed)
return Res;
}
return PlugInRes.Succeeded;
}
public PlugInRes NewCastNode_NonFloat(ref ExpressionNode Node)
{
var CastNode = Node as CastExpressionNode;
var Ch = CastNode.Child;
var Data = Node.ArchData as x86NodeData;
var ChData = Ch.ArchData as x86NodeData;
Data.Index = ChData.Index == -1 ? 0 : ChData.Index;
var From = Ch.Type.RealType;
var To = Node.Type.RealType;
var ToSize = To.Size;
//--------------------------------------------------------------------------------------
if (From is FloatType)
{
if (ToSize > Arch.RegSize && To is UnsignedType)
{
if (ToSize != 8) throw new NotImplementedException();
var Func = Ch.Type.Size == 4 ? "FloatToULong" : "DoubleToULong";
Node = Expressions.CreateCallIndexExpr(Node.Code, Root, Operator.Call,
new PString(Func), Ch);
if (Node == null) return PlugInRes.Failed;
else return PlugInRes.Ready;
}
else if (ToSize == 1 || To is UnsignedType)
{
CastNode.ArchData = Data;
CastNode.Type = Container.GetType(To.GetType(), ToSize * 2);
Node = CreateSizeChangerNode(CastNode, ToSize, x86DataCalcPos.Memory);
}
}
//--------------------------------------------------------------------------------------
else if (From is NonFltNumType)
{
if (From.Size == ToSize)
{
Node = Ch;
Node.Type = CastNode.Type;
}
else if (From is SignedType && ToSize > Arch.RegSize && Ch.Type.Size < ToSize)
{
Data.Output = Arch.MultiRegPos(0, 2);
Data.UsedRegs = new x86RegList(Arch.RegCount);
Data.UsedRegs.SetUsed(0, Arch.RegSize);
Data.UsedRegs.SetUsed(2, Arch.RegSize);
Data.Index = -1;
Data.NewScope = true;
}
}
//--------------------------------------------------------------------------------------
else
{
throw new Exception("ERROR");
}
return PlugInRes.Succeeded;
}
public PlugInRes NewCastNode_Float(ref ExpressionNode Node)
{
var CastNode = Node as CastExpressionNode;
var Ch = CastNode.Child;
var Data = Node.ArchData as x86NodeData;
Data.Index = -1;
var From = Ch.Type.RealType;
var To = Node.Type.RealType;
//--------------------------------------------------------------------------------------
if (From is FloatType)
{
Node = Ch;
Node.Type = CastNode.Type;
}
//--------------------------------------------------------------------------------------
else if (From is NonFltNumType)
{
var Size = From.Size;
if (From is UnsignedType && Size > Arch.RegSize)
{
if (Size != 8) throw new Exception("ERROR");
Node = Expressions.CreateCallIndexExpr(Node.Code, Root, Operator.Call,
new PString("ULongToFloat"), Ch);
if (Node == null) return PlugInRes.Failed;
else return PlugInRes.Ready;
}
else
{
var Ok = true;
if (From is UnsignedType) Ok = false;
else if (Size == 1) Ok = false;
if (!Ok)
{
Ch = CreateSizeChangerNode(Ch, Size * 2);
(Ch.ArchData as x86NodeData).DataCalcPos = x86DataCalcPos.Memory;
}
/*else
{
if (Ch is IdExpressionNode)
{
var IdCh = Ch as IdExpressionNode;
IdCh.Id.CanBeInReg = false;
}
else
{
var ChData = Ch.Data as x86NodeData;
if (ChData.Index != -1) ChData.DataCalcPos = x86DataCalcPos.Memory;
}
}*/
Data.FPUItemsOnStack = 1;
CastNode.Child = Ch;
}
}
//--------------------------------------------------------------------------------------
else
{
throw new Exception("ERROR");
}
return PlugInRes.Succeeded;
}
public PlugInRes NewCastNode_Ptr(ref ExpressionNode Node)
{
var CastNode = Node as CastExpressionNode;
var Ch = CastNode.Child;
var Data = Node.ArchData as x86NodeData;
var ChData = Ch.ArchData as x86NodeData;
Data.Index = ChData.Index == -1 ? 0 : ChData.Index;
var From = Ch.Type.RealType;
var To = Node.Type.RealType;
//--------------------------------------------------------------------------------------
if (From is PointerType)
{
if (Ch.Type.Size != Node.Type.Size)
throw new Exception("ERROR");
}
//--------------------------------------------------------------------------------------
else
{
throw new Exception("ERROR");
}
return PlugInRes.Succeeded;
}
public PlugInRes NewCastNode_Structured(ref ExpressionNode Node)
{
var CastNode = Node as CastExpressionNode;
var Ch = CastNode.Child;
var Data = Node.ArchData as x86NodeData;
var ChData = Ch.ArchData as x86NodeData;
Data.Index = ChData.Index == -1 ? 0 : ChData.Index;
Data.DataCalcPos = x86DataCalcPos.Memory;
var From = Ch.Type.RealType;
var To = Node.Type.RealType;
if (From.IsEqual(To)) return PlugInRes.Succeeded;
if (To is TupleType && From is TupleType)
{
var DstType = To as TupleType;
var Code = Node.Code;
Node = Expressions.ExtractTupleOp(Node, Root, (i, Nodes) =>
{
var MemVar = DstType.Members[i] as MemberVariable;
var Ret = Root.NewNode(new CastExpressionNode(MemVar.Type, Nodes[0], Code));
if (Ret == null) return null;
Ret.IncRegs(i + 1);
return Ret;
});
if (Node == null) return PlugInRes.Failed;
else return PlugInRes.Ready;
}
else
{
throw new Exception("ERROR");
}
}
public PlugInRes NewCastNode(ref ExpressionNode Node)
{
var CastNode = Node as CastExpressionNode;
var Ch = CastNode.Child;
var Data = Node.ArchData as x86NodeData;
var RealType = Node.Type.RealType;
if (Ch.Type.RealType is AutomaticType)
{
Ch.Type = CastNode.Type;
Node = Ch;
return PlugInRes.Succeeded;
}
else if (RealType is NonFltNumType) return NewCastNode_NonFloat(ref Node);
else if (RealType is FloatType) return NewCastNode_Float(ref Node);
else if (RealType is PointerType) return NewCastNode_Ptr(ref Node);
else if (RealType is StructuredType) return NewCastNode_Structured(ref Node);
else throw new Exception("ERROR");
}
public override PlugInRes NewNode(ref ExpressionNode Node)
{
var Data = Node.ArchData as x86NodeData;
if (Data != null) throw new Exception("ERROR");
Data = new x86NodeData();
Node.ArchData = Data;
if (Node.LinkedNodes != null)
{
foreach (var e in Node.LinkedNodes)
e.ArchData = new x86LinkedNodeData(null);
}
// ------------------------------------------------------------------------------------
if (Node is LinkingNode)
{
Data.Index = -1;
}
else if (Node is MacroExpressionNode)
{
return PlugInRes.Succeeded;
}
else if (Node is StrExpressionNode)
{
return PlugInRes.Succeeded;
}
else if (Node is IdExpressionNode)
{
var RIdNode = Node as IdExpressionNode;
var Id = RIdNode.Id;
Data.Index = -1;
if (Id is Variable)
{
var T = RIdNode.Type;
if (T is FloatType || T is ValueType)
Id.CanBeInReg = false;
}
}
else if (Node is OpExpressionNode)
{
var Res = NewOpNode(ref Node);
if (Res == PlugInRes.Ready || Res == PlugInRes.Failed)
return Res;
}
else if (Node is CastExpressionNode)
{
var Res = NewCastNode(ref Node);
if (Res == PlugInRes.Ready || Res == PlugInRes.Failed)
return Res;
}
else if (Node is ConstExpressionNode)
{
var ConstNode = Node as ConstExpressionNode;
Data.Index = -1;
}
// ------------------------------------------------------------------------------------
Data = Node.ArchData as x86NodeData;
if (Node == null || Node.Type == null || Data == null || Data.Index == int.MaxValue)
throw new Exception("ERROR");
if (!PostProcNode(Node)) return PlugInRes.Failed;
else return PlugInRes.Succeeded;
}
public bool PostProcNode(ExpressionNode Node)
{
if (!CalcLinkedNodes(Node)) return false;
if (!CalcNodeCantBe(Node)) return false;
return true;
}
public bool CalcLinkedNodes(ExpressionNode Node)
{
if (Node.LinkedNodes != null)
foreach (var e in Node.LinkedNodes)
{
var ChData = e.Node.ArchData as x86NodeData;
ChData.NewScope = true;
}
return true;
}
bool CalcNodeCantBe(ExpressionNode Node)
{
var Data = Node.ArchData as x86NodeData;
if (Data.UsedFPUStack < Data.FPUItemsOnStack)
Data.UsedFPUStack = Data.FPUItemsOnStack;
foreach (var Ch in Node.EnumChildren)
{
var ChData = Ch.ArchData as x86NodeData;
if (ChData.UsedFPUStack > Data.UsedFPUStack)
Data.UsedFPUStack = ChData.UsedFPUStack;
}
// ----------------------------------------------------------------
var UsedRegs = (x86RegList)null;
foreach (var Ch in Node.EnumChWithoutLinkedNodes)
{
var ChUsed = (Ch.ArchData as x86NodeData).UsedRegs;
if (ChUsed == null) continue;
if (UsedRegs == null) UsedRegs = ChUsed.Copy();
else UsedRegs.SetUsed(ChUsed);
}
// ----------------------------------------------------------------
if (Node.LinkedNodes != null)
{
for (var i = Node.LinkedNodes.Count - 1; i >= 0; i--)
{
var e = Node.LinkedNodes[i];
var LNode = e.Node;
var LData = LNode.ArchData as x86NodeData;
if (UsedRegs != null)
{
if (LData.CantBe != null) LData.CantBe.SetUsed(UsedRegs);
else LData.CantBe = UsedRegs.Copy();
if (LData.UsedRegs != null) UsedRegs.SetUsed(LData.UsedRegs);
}
else
{
if (LData.UsedRegs != null) UsedRegs = LData.UsedRegs.Copy();
}
}
}
// ----------------------------------------------------------------
if (UsedRegs != null)
{
if (Data.UsedRegs == null) Data.UsedRegs = UsedRegs;
else Data.UsedRegs.SetUsed(UsedRegs);
}
// ----------------------------------------------------------------
if (Node is OpExpressionNode)
{
var OpNode = Node as OpExpressionNode;
var Op = OpNode.Operator;
var Ch = OpNode.Children;
if (Operators.IsBoolRetBitArithmOp(Op))
{
var Dst = Ch[0];
var Src = Ch[1];
var DstData = Dst.ArchData as x86NodeData;
var SrArchData = Src.ArchData as x86NodeData;
if (!OpNode.Reverse)
{
if (SrArchData.UsedRegs != null)
{
var Regs = SrArchData.UsedRegs;
if (DstData.CantBe == null)
DstData.CantBe = Regs.Copy();
else DstData.CantBe.SetUsed(Regs);
}
}
else
{
if (DstData.Output != null)
{
var Regs = DstData.Output.GetRegs();
if (SrArchData.CantBe == null)
SrArchData.CantBe = Regs.Copy();
else SrArchData.CantBe.SetUsed(Regs);
}
}
}
}
return true;
}
private CastExpressionNode CreateSizeChangerNode(ExpressionNode Ch, int NewSize,
x86DataCalcPos DataCalcPos = x86DataCalcPos.GRegMem)
{
var NewType = Container.GetType(Ch.Type.GetType(), NewSize);
var nNode = new CastExpressionNode(NewType, Ch, Ch.Code);
var Data = new x86NodeData();
nNode.ArchData = Data;
Data.DataCalcPos = DataCalcPos;
var ChData = Ch.ArchData as x86NodeData;
Data.Index = ChData.Index == -1 ? 0 : ChData.Index;
if (!PostProcNode(nNode)) return null;
return nNode;
}
private ExpressionNode CreateMoveNode(ExpressionNode n, int RegId,
x86DataCalcPos DataCalcPos = x86DataCalcPos.GRegMem, bool ModCastNode = true)
{
if (n is CastExpressionNode && ModCastNode)
{
var Data = n.ArchData as x86NodeData;
Data.Index = RegId;
Data.DataCalcPos &= DataCalcPos;
}
else
{
n = new CastExpressionNode(n.Type, n, n.Code);
var Data = new x86NodeData();
n.ArchData = Data;
Data.Index = RegId;
Data.DataCalcPos = DataCalcPos;
if (!PostProcNode(n)) return null;
}
return n;
}
bool NeedLoadRId(ExpressionNode Node)
{
var RId = Node as IdExpressionNode;
if (RId == null) return false;
var Type = RId.Type;
if (!(Type is FloatType))
throw new Exception("ERROR");
var S = Type.Size;
return S != 4 && S != 8;
}
ExpressionNode AdjustConstFltNode(ConstExpressionNode Node)
{
if (Node is ConstExpressionNode && Node.Type is FloatType)
{
var Val = Node.Double;
if (Val != 0.0 && Val != 1.0 && Val != Math.PI)
return Container.GlobalScope.CreateConstRId(Node, Root);
else return CreateMoveNode(Node, -1);
}
return Node;
}
bool AdjustConstFltNode(List<ExpressionNode> Ch)
{
for (var i = 0; i < Ch.Count; i++)
{
var N = Ch[i].RealNode;
if (N is ConstExpressionNode && N.Type is FloatType)
{
N = AdjustConstFltNode(N as ConstExpressionNode);
if (N == null) return false;
Ch[i] = N;
}
}
return true;
}
bool AdjustRegs_Float(OpExpressionNode Node, bool Mod, bool RemoveIntCasts = true)
{
var Ch = Node.Children;
var Data = Node.ArchData as x86NodeData;
var RCh0 = Ch[0].RealNode;
var RCh1 = Ch[1].RealNode;
var Ch0Data = Ch[0].ArchData as x86NodeData;
var Ch1Data = Ch[1].ArchData as x86NodeData;
// -----------------------------------------------------------------------
if (x86Architecture.NeedLoadFloatDst(Ch[0], Mod))
{
RCh0 = CreateMoveNode(Ch[0], -1);
Ch0Data = RCh0.ArchData as x86NodeData;
Ch0Data.FPUItemsOnStack = 1;
Ch[0] = RCh0;
}
if (NeedLoadRId(RCh1))
{
RCh1 = CreateMoveNode(Ch[1], -1);
Ch1Data = RCh1.ArchData as x86NodeData;
Ch1Data.FPUItemsOnStack = 1;
Ch[1] = RCh1;
}
if (RemoveIntCasts)
{
RCh1 = FloatOpIntSrc(Ch[1]);
if (RCh1 == null) return false;
Ch[1] = RCh1;
}
// -----------------------------------------------------------------------
if (Ch1Data.UsedFPUStack >= 8 && Mod)
{
if ((Ch[0] = CreateMoveNode(Ch[0], 0, x86DataCalcPos.Memory)) == null)
return false;
Ch[0].Type = Container.GetType(typeof(FloatType), 8);
Ch0Data = Ch[0].ArchData as x86NodeData;
Ch[1].IncRegs();
}
Data.FPUItemsOnStack = Ch0Data.FPUItemsOnStack + Ch1Data.FPUItemsOnStack;
return true;
}
int AdjustRegs(OpExpressionNode Node, bool Mod)
{
var Ch = Node.Children;
var DstIndex = Node.Reverse ? 1 : 0;
var Dst = Ch[DstIndex];
var Src = Ch[1 - DstIndex];
var DstData = Dst.ArchData as x86NodeData;
var SrArchData = Src.ArchData as x86NodeData;
var NeedMove = (DstData.Index != 0 && Mod) || Dst is ConstExpressionNode;
if (!NeedMove && Dst.SamePosition(Src, false)) NeedMove = true;
if (NeedMove)
{
Ch[DstIndex] = Dst = CreateMoveNode(Ch[DstIndex], 0);
DstData = Dst.ArchData as x86NodeData;
}
if (SrArchData != null && SrArchData.Index != -1 && SrArchData.Index == DstData.Index)
Src.IncRegs();
return Mod ? 0 : -1;
}
private static bool NeedSwap(List<ExpressionNode> Ch)
{
if (Ch[0].Type is FloatType)
return Ch[1] is OpExpressionNode && !(Ch[0] is OpExpressionNode);
var A = Ch[0].RealNode;
var B = Ch[1].RealNode;
var AIndex = (A.ArchData as x86NodeData).Index;
var BIndex = (B.ArchData as x86NodeData).Index;
return AIndex == -1 && BIndex != -1;
}
private ExpressionNode FloatOpIntSrc(ExpressionNode Node)
{
var CastNode = Node as CastExpressionNode;
if (CastNode == null) return Node;
var Size = CastNode.Child.Type.Size;
if (Size != 2 && Size != 4) return Node;
return CastNode.Child;
}
private ExpressionNode MulBy(ExpressionNode N, long Num)
{
var Four = Root.NewNode(new ConstExpressionNode(N.Type, Num, N.Code));
var NCh = new List<ExpressionNode>() { N, Four };
return Root.NewNode(new OpExpressionNode(Operator.Multiply, NCh, N.Code));
}
}
}