Start of JIT garbage collection improvements
- thread static pool for Operand, MemoryOperand, Operation - Operands and Operations are always to be constructed via their static helper classes, so they can be pooled. - removing LinkedList from Node for sources/destinations (replaced with List<>s for now, but probably could do arrays since size is bounded) - removing params constructors from Node - LinkedList<> to List<> with Clear() for Operand assignments/uses - ThreadStaticPool is very simple and basically just exists for the purpose of our specific translation allocation problem. Right now it will stay at the worst case allocation count for that thread (so far) - the pool can never shrink. - Still some cases of Operand[] that haven't been removed yet. Will need to evaluate them (eg. is there a reasonable max number of params for Calls?)
This commit is contained in:
parent
08c0e3829b
commit
1413723687
18 changed files with 570 additions and 198 deletions
|
@ -2,6 +2,9 @@ using ARMeilleure.IntermediateRepresentation;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
using static ARMeilleure.IntermediateRepresentation.OperandHelper;
|
||||||
|
using static ARMeilleure.IntermediateRepresentation.OperationHelper;
|
||||||
|
|
||||||
namespace ARMeilleure.CodeGen.RegisterAllocators
|
namespace ARMeilleure.CodeGen.RegisterAllocators
|
||||||
{
|
{
|
||||||
class CopyResolver
|
class CopyResolver
|
||||||
|
@ -133,14 +136,14 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
||||||
|
|
||||||
private static void EmitCopy(List<Operation> sequence, Operand x, Operand y)
|
private static void EmitCopy(List<Operation> sequence, Operand x, Operand y)
|
||||||
{
|
{
|
||||||
sequence.Add(new Operation(Instruction.Copy, x, y));
|
sequence.Add(Operation(Instruction.Copy, x, y));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void EmitXorSwap(List<Operation> sequence, Operand x, Operand y)
|
private static void EmitXorSwap(List<Operation> sequence, Operand x, Operand y)
|
||||||
{
|
{
|
||||||
sequence.Add(new Operation(Instruction.BitwiseExclusiveOr, x, x, y));
|
sequence.Add(Operation(Instruction.BitwiseExclusiveOr, x, x, y));
|
||||||
sequence.Add(new Operation(Instruction.BitwiseExclusiveOr, y, y, x));
|
sequence.Add(Operation(Instruction.BitwiseExclusiveOr, y, y, x));
|
||||||
sequence.Add(new Operation(Instruction.BitwiseExclusiveOr, x, x, y));
|
sequence.Add(Operation(Instruction.BitwiseExclusiveOr, x, x, y));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -194,20 +197,20 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
||||||
{
|
{
|
||||||
Operand register = GetRegister(right.Register, type);
|
Operand register = GetRegister(right.Register, type);
|
||||||
|
|
||||||
Operand offset = new Operand(left.SpillOffset);
|
Operand offset = Const(left.SpillOffset);
|
||||||
|
|
||||||
_fillQueue.Enqueue(new Operation(Instruction.Fill, register, offset));
|
_fillQueue.Enqueue(Operation(Instruction.Fill, register, offset));
|
||||||
|
|
||||||
HasCopy = true;
|
HasCopy = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AddSplitSpill(LiveInterval left, LiveInterval right, OperandType type)
|
private void AddSplitSpill(LiveInterval left, LiveInterval right, OperandType type)
|
||||||
{
|
{
|
||||||
Operand offset = new Operand(right.SpillOffset);
|
Operand offset = Const(right.SpillOffset);
|
||||||
|
|
||||||
Operand register = GetRegister(left.Register, type);
|
Operand register = GetRegister(left.Register, type);
|
||||||
|
|
||||||
_spillQueue.Enqueue(new Operation(Instruction.Spill, null, offset, register));
|
_spillQueue.Enqueue(Operation(Instruction.Spill, null, offset, register));
|
||||||
|
|
||||||
HasCopy = true;
|
HasCopy = true;
|
||||||
}
|
}
|
||||||
|
@ -240,7 +243,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
||||||
|
|
||||||
private static Operand GetRegister(Register reg, OperandType type)
|
private static Operand GetRegister(Register reg, OperandType type)
|
||||||
{
|
{
|
||||||
return new Operand(reg.Index, reg.Type, type);
|
return Register(reg.Index, reg.Type, type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -5,6 +5,7 @@ using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
|
||||||
using static ARMeilleure.IntermediateRepresentation.OperandHelper;
|
using static ARMeilleure.IntermediateRepresentation.OperandHelper;
|
||||||
|
using static ARMeilleure.IntermediateRepresentation.OperationHelper;
|
||||||
|
|
||||||
namespace ARMeilleure.CodeGen.RegisterAllocators
|
namespace ARMeilleure.CodeGen.RegisterAllocators
|
||||||
{
|
{
|
||||||
|
@ -265,7 +266,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
||||||
node.SetSource(srcIndex, temp);
|
node.SetSource(srcIndex, temp);
|
||||||
}
|
}
|
||||||
|
|
||||||
Operation fillOp = new Operation(Instruction.Fill, temp, Const(info.SpillOffset));
|
Operation fillOp = Operation(Instruction.Fill, temp, Const(info.SpillOffset));
|
||||||
|
|
||||||
block.Operations.AddBefore(node, fillOp);
|
block.Operations.AddBefore(node, fillOp);
|
||||||
}
|
}
|
||||||
|
@ -363,7 +364,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
||||||
|
|
||||||
node.SetDestination(dstIndex, temp);
|
node.SetDestination(dstIndex, temp);
|
||||||
|
|
||||||
Operation spillOp = new Operation(Instruction.Spill, null, Const(info.SpillOffset), temp);
|
Operation spillOp = Operation(Instruction.Spill, null, Const(info.SpillOffset), temp);
|
||||||
|
|
||||||
block.Operations.AddAfter(node, spillOp);
|
block.Operations.AddAfter(node, spillOp);
|
||||||
|
|
||||||
|
|
|
@ -743,7 +743,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
||||||
{
|
{
|
||||||
Debug.Assert(!interval.IsSpilled, "Spilled intervals are not allowed.");
|
Debug.Assert(!interval.IsSpilled, "Spilled intervals are not allowed.");
|
||||||
|
|
||||||
return new Operand(
|
return OperandHelper.Register(
|
||||||
interval.Register.Index,
|
interval.Register.Index,
|
||||||
interval.Register.Type,
|
interval.Register.Type,
|
||||||
interval.Local.Type);
|
interval.Local.Type);
|
||||||
|
|
|
@ -10,6 +10,8 @@ using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
|
||||||
|
using static ARMeilleure.IntermediateRepresentation.OperandHelper;
|
||||||
|
|
||||||
namespace ARMeilleure.CodeGen.X86
|
namespace ARMeilleure.CodeGen.X86
|
||||||
{
|
{
|
||||||
static class CodeGenerator
|
static class CodeGenerator
|
||||||
|
@ -547,7 +549,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
{
|
{
|
||||||
Operand source = operation.GetSource(0);
|
Operand source = operation.GetSource(0);
|
||||||
|
|
||||||
MemoryOperand memOp = new MemoryOperand(OperandType.I64, source);
|
MemoryOperand memOp = MemoryOp(OperandType.I64, source);
|
||||||
|
|
||||||
context.Assembler.Cmpxchg16b(memOp);
|
context.Assembler.Cmpxchg16b(memOp);
|
||||||
}
|
}
|
||||||
|
@ -736,7 +738,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
// operand size constant to the destination register.
|
// operand size constant to the destination register.
|
||||||
context.JumpToNear(X86Condition.NotEqual);
|
context.JumpToNear(X86Condition.NotEqual);
|
||||||
|
|
||||||
context.Assembler.Mov(dest, new Operand(operandSize | operandMask), OperandType.I32);
|
context.Assembler.Mov(dest, Const(operandSize | operandMask), OperandType.I32);
|
||||||
|
|
||||||
context.JumpHere();
|
context.JumpHere();
|
||||||
|
|
||||||
|
@ -744,7 +746,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
// starting from the least significant bit. However we are supposed to
|
// starting from the least significant bit. However we are supposed to
|
||||||
// return the number of 0 bits on the high end. So, we invert the result
|
// return the number of 0 bits on the high end. So, we invert the result
|
||||||
// of the BSR using XOR to get the correct value.
|
// of the BSR using XOR to get the correct value.
|
||||||
context.Assembler.Xor(dest, new Operand(operandMask), OperandType.I32);
|
context.Assembler.Xor(dest, Const(operandMask), OperandType.I32);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void GenerateCpuId(CodeGenContext context, Operation operation)
|
private static void GenerateCpuId(CodeGenContext context, Operation operation)
|
||||||
|
@ -813,7 +815,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
|
|
||||||
Operand rsp = Register(X86Register.Rsp);
|
Operand rsp = Register(X86Register.Rsp);
|
||||||
|
|
||||||
MemoryOperand memOp = new MemoryOperand(dest.Type, rsp, null, Multiplier.x1, offs);
|
MemoryOperand memOp = MemoryOp(dest.Type, rsp, null, Multiplier.x1, offs);
|
||||||
|
|
||||||
GenerateLoad(context, memOp, dest);
|
GenerateLoad(context, memOp, dest);
|
||||||
}
|
}
|
||||||
|
@ -1012,7 +1014,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
|
|
||||||
Operand rsp = Register(X86Register.Rsp);
|
Operand rsp = Register(X86Register.Rsp);
|
||||||
|
|
||||||
MemoryOperand memOp = new MemoryOperand(source.Type, rsp, null, Multiplier.x1, offs);
|
MemoryOperand memOp = MemoryOp(source.Type, rsp, null, Multiplier.x1, offs);
|
||||||
|
|
||||||
GenerateStore(context, memOp, source);
|
GenerateStore(context, memOp, source);
|
||||||
}
|
}
|
||||||
|
@ -1028,7 +1030,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
|
|
||||||
Operand rsp = Register(X86Register.Rsp);
|
Operand rsp = Register(X86Register.Rsp);
|
||||||
|
|
||||||
MemoryOperand memOp = new MemoryOperand(OperandType.I64, rsp, null, Multiplier.x1, offs);
|
MemoryOperand memOp = MemoryOp(OperandType.I64, rsp, null, Multiplier.x1, offs);
|
||||||
|
|
||||||
context.Assembler.Lea(dest, memOp, OperandType.I64);
|
context.Assembler.Lea(dest, memOp, OperandType.I64);
|
||||||
}
|
}
|
||||||
|
@ -1225,7 +1227,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
|
|
||||||
if ((index & 1) != 0)
|
if ((index & 1) != 0)
|
||||||
{
|
{
|
||||||
context.Assembler.Shr(dest, new Operand(8), OperandType.I32);
|
context.Assembler.Shr(dest, Const(8), OperandType.I32);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1264,7 +1266,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
context.Assembler.Pinsrw(dest, dest, src2, (byte)(index * words + word));
|
context.Assembler.Pinsrw(dest, dest, src2, (byte)(index * words + word));
|
||||||
|
|
||||||
// Move next word down.
|
// Move next word down.
|
||||||
context.Assembler.Ror(src2, new Operand(16), src2.Type);
|
context.Assembler.Ror(src2, Const(16), src2.Type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1592,7 +1594,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
|
|
||||||
if (reservedStackSize != 0)
|
if (reservedStackSize != 0)
|
||||||
{
|
{
|
||||||
context.Assembler.Sub(rsp, new Operand(reservedStackSize), OperandType.I64);
|
context.Assembler.Sub(rsp, Const(reservedStackSize), OperandType.I64);
|
||||||
}
|
}
|
||||||
|
|
||||||
int offset = reservedStackSize;
|
int offset = reservedStackSize;
|
||||||
|
@ -1605,7 +1607,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
|
|
||||||
offset -= 16;
|
offset -= 16;
|
||||||
|
|
||||||
MemoryOperand memOp = new MemoryOperand(OperandType.V128, rsp, null, Multiplier.x1, offset);
|
MemoryOperand memOp = MemoryOp(OperandType.V128, rsp, null, Multiplier.x1, offset);
|
||||||
|
|
||||||
context.Assembler.Movdqu(memOp, Xmm((X86Register)bit));
|
context.Assembler.Movdqu(memOp, Xmm((X86Register)bit));
|
||||||
|
|
||||||
|
@ -1635,7 +1637,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
|
|
||||||
offset -= 16;
|
offset -= 16;
|
||||||
|
|
||||||
MemoryOperand memOp = new MemoryOperand(OperandType.V128, rsp, null, Multiplier.x1, offset);
|
MemoryOperand memOp = MemoryOp(OperandType.V128, rsp, null, Multiplier.x1, offset);
|
||||||
|
|
||||||
context.Assembler.Movdqu(Xmm((X86Register)bit), memOp);
|
context.Assembler.Movdqu(Xmm((X86Register)bit), memOp);
|
||||||
|
|
||||||
|
@ -1644,7 +1646,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
|
|
||||||
if (reservedStackSize != 0)
|
if (reservedStackSize != 0)
|
||||||
{
|
{
|
||||||
context.Assembler.Add(rsp, new Operand(reservedStackSize), OperandType.I64);
|
context.Assembler.Add(rsp, Const(reservedStackSize), OperandType.I64);
|
||||||
}
|
}
|
||||||
|
|
||||||
mask = CallingConvention.GetIntCalleeSavedRegisters() & context.AllocResult.IntUsedRegisters;
|
mask = CallingConvention.GetIntCalleeSavedRegisters() & context.AllocResult.IntUsedRegisters;
|
||||||
|
@ -1676,7 +1678,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
|
|
||||||
for (int offset = PageSize; offset < size; offset += PageSize)
|
for (int offset = PageSize; offset < size; offset += PageSize)
|
||||||
{
|
{
|
||||||
Operand memOp = new MemoryOperand(OperandType.I32, rsp, null, Multiplier.x1, -offset);
|
Operand memOp = MemoryOp(OperandType.I32, rsp, null, Multiplier.x1, -offset);
|
||||||
|
|
||||||
context.Assembler.Mov(temp, memOp, OperandType.I32);
|
context.Assembler.Mov(temp, memOp, OperandType.I32);
|
||||||
}
|
}
|
||||||
|
@ -1689,17 +1691,17 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
return operand as MemoryOperand;
|
return operand as MemoryOperand;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new MemoryOperand(type, operand);
|
return MemoryOp(type, operand);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Operand Register(X86Register register, OperandType type = OperandType.I64)
|
private static Operand Register(X86Register register, OperandType type = OperandType.I64)
|
||||||
{
|
{
|
||||||
return new Operand((int)register, RegisterType.Integer, type);
|
return OperandHelper.Register((int)register, RegisterType.Integer, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Operand Xmm(X86Register register)
|
private static Operand Xmm(X86Register register)
|
||||||
{
|
{
|
||||||
return new Operand((int)register, RegisterType.Vector, OperandType.V128);
|
return OperandHelper.Register((int)register, RegisterType.Vector, OperandType.V128);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,10 +1,12 @@
|
||||||
using ARMeilleure.CodeGen.RegisterAllocators;
|
using ARMeilleure.CodeGen.RegisterAllocators;
|
||||||
using ARMeilleure.IntermediateRepresentation;
|
using ARMeilleure.IntermediateRepresentation;
|
||||||
using ARMeilleure.Translation;
|
using ARMeilleure.Translation;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
|
||||||
using static ARMeilleure.IntermediateRepresentation.OperandHelper;
|
using static ARMeilleure.IntermediateRepresentation.OperandHelper;
|
||||||
|
using static ARMeilleure.IntermediateRepresentation.OperationHelper;
|
||||||
|
|
||||||
namespace ARMeilleure.CodeGen.X86
|
namespace ARMeilleure.CodeGen.X86
|
||||||
{
|
{
|
||||||
|
@ -207,8 +209,8 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
// - The value at the memory location is loaded to RDX:RAX.
|
// - The value at the memory location is loaded to RDX:RAX.
|
||||||
void SplitOperand(Operand source, Operand lr, Operand hr)
|
void SplitOperand(Operand source, Operand lr, Operand hr)
|
||||||
{
|
{
|
||||||
nodes.AddBefore(node, new Operation(Instruction.VectorExtract, lr, source, Const(0)));
|
nodes.AddBefore(node, Operation(Instruction.VectorExtract, lr, source, Const(0)));
|
||||||
nodes.AddBefore(node, new Operation(Instruction.VectorExtract, hr, source, Const(1)));
|
nodes.AddBefore(node, Operation(Instruction.VectorExtract, hr, source, Const(1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
Operand rax = Gpr(X86Register.Rax, OperandType.I64);
|
Operand rax = Gpr(X86Register.Rax, OperandType.I64);
|
||||||
|
@ -219,8 +221,8 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
SplitOperand(operation.GetSource(1), rax, rdx);
|
SplitOperand(operation.GetSource(1), rax, rdx);
|
||||||
SplitOperand(operation.GetSource(2), rbx, rcx);
|
SplitOperand(operation.GetSource(2), rbx, rcx);
|
||||||
|
|
||||||
node = nodes.AddAfter(node, new Operation(Instruction.VectorCreateScalar, dest, rax));
|
node = nodes.AddAfter(node, Operation(Instruction.VectorCreateScalar, dest, rax));
|
||||||
node = nodes.AddAfter(node, new Operation(Instruction.VectorInsert, dest, dest, rdx, Const(1)));
|
node = nodes.AddAfter(node, Operation(Instruction.VectorInsert, dest, dest, rdx, Const(1)));
|
||||||
|
|
||||||
operation.SetDestinations(new Operand[] { rdx, rax });
|
operation.SetDestinations(new Operand[] { rdx, rax });
|
||||||
|
|
||||||
|
@ -243,16 +245,16 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
Operand edx = Gpr(X86Register.Rdx, OperandType.I32);
|
Operand edx = Gpr(X86Register.Rdx, OperandType.I32);
|
||||||
|
|
||||||
// Value 0x01 = Version, family and feature information.
|
// Value 0x01 = Version, family and feature information.
|
||||||
nodes.AddBefore(node, new Operation(Instruction.Copy, eax, Const(1)));
|
nodes.AddBefore(node, Operation(Instruction.Copy, eax, Const(1)));
|
||||||
|
|
||||||
// Copy results to the destination register.
|
// Copy results to the destination register.
|
||||||
// The values are split into 2 32-bits registers, we merge them
|
// The values are split into 2 32-bits registers, we merge them
|
||||||
// into a single 64-bits register.
|
// into a single 64-bits register.
|
||||||
Operand rcx = Gpr(X86Register.Rcx, OperandType.I64);
|
Operand rcx = Gpr(X86Register.Rcx, OperandType.I64);
|
||||||
|
|
||||||
node = nodes.AddAfter(node, new Operation(Instruction.ZeroExtend32, dest, edx));
|
node = nodes.AddAfter(node, Operation(Instruction.ZeroExtend32, dest, edx));
|
||||||
node = nodes.AddAfter(node, new Operation(Instruction.ShiftLeft, dest, dest, Const(32)));
|
node = nodes.AddAfter(node, Operation(Instruction.ShiftLeft, dest, dest, Const(32)));
|
||||||
node = nodes.AddAfter(node, new Operation(Instruction.BitwiseOr, dest, dest, rcx));
|
node = nodes.AddAfter(node, Operation(Instruction.BitwiseOr, dest, dest, rcx));
|
||||||
|
|
||||||
operation.SetDestinations(new Operand[] { eax, ebx, ecx, edx });
|
operation.SetDestinations(new Operand[] { eax, ebx, ecx, edx });
|
||||||
|
|
||||||
|
@ -275,10 +277,10 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
Operand rax = Gpr(X86Register.Rax, src1.Type);
|
Operand rax = Gpr(X86Register.Rax, src1.Type);
|
||||||
Operand rdx = Gpr(X86Register.Rdx, src1.Type);
|
Operand rdx = Gpr(X86Register.Rdx, src1.Type);
|
||||||
|
|
||||||
nodes.AddBefore(node, new Operation(Instruction.Copy, rax, src1));
|
nodes.AddBefore(node, Operation(Instruction.Copy, rax, src1));
|
||||||
nodes.AddBefore(node, new Operation(Instruction.Clobber, rdx));
|
nodes.AddBefore(node, Operation(Instruction.Clobber, rdx));
|
||||||
|
|
||||||
node = nodes.AddAfter(node, new Operation(Instruction.Copy, dest, rax));
|
node = nodes.AddAfter(node, Operation(Instruction.Copy, dest, rax));
|
||||||
|
|
||||||
operation.SetDestinations(new Operand[] { rdx, rax });
|
operation.SetDestinations(new Operand[] { rdx, rax });
|
||||||
|
|
||||||
|
@ -302,7 +304,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
{
|
{
|
||||||
Operand xmm0 = Xmm(X86Register.Xmm0, OperandType.V128);
|
Operand xmm0 = Xmm(X86Register.Xmm0, OperandType.V128);
|
||||||
|
|
||||||
nodes.AddBefore(node, new Operation(Instruction.Copy, xmm0, operation.GetSource(2)));
|
nodes.AddBefore(node, Operation(Instruction.Copy, xmm0, operation.GetSource(2)));
|
||||||
|
|
||||||
operation.SetSource(2, xmm0);
|
operation.SetSource(2, xmm0);
|
||||||
}
|
}
|
||||||
|
@ -322,11 +324,11 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
Operand rax = Gpr(X86Register.Rax, src1.Type);
|
Operand rax = Gpr(X86Register.Rax, src1.Type);
|
||||||
Operand rdx = Gpr(X86Register.Rdx, src1.Type);
|
Operand rdx = Gpr(X86Register.Rdx, src1.Type);
|
||||||
|
|
||||||
nodes.AddBefore(node, new Operation(Instruction.Copy, rax, src1));
|
nodes.AddBefore(node, Operation(Instruction.Copy, rax, src1));
|
||||||
|
|
||||||
operation.SetSource(0, rax);
|
operation.SetSource(0, rax);
|
||||||
|
|
||||||
node = nodes.AddAfter(node, new Operation(Instruction.Copy, dest, rdx));
|
node = nodes.AddAfter(node, Operation(Instruction.Copy, dest, rdx));
|
||||||
|
|
||||||
operation.SetDestinations(new Operand[] { rdx, rax });
|
operation.SetDestinations(new Operand[] { rdx, rax });
|
||||||
|
|
||||||
|
@ -343,7 +345,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
{
|
{
|
||||||
Operand rcx = Gpr(X86Register.Rcx, OperandType.I32);
|
Operand rcx = Gpr(X86Register.Rcx, OperandType.I32);
|
||||||
|
|
||||||
nodes.AddBefore(node, new Operation(Instruction.Copy, rcx, operation.GetSource(1)));
|
nodes.AddBefore(node, Operation(Instruction.Copy, rcx, operation.GetSource(1)));
|
||||||
|
|
||||||
operation.SetSource(1, rcx);
|
operation.SetSource(1, rcx);
|
||||||
}
|
}
|
||||||
|
@ -392,17 +394,17 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
// local would be overwritten.
|
// local would be overwritten.
|
||||||
Operand temp = Local(dest.Type);
|
Operand temp = Local(dest.Type);
|
||||||
|
|
||||||
nodes.AddBefore(node, new Operation(Instruction.Copy, temp, src1));
|
nodes.AddBefore(node, Operation(Instruction.Copy, temp, src1));
|
||||||
|
|
||||||
operation.SetSource(0, temp);
|
operation.SetSource(0, temp);
|
||||||
|
|
||||||
node = nodes.AddAfter(node, new Operation(Instruction.Copy, dest, temp));
|
node = nodes.AddAfter(node, Operation(Instruction.Copy, dest, temp));
|
||||||
|
|
||||||
operation.Destination = temp;
|
operation.Destination = temp;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
nodes.AddBefore(node, new Operation(Instruction.Copy, dest, src1));
|
nodes.AddBefore(node, Operation(Instruction.Copy, dest, src1));
|
||||||
|
|
||||||
operation.SetSource(0, dest);
|
operation.SetSource(0, dest);
|
||||||
}
|
}
|
||||||
|
@ -416,17 +418,17 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
{
|
{
|
||||||
Operand temp = Local(dest.Type);
|
Operand temp = Local(dest.Type);
|
||||||
|
|
||||||
nodes.AddBefore(node, new Operation(Instruction.Copy, temp, src3));
|
nodes.AddBefore(node, Operation(Instruction.Copy, temp, src3));
|
||||||
|
|
||||||
operation.SetSource(2, temp);
|
operation.SetSource(2, temp);
|
||||||
|
|
||||||
node = nodes.AddAfter(node, new Operation(Instruction.Copy, dest, temp));
|
node = nodes.AddAfter(node, Operation(Instruction.Copy, dest, temp));
|
||||||
|
|
||||||
operation.Destination = temp;
|
operation.Destination = temp;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
nodes.AddBefore(node, new Operation(Instruction.Copy, dest, src3));
|
nodes.AddBefore(node, Operation(Instruction.Copy, dest, src3));
|
||||||
|
|
||||||
operation.SetSource(2, dest);
|
operation.SetSource(2, dest);
|
||||||
}
|
}
|
||||||
|
@ -453,8 +455,8 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
// and then use the 64-bits signed conversion instructions.
|
// and then use the 64-bits signed conversion instructions.
|
||||||
Operand zex = Local(OperandType.I64);
|
Operand zex = Local(OperandType.I64);
|
||||||
|
|
||||||
node = nodes.AddAfter(node, new Operation(Instruction.ZeroExtend32, zex, source));
|
node = nodes.AddAfter(node, Operation(Instruction.ZeroExtend32, zex, source));
|
||||||
node = nodes.AddAfter(node, new Operation(Instruction.ConvertToFP, dest, zex));
|
node = nodes.AddAfter(node, Operation(Instruction.ConvertToFP, dest, zex));
|
||||||
}
|
}
|
||||||
else /* if (source.Type == OperandType.I64) */
|
else /* if (source.Type == OperandType.I64) */
|
||||||
{
|
{
|
||||||
|
@ -473,17 +475,17 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
|
|
||||||
Operand lsbF = Local(dest.Type);
|
Operand lsbF = Local(dest.Type);
|
||||||
|
|
||||||
node = nodes.AddAfter(node, new Operation(Instruction.Copy, lsb, source));
|
node = nodes.AddAfter(node, Operation(Instruction.Copy, lsb, source));
|
||||||
node = nodes.AddAfter(node, new Operation(Instruction.Copy, half, source));
|
node = nodes.AddAfter(node, Operation(Instruction.Copy, half, source));
|
||||||
|
|
||||||
node = nodes.AddAfter(node, new Operation(Instruction.BitwiseAnd, lsb, lsb, Const(1L)));
|
node = nodes.AddAfter(node, Operation(Instruction.BitwiseAnd, lsb, lsb, Const(1L)));
|
||||||
node = nodes.AddAfter(node, new Operation(Instruction.ShiftRightUI, half, half, Const(1)));
|
node = nodes.AddAfter(node, Operation(Instruction.ShiftRightUI, half, half, Const(1)));
|
||||||
|
|
||||||
node = nodes.AddAfter(node, new Operation(Instruction.ConvertToFP, lsbF, lsb));
|
node = nodes.AddAfter(node, Operation(Instruction.ConvertToFP, lsbF, lsb));
|
||||||
node = nodes.AddAfter(node, new Operation(Instruction.ConvertToFP, dest, half));
|
node = nodes.AddAfter(node, Operation(Instruction.ConvertToFP, dest, half));
|
||||||
|
|
||||||
node = nodes.AddAfter(node, new Operation(Instruction.Add, dest, dest, dest));
|
node = nodes.AddAfter(node, Operation(Instruction.Add, dest, dest, dest));
|
||||||
node = nodes.AddAfter(node, new Operation(Instruction.Add, dest, dest, lsbF));
|
node = nodes.AddAfter(node, Operation(Instruction.Add, dest, dest, lsbF));
|
||||||
}
|
}
|
||||||
|
|
||||||
Delete(nodes, currentNode, operation);
|
Delete(nodes, currentNode, operation);
|
||||||
|
@ -506,7 +508,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
|
|
||||||
Operand res = Local(dest.Type);
|
Operand res = Local(dest.Type);
|
||||||
|
|
||||||
node = nodes.AddAfter(node, new Operation(Instruction.VectorOne, res));
|
node = nodes.AddAfter(node, Operation(Instruction.VectorOne, res));
|
||||||
|
|
||||||
if (dest.Type == OperandType.FP32)
|
if (dest.Type == OperandType.FP32)
|
||||||
{
|
{
|
||||||
|
@ -519,7 +521,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
|
|
||||||
node = nodes.AddAfter(node, new IntrinsicOperation(Intrinsic.X86Xorps, res, res, source));
|
node = nodes.AddAfter(node, new IntrinsicOperation(Intrinsic.X86Xorps, res, res, source));
|
||||||
|
|
||||||
node = nodes.AddAfter(node, new Operation(Instruction.Copy, dest, res));
|
node = nodes.AddAfter(node, Operation(Instruction.Copy, dest, res));
|
||||||
|
|
||||||
Delete(nodes, currentNode, operation);
|
Delete(nodes, currentNode, operation);
|
||||||
|
|
||||||
|
@ -545,26 +547,26 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
Operand temp1 = Local(OperandType.I32);
|
Operand temp1 = Local(OperandType.I32);
|
||||||
Operand temp2 = Local(OperandType.I32);
|
Operand temp2 = Local(OperandType.I32);
|
||||||
|
|
||||||
node = nodes.AddAfter(node, new Operation(Instruction.Copy, temp2, src2));
|
node = nodes.AddAfter(node, Operation(Instruction.Copy, temp2, src2));
|
||||||
|
|
||||||
Operation vextOp = new Operation(Instruction.VectorExtract16, temp1, src1, Const(index >> 1));
|
Operation vextOp = Operation(Instruction.VectorExtract16, temp1, src1, Const(index >> 1));
|
||||||
|
|
||||||
node = nodes.AddAfter(node, vextOp);
|
node = nodes.AddAfter(node, vextOp);
|
||||||
|
|
||||||
if ((index & 1) != 0)
|
if ((index & 1) != 0)
|
||||||
{
|
{
|
||||||
node = nodes.AddAfter(node, new Operation(Instruction.ZeroExtend8, temp1, temp1));
|
node = nodes.AddAfter(node, Operation(Instruction.ZeroExtend8, temp1, temp1));
|
||||||
node = nodes.AddAfter(node, new Operation(Instruction.ShiftLeft, temp2, temp2, Const(8)));
|
node = nodes.AddAfter(node, Operation(Instruction.ShiftLeft, temp2, temp2, Const(8)));
|
||||||
node = nodes.AddAfter(node, new Operation(Instruction.BitwiseOr, temp1, temp1, temp2));
|
node = nodes.AddAfter(node, Operation(Instruction.BitwiseOr, temp1, temp1, temp2));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
node = nodes.AddAfter(node, new Operation(Instruction.ZeroExtend8, temp2, temp2));
|
node = nodes.AddAfter(node, Operation(Instruction.ZeroExtend8, temp2, temp2));
|
||||||
node = nodes.AddAfter(node, new Operation(Instruction.BitwiseAnd, temp1, temp1, Const(0xff00)));
|
node = nodes.AddAfter(node, Operation(Instruction.BitwiseAnd, temp1, temp1, Const(0xff00)));
|
||||||
node = nodes.AddAfter(node, new Operation(Instruction.BitwiseOr, temp1, temp1, temp2));
|
node = nodes.AddAfter(node, Operation(Instruction.BitwiseOr, temp1, temp1, temp2));
|
||||||
}
|
}
|
||||||
|
|
||||||
Operation vinsOp = new Operation(Instruction.VectorInsert16, dest, src1, temp1, Const(index >> 1));
|
Operation vinsOp = Operation(Instruction.VectorInsert16, dest, src1, temp1, Const(index >> 1));
|
||||||
|
|
||||||
node = nodes.AddAfter(node, vinsOp);
|
node = nodes.AddAfter(node, vinsOp);
|
||||||
|
|
||||||
|
@ -608,7 +610,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
|
|
||||||
arg0Reg = Gpr(CallingConvention.GetIntArgumentRegister(0), OperandType.I64);
|
arg0Reg = Gpr(CallingConvention.GetIntArgumentRegister(0), OperandType.I64);
|
||||||
|
|
||||||
Operation allocOp = new Operation(Instruction.StackAlloc, arg0Reg, Const(stackOffset));
|
Operation allocOp = Operation(Instruction.StackAlloc, arg0Reg, Const(stackOffset));
|
||||||
|
|
||||||
nodes.AddBefore(node, allocOp);
|
nodes.AddBefore(node, allocOp);
|
||||||
|
|
||||||
|
@ -643,9 +645,9 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
|
|
||||||
int stackOffset = AllocateOnStack(source.Type.GetSizeInBytes());
|
int stackOffset = AllocateOnStack(source.Type.GetSizeInBytes());
|
||||||
|
|
||||||
nodes.AddBefore(node, new Operation(Instruction.StackAlloc, stackAddr, Const(stackOffset)));
|
nodes.AddBefore(node, Operation(Instruction.StackAlloc, stackAddr, Const(stackOffset)));
|
||||||
|
|
||||||
Operation storeOp = new Operation(Instruction.Store, null, stackAddr, source);
|
Operation storeOp = Operation(Instruction.Store, null, stackAddr, source);
|
||||||
|
|
||||||
HandleConstantCopy(nodes, nodes.AddBefore(node, storeOp), storeOp);
|
HandleConstantCopy(nodes, nodes.AddBefore(node, storeOp), storeOp);
|
||||||
|
|
||||||
|
@ -671,7 +673,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
argReg = Xmm(CallingConvention.GetVecArgumentRegister(argIndex), source.Type);
|
argReg = Xmm(CallingConvention.GetVecArgumentRegister(argIndex), source.Type);
|
||||||
}
|
}
|
||||||
|
|
||||||
Operation copyOp = new Operation(Instruction.Copy, argReg, source);
|
Operation copyOp = Operation(Instruction.Copy, argReg, source);
|
||||||
|
|
||||||
HandleConstantCopy(nodes, nodes.AddBefore(node, copyOp), copyOp);
|
HandleConstantCopy(nodes, nodes.AddBefore(node, copyOp), copyOp);
|
||||||
|
|
||||||
|
@ -684,9 +686,9 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
{
|
{
|
||||||
Operand source = operation.GetSource(index + 1);
|
Operand source = operation.GetSource(index + 1);
|
||||||
|
|
||||||
Operand offset = new Operand((index + retArgs) * 8);
|
Operand offset = Const((index + retArgs) * 8);
|
||||||
|
|
||||||
Operation spillOp = new Operation(Instruction.SpillArg, null, offset, source);
|
Operation spillOp = Operation(Instruction.SpillArg, null, offset, source);
|
||||||
|
|
||||||
HandleConstantCopy(nodes, nodes.AddBefore(node, spillOp), spillOp);
|
HandleConstantCopy(nodes, nodes.AddBefore(node, spillOp), spillOp);
|
||||||
}
|
}
|
||||||
|
@ -697,9 +699,9 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
{
|
{
|
||||||
Operand retValueAddr = Local(OperandType.I64);
|
Operand retValueAddr = Local(OperandType.I64);
|
||||||
|
|
||||||
nodes.AddBefore(node, new Operation(Instruction.Copy, retValueAddr, arg0Reg));
|
nodes.AddBefore(node, Operation(Instruction.Copy, retValueAddr, arg0Reg));
|
||||||
|
|
||||||
Operation loadOp = new Operation(Instruction.Load, dest, retValueAddr);
|
Operation loadOp = Operation(Instruction.Load, dest, retValueAddr);
|
||||||
|
|
||||||
node = nodes.AddAfter(node, loadOp);
|
node = nodes.AddAfter(node, loadOp);
|
||||||
|
|
||||||
|
@ -711,7 +713,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
? Gpr(CallingConvention.GetIntReturnRegister(), dest.Type)
|
? Gpr(CallingConvention.GetIntReturnRegister(), dest.Type)
|
||||||
: Xmm(CallingConvention.GetVecReturnRegister(), dest.Type);
|
: Xmm(CallingConvention.GetVecReturnRegister(), dest.Type);
|
||||||
|
|
||||||
Operation copyOp = new Operation(Instruction.Copy, dest, retReg);
|
Operation copyOp = Operation(Instruction.Copy, dest, retReg);
|
||||||
|
|
||||||
node = nodes.AddAfter(node, copyOp);
|
node = nodes.AddAfter(node, copyOp);
|
||||||
|
|
||||||
|
@ -768,8 +770,8 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
Operand argReg = Gpr(CallingConvention.GetIntArgumentRegister(intCount++), OperandType.I64);
|
Operand argReg = Gpr(CallingConvention.GetIntArgumentRegister(intCount++), OperandType.I64);
|
||||||
Operand argReg2 = Gpr(CallingConvention.GetIntArgumentRegister(intCount++), OperandType.I64);
|
Operand argReg2 = Gpr(CallingConvention.GetIntArgumentRegister(intCount++), OperandType.I64);
|
||||||
|
|
||||||
nodes.AddBefore(node, new Operation(Instruction.VectorExtract, argReg, source, Const(0)));
|
nodes.AddBefore(node, Operation(Instruction.VectorExtract, argReg, source, Const(0)));
|
||||||
nodes.AddBefore(node, new Operation(Instruction.VectorExtract, argReg2, source, Const(1)));
|
nodes.AddBefore(node, Operation(Instruction.VectorExtract, argReg2, source, Const(1)));
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -780,7 +782,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
? Gpr(CallingConvention.GetIntArgumentRegister(intCount++), source.Type)
|
? Gpr(CallingConvention.GetIntArgumentRegister(intCount++), source.Type)
|
||||||
: Xmm(CallingConvention.GetVecArgumentRegister(vecCount++), source.Type);
|
: Xmm(CallingConvention.GetVecArgumentRegister(vecCount++), source.Type);
|
||||||
|
|
||||||
Operation copyOp = new Operation(Instruction.Copy, argReg, source);
|
Operation copyOp = Operation(Instruction.Copy, argReg, source);
|
||||||
|
|
||||||
HandleConstantCopy(nodes, nodes.AddBefore(node, copyOp), copyOp);
|
HandleConstantCopy(nodes, nodes.AddBefore(node, copyOp), copyOp);
|
||||||
|
|
||||||
|
@ -788,9 +790,9 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Operand offset = new Operand(stackOffset);
|
Operand offset = Const(stackOffset);
|
||||||
|
|
||||||
Operation spillOp = new Operation(Instruction.SpillArg, null, offset, source);
|
Operation spillOp = Operation(Instruction.SpillArg, null, offset, source);
|
||||||
|
|
||||||
HandleConstantCopy(nodes, nodes.AddBefore(node, spillOp), spillOp);
|
HandleConstantCopy(nodes, nodes.AddBefore(node, spillOp), spillOp);
|
||||||
|
|
||||||
|
@ -805,8 +807,8 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
Operand retLReg = Gpr(CallingConvention.GetIntReturnRegister(), OperandType.I64);
|
Operand retLReg = Gpr(CallingConvention.GetIntReturnRegister(), OperandType.I64);
|
||||||
Operand retHReg = Gpr(CallingConvention.GetIntReturnRegisterHigh(), OperandType.I64);
|
Operand retHReg = Gpr(CallingConvention.GetIntReturnRegisterHigh(), OperandType.I64);
|
||||||
|
|
||||||
node = nodes.AddAfter(node, new Operation(Instruction.VectorCreateScalar, dest, retLReg));
|
node = nodes.AddAfter(node, Operation(Instruction.VectorCreateScalar, dest, retLReg));
|
||||||
node = nodes.AddAfter(node, new Operation(Instruction.VectorInsert, dest, dest, retHReg, Const(1)));
|
node = nodes.AddAfter(node, Operation(Instruction.VectorInsert, dest, dest, retHReg, Const(1)));
|
||||||
|
|
||||||
operation.Destination = null;
|
operation.Destination = null;
|
||||||
}
|
}
|
||||||
|
@ -816,7 +818,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
? Gpr(CallingConvention.GetIntReturnRegister(), dest.Type)
|
? Gpr(CallingConvention.GetIntReturnRegister(), dest.Type)
|
||||||
: Xmm(CallingConvention.GetVecReturnRegister(), dest.Type);
|
: Xmm(CallingConvention.GetVecReturnRegister(), dest.Type);
|
||||||
|
|
||||||
Operation copyOp = new Operation(Instruction.Copy, dest, retReg);
|
Operation copyOp = Operation(Instruction.Copy, dest, retReg);
|
||||||
|
|
||||||
node = nodes.AddAfter(node, copyOp);
|
node = nodes.AddAfter(node, copyOp);
|
||||||
|
|
||||||
|
@ -871,14 +873,14 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
pArg = Local(dest.Type);
|
pArg = Local(dest.Type);
|
||||||
}
|
}
|
||||||
|
|
||||||
Operation copyOp = new Operation(Instruction.Copy, pArg, argReg);
|
Operation copyOp = Operation(Instruction.Copy, pArg, argReg);
|
||||||
|
|
||||||
cctx.Cfg.Entry.Operations.AddFirst(copyOp);
|
cctx.Cfg.Entry.Operations.AddFirst(copyOp);
|
||||||
|
|
||||||
preservedArgs[index] = pArg;
|
preservedArgs[index] = pArg;
|
||||||
}
|
}
|
||||||
|
|
||||||
Operation argCopyOp = new Operation(dest.Type == OperandType.V128
|
Operation argCopyOp = Operation(dest.Type == OperandType.V128
|
||||||
? Instruction.Load
|
? Instruction.Load
|
||||||
: Instruction.Copy, dest, preservedArgs[index]);
|
: Instruction.Copy, dest, preservedArgs[index]);
|
||||||
|
|
||||||
|
@ -955,8 +957,8 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
Operand argLReg = Gpr(CallingConvention.GetIntArgumentRegister(intCount), OperandType.I64);
|
Operand argLReg = Gpr(CallingConvention.GetIntArgumentRegister(intCount), OperandType.I64);
|
||||||
Operand argHReg = Gpr(CallingConvention.GetIntArgumentRegister(intCount + 1), OperandType.I64);
|
Operand argHReg = Gpr(CallingConvention.GetIntArgumentRegister(intCount + 1), OperandType.I64);
|
||||||
|
|
||||||
Operation copyL = new Operation(Instruction.VectorCreateScalar, pArg, argLReg);
|
Operation copyL = Operation(Instruction.VectorCreateScalar, pArg, argLReg);
|
||||||
Operation copyH = new Operation(Instruction.VectorInsert, pArg, pArg, argHReg, Const(1));
|
Operation copyH = Operation(Instruction.VectorInsert, pArg, pArg, argHReg, Const(1));
|
||||||
|
|
||||||
cctx.Cfg.Entry.Operations.AddFirst(copyH);
|
cctx.Cfg.Entry.Operations.AddFirst(copyH);
|
||||||
cctx.Cfg.Entry.Operations.AddFirst(copyL);
|
cctx.Cfg.Entry.Operations.AddFirst(copyL);
|
||||||
|
@ -971,7 +973,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
? Gpr(CallingConvention.GetIntArgumentRegister(intCount), dest.Type)
|
? Gpr(CallingConvention.GetIntArgumentRegister(intCount), dest.Type)
|
||||||
: Xmm(CallingConvention.GetVecArgumentRegister(vecCount), dest.Type);
|
: Xmm(CallingConvention.GetVecArgumentRegister(vecCount), dest.Type);
|
||||||
|
|
||||||
Operation copyOp = new Operation(Instruction.Copy, pArg, argReg);
|
Operation copyOp = Operation(Instruction.Copy, pArg, argReg);
|
||||||
|
|
||||||
cctx.Cfg.Entry.Operations.AddFirst(copyOp);
|
cctx.Cfg.Entry.Operations.AddFirst(copyOp);
|
||||||
|
|
||||||
|
@ -979,7 +981,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Operation argCopyOp = new Operation(Instruction.Copy, dest, preservedArgs[index]);
|
Operation argCopyOp = Operation(Instruction.Copy, dest, preservedArgs[index]);
|
||||||
|
|
||||||
nodes.AddBefore(node, argCopyOp);
|
nodes.AddBefore(node, argCopyOp);
|
||||||
|
|
||||||
|
@ -1019,7 +1021,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
|
|
||||||
Operand arg0 = Gpr(CallingConvention.GetIntArgumentRegister(0), OperandType.I64);
|
Operand arg0 = Gpr(CallingConvention.GetIntArgumentRegister(0), OperandType.I64);
|
||||||
|
|
||||||
Operation copyOp = new Operation(Instruction.Copy, preservedArg, arg0);
|
Operation copyOp = Operation(Instruction.Copy, preservedArg, arg0);
|
||||||
|
|
||||||
cctx.Cfg.Entry.Operations.AddFirst(copyOp);
|
cctx.Cfg.Entry.Operations.AddFirst(copyOp);
|
||||||
|
|
||||||
|
@ -1035,18 +1037,18 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
|
|
||||||
if (source.Type == OperandType.V128)
|
if (source.Type == OperandType.V128)
|
||||||
{
|
{
|
||||||
Operation retStoreOp = new Operation(Instruction.Store, null, retReg, source);
|
Operation retStoreOp = Operation(Instruction.Store, null, retReg, source);
|
||||||
|
|
||||||
nodes.AddBefore(node, retStoreOp);
|
nodes.AddBefore(node, retStoreOp);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Operation retCopyOp = new Operation(Instruction.Copy, retReg, source);
|
Operation retCopyOp = Operation(Instruction.Copy, retReg, source);
|
||||||
|
|
||||||
nodes.AddBefore(node, retCopyOp);
|
nodes.AddBefore(node, retCopyOp);
|
||||||
}
|
}
|
||||||
|
|
||||||
operation.SetSources(System.Array.Empty<Operand>());
|
operation.SetSources(Array.Empty<Operand>());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void HandleReturnSystemVAbi(IntrusiveList<Node> nodes, Node node, Operation operation)
|
private static void HandleReturnSystemVAbi(IntrusiveList<Node> nodes, Node node, Operation operation)
|
||||||
|
@ -1063,8 +1065,8 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
Operand retLReg = Gpr(CallingConvention.GetIntReturnRegister(), OperandType.I64);
|
Operand retLReg = Gpr(CallingConvention.GetIntReturnRegister(), OperandType.I64);
|
||||||
Operand retHReg = Gpr(CallingConvention.GetIntReturnRegisterHigh(), OperandType.I64);
|
Operand retHReg = Gpr(CallingConvention.GetIntReturnRegisterHigh(), OperandType.I64);
|
||||||
|
|
||||||
nodes.AddBefore(node, new Operation(Instruction.VectorExtract, retLReg, source, Const(0)));
|
nodes.AddBefore(node, Operation(Instruction.VectorExtract, retLReg, source, Const(0)));
|
||||||
nodes.AddBefore(node, new Operation(Instruction.VectorExtract, retHReg, source, Const(1)));
|
nodes.AddBefore(node, Operation(Instruction.VectorExtract, retHReg, source, Const(1)));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1072,7 +1074,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
? Gpr(CallingConvention.GetIntReturnRegister(), source.Type)
|
? Gpr(CallingConvention.GetIntReturnRegister(), source.Type)
|
||||||
: Xmm(CallingConvention.GetVecReturnRegister(), source.Type);
|
: Xmm(CallingConvention.GetVecReturnRegister(), source.Type);
|
||||||
|
|
||||||
Operation retCopyOp = new Operation(Instruction.Copy, retReg, source);
|
Operation retCopyOp = Operation(Instruction.Copy, retReg, source);
|
||||||
|
|
||||||
nodes.AddBefore(node, retCopyOp);
|
nodes.AddBefore(node, retCopyOp);
|
||||||
}
|
}
|
||||||
|
@ -1084,7 +1086,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
|
|
||||||
Operand intConst = AddCopy(nodes, node, GetIntConst(source));
|
Operand intConst = AddCopy(nodes, node, GetIntConst(source));
|
||||||
|
|
||||||
Operation copyOp = new Operation(Instruction.VectorCreateScalar, temp, intConst);
|
Operation copyOp = Operation(Instruction.VectorCreateScalar, temp, intConst);
|
||||||
|
|
||||||
nodes.AddBefore(node, copyOp);
|
nodes.AddBefore(node, copyOp);
|
||||||
|
|
||||||
|
@ -1095,7 +1097,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
{
|
{
|
||||||
Operand temp = Local(source.Type);
|
Operand temp = Local(source.Type);
|
||||||
|
|
||||||
Operation copyOp = new Operation(Instruction.Copy, temp, source);
|
Operation copyOp = Operation(Instruction.Copy, temp, source);
|
||||||
|
|
||||||
nodes.AddBefore(node, copyOp);
|
nodes.AddBefore(node, copyOp);
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@ using ARMeilleure.IntermediateRepresentation;
|
||||||
using ARMeilleure.Translation;
|
using ARMeilleure.Translation;
|
||||||
|
|
||||||
using static ARMeilleure.IntermediateRepresentation.OperandHelper;
|
using static ARMeilleure.IntermediateRepresentation.OperandHelper;
|
||||||
|
using static ARMeilleure.IntermediateRepresentation.OperationHelper;
|
||||||
|
|
||||||
namespace ARMeilleure.CodeGen.X86
|
namespace ARMeilleure.CodeGen.X86
|
||||||
{
|
{
|
||||||
|
@ -34,7 +35,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
{
|
{
|
||||||
Operand temp = Local(src1.Type);
|
Operand temp = Local(src1.Type);
|
||||||
|
|
||||||
Operation copyOp = new Operation(Instruction.Copy, temp, src1);
|
Operation copyOp = Operation(Instruction.Copy, temp, src1);
|
||||||
|
|
||||||
block.Operations.AddBefore(operation, copyOp);
|
block.Operations.AddBefore(operation, copyOp);
|
||||||
|
|
||||||
|
@ -45,7 +46,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
{
|
{
|
||||||
Operand temp = Local(src2.Type);
|
Operand temp = Local(src2.Type);
|
||||||
|
|
||||||
Operation copyOp = new Operation(Instruction.Copy, temp, src2);
|
Operation copyOp = Operation(Instruction.Copy, temp, src2);
|
||||||
|
|
||||||
block.Operations.AddBefore(operation, copyOp);
|
block.Operations.AddBefore(operation, copyOp);
|
||||||
|
|
||||||
|
@ -110,7 +111,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new MemoryOperand(type, baseOp, indexOp, scale, imm);
|
return MemoryOp(type, baseOp, indexOp, scale, imm);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int GetConstOp(ref Operand baseOp)
|
private static int GetConstOp(ref Operand baseOp)
|
||||||
|
|
|
@ -5,21 +5,25 @@ namespace ARMeilleure.IntermediateRepresentation
|
||||||
public Operand BaseAddress { get; set; }
|
public Operand BaseAddress { get; set; }
|
||||||
public Operand Index { get; set; }
|
public Operand Index { get; set; }
|
||||||
|
|
||||||
public Multiplier Scale { get; }
|
public Multiplier Scale { get; private set; }
|
||||||
|
|
||||||
public int Displacement { get; }
|
public int Displacement { get; private set; }
|
||||||
|
|
||||||
public MemoryOperand(
|
public MemoryOperand() { }
|
||||||
|
|
||||||
|
public MemoryOperand With(
|
||||||
OperandType type,
|
OperandType type,
|
||||||
Operand baseAddress,
|
Operand baseAddress,
|
||||||
Operand index = null,
|
Operand index = null,
|
||||||
Multiplier scale = Multiplier.x1,
|
Multiplier scale = Multiplier.x1,
|
||||||
int displacement = 0) : base(OperandKind.Memory, type)
|
int displacement = 0)
|
||||||
{
|
{
|
||||||
|
With(OperandKind.Memory, type);
|
||||||
BaseAddress = baseAddress;
|
BaseAddress = baseAddress;
|
||||||
Index = index;
|
Index = index;
|
||||||
Scale = scale;
|
Scale = scale;
|
||||||
Displacement = displacement;
|
Displacement = displacement;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,4 +1,5 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace ARMeilleure.IntermediateRepresentation
|
namespace ARMeilleure.IntermediateRepresentation
|
||||||
{
|
{
|
||||||
|
@ -11,39 +12,78 @@ namespace ARMeilleure.IntermediateRepresentation
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return _destinations.Length != 0 ? GetDestination(0) : null;
|
return _destinations.Count != 0 ? GetDestination(0) : null;
|
||||||
}
|
}
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (value != null)
|
if (value != null)
|
||||||
{
|
{
|
||||||
SetDestinations(new Operand[] { value });
|
SetDestination(value);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SetDestinations(new Operand[0]);
|
_destinations.Clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Operand[] _destinations;
|
private List<Operand> _destinations;
|
||||||
private Operand[] _sources;
|
private List<Operand> _sources;
|
||||||
|
private bool _clearedDest;
|
||||||
|
|
||||||
public int DestinationsCount => _destinations.Length;
|
public int DestinationsCount => _destinations.Count;
|
||||||
public int SourcesCount => _sources.Length;
|
public int SourcesCount => _sources.Count;
|
||||||
|
|
||||||
public Node(Operand destination, int sourcesCount)
|
private void Resize(List<Operand> list, int size)
|
||||||
|
{
|
||||||
|
while (list.Count > size)
|
||||||
|
{
|
||||||
|
list.RemoveAt(list.Count - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (list.Count < size)
|
||||||
|
{
|
||||||
|
list.Add(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Node()
|
||||||
|
{
|
||||||
|
_destinations = new List<Operand>();
|
||||||
|
_sources = new List<Operand>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Node(Operand destination, int sourcesCount) : this()
|
||||||
{
|
{
|
||||||
Destination = destination;
|
Destination = destination;
|
||||||
|
|
||||||
_sources = new Operand[sourcesCount];
|
Resize(_sources, sourcesCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Node(Operand[] destinations, int sourcesCount)
|
private void Reset(int sourcesCount)
|
||||||
{
|
{
|
||||||
|
_clearedDest = true;
|
||||||
|
_sources.Clear();
|
||||||
|
ListPrevious = null;
|
||||||
|
ListNext = null;
|
||||||
|
|
||||||
|
Resize(_sources, sourcesCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Node With(Operand destination, int sourcesCount)
|
||||||
|
{
|
||||||
|
Reset(sourcesCount);
|
||||||
|
Destination = destination;
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Node With(Operand[] destinations, int sourcesCount)
|
||||||
|
{
|
||||||
|
Reset(sourcesCount);
|
||||||
SetDestinations(destinations ?? throw new ArgumentNullException(nameof(destinations)));
|
SetDestinations(destinations ?? throw new ArgumentNullException(nameof(destinations)));
|
||||||
|
|
||||||
_sources = new Operand[sourcesCount];
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Operand GetDestination(int index)
|
public Operand GetDestination(int index)
|
||||||
|
@ -57,11 +97,16 @@ namespace ARMeilleure.IntermediateRepresentation
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetDestination(int index, Operand destination)
|
public void SetDestination(int index, Operand destination)
|
||||||
|
{
|
||||||
|
if (!_clearedDest)
|
||||||
{
|
{
|
||||||
RemoveAssignment(_destinations[index]);
|
RemoveAssignment(_destinations[index]);
|
||||||
|
}
|
||||||
|
|
||||||
AddAssignment(destination);
|
AddAssignment(destination);
|
||||||
|
|
||||||
|
_clearedDest = false;
|
||||||
|
|
||||||
_destinations[index] = destination;
|
_destinations[index] = destination;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,21 +119,37 @@ namespace ARMeilleure.IntermediateRepresentation
|
||||||
_sources[index] = source;
|
_sources[index] = source;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetDestinations(Operand[] destinations)
|
private void RemoveOldDestinations()
|
||||||
{
|
{
|
||||||
if (_destinations != null)
|
if (_destinations != null && !_clearedDest)
|
||||||
{
|
{
|
||||||
for (int index = 0; index < _destinations.Length; index++)
|
for (int index = 0; index < _destinations.Count; index++)
|
||||||
{
|
{
|
||||||
RemoveAssignment(_destinations[index]);
|
RemoveAssignment(_destinations[index]);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
_clearedDest = false;
|
||||||
|
}
|
||||||
|
|
||||||
_destinations = destinations;
|
public void SetDestination(Operand destination)
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
_destinations = new Operand[destinations.Length];
|
RemoveOldDestinations();
|
||||||
|
|
||||||
|
Resize(_destinations, 1);
|
||||||
|
|
||||||
|
_destinations[0] = destination;
|
||||||
|
|
||||||
|
if (destination.Kind == OperandKind.LocalVariable)
|
||||||
|
{
|
||||||
|
destination.Assignments.Add(this);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetDestinations(Operand[] destinations)
|
||||||
|
{
|
||||||
|
RemoveOldDestinations();
|
||||||
|
|
||||||
|
Resize(_destinations, destinations.Length);
|
||||||
|
|
||||||
for (int index = 0; index < destinations.Length; index++)
|
for (int index = 0; index < destinations.Length; index++)
|
||||||
{
|
{
|
||||||
|
@ -100,14 +161,33 @@ namespace ARMeilleure.IntermediateRepresentation
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetSources(Operand[] sources)
|
private void RemoveOldSources()
|
||||||
{
|
{
|
||||||
for (int index = 0; index < _sources.Length; index++)
|
for (int index = 0; index < _sources.Count; index++)
|
||||||
{
|
{
|
||||||
RemoveUse(_sources[index]);
|
RemoveUse(_sources[index]);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_sources = new Operand[sources.Length];
|
public void SetSource(Operand source)
|
||||||
|
{
|
||||||
|
RemoveOldSources();
|
||||||
|
|
||||||
|
Resize(_sources, 1);
|
||||||
|
|
||||||
|
_sources[0] = source;
|
||||||
|
|
||||||
|
if (source.Kind == OperandKind.LocalVariable)
|
||||||
|
{
|
||||||
|
source.Uses.Add(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetSources(Operand[] sources)
|
||||||
|
{
|
||||||
|
RemoveOldSources();
|
||||||
|
|
||||||
|
Resize(_sources, sources.Length);
|
||||||
|
|
||||||
for (int index = 0; index < sources.Length; index++)
|
for (int index = 0; index < sources.Length; index++)
|
||||||
{
|
{
|
||||||
|
|
|
@ -5,16 +5,16 @@ namespace ARMeilleure.IntermediateRepresentation
|
||||||
{
|
{
|
||||||
class Operand
|
class Operand
|
||||||
{
|
{
|
||||||
public OperandKind Kind { get; }
|
public OperandKind Kind { get; private set; }
|
||||||
|
|
||||||
public OperandType Type { get; }
|
public OperandType Type { get; private set; }
|
||||||
|
|
||||||
public ulong Value { get; private set; }
|
public ulong Value { get; private set; }
|
||||||
|
|
||||||
public List<Node> Assignments { get; }
|
public List<Node> Assignments { get; }
|
||||||
public List<Node> Uses { get; }
|
public List<Node> Uses { get; }
|
||||||
|
|
||||||
private Operand()
|
public Operand()
|
||||||
{
|
{
|
||||||
Assignments = new List<Node>();
|
Assignments = new List<Node>();
|
||||||
Uses = new List<Node>();
|
Uses = new List<Node>();
|
||||||
|
@ -26,42 +26,64 @@ namespace ARMeilleure.IntermediateRepresentation
|
||||||
Type = type;
|
Type = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Operand(int value) : this(OperandKind.Constant, OperandType.I32)
|
public Operand With(OperandKind kind, OperandType type = OperandType.None)
|
||||||
{
|
{
|
||||||
Value = (uint)value;
|
Kind = kind;
|
||||||
}
|
|
||||||
|
|
||||||
public Operand(uint value) : this(OperandKind.Constant, OperandType.I32)
|
|
||||||
{
|
|
||||||
Value = (uint)value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Operand(long value) : this(OperandKind.Constant, OperandType.I64)
|
|
||||||
{
|
|
||||||
Value = (ulong)value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Operand(ulong value) : this(OperandKind.Constant, OperandType.I64)
|
|
||||||
{
|
|
||||||
Value = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Operand(float value) : this(OperandKind.Constant, OperandType.FP32)
|
|
||||||
{
|
|
||||||
Value = (ulong)BitConverter.SingleToInt32Bits(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Operand(double value) : this(OperandKind.Constant, OperandType.FP64)
|
|
||||||
{
|
|
||||||
Value = (ulong)BitConverter.DoubleToInt64Bits(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Operand(int index, RegisterType regType, OperandType type) : this()
|
|
||||||
{
|
|
||||||
Kind = OperandKind.Register;
|
|
||||||
Type = type;
|
Type = type;
|
||||||
|
Value = 0;
|
||||||
|
|
||||||
|
Assignments.Clear();
|
||||||
|
Uses.Clear();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Operand With(int value)
|
||||||
|
{
|
||||||
|
With(OperandKind.Constant, OperandType.I32);
|
||||||
|
Value = (uint)value;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Operand With(uint value)
|
||||||
|
{
|
||||||
|
With(OperandKind.Constant, OperandType.I32);
|
||||||
|
Value = (uint)value;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Operand With(long value)
|
||||||
|
{
|
||||||
|
With(OperandKind.Constant, OperandType.I64);
|
||||||
|
Value = (ulong)value;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Operand With(ulong value)
|
||||||
|
{
|
||||||
|
With(OperandKind.Constant, OperandType.I64);
|
||||||
|
Value = value;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Operand With(float value)
|
||||||
|
{
|
||||||
|
With(OperandKind.Constant, OperandType.FP32);
|
||||||
|
Value = (ulong)BitConverter.SingleToInt32Bits(value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Operand With(double value)
|
||||||
|
{
|
||||||
|
With(OperandKind.Constant, OperandType.FP64);
|
||||||
|
Value = (ulong)BitConverter.DoubleToInt64Bits(value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Operand With(int index, RegisterType regType, OperandType type)
|
||||||
|
{
|
||||||
|
With(OperandKind.Register, type);
|
||||||
Value = (ulong)((int)regType << 24 | index);
|
Value = (ulong)((int)regType << 24 | index);
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Register GetRegister()
|
public Register GetRegister()
|
||||||
|
|
|
@ -5,64 +5,90 @@ namespace ARMeilleure.IntermediateRepresentation
|
||||||
{
|
{
|
||||||
static class OperandHelper
|
static class OperandHelper
|
||||||
{
|
{
|
||||||
|
private static MemoryOperand MemoryOperand()
|
||||||
|
{
|
||||||
|
return ThreadStaticPool<MemoryOperand>.Instance.Allocate();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Operand Operand()
|
||||||
|
{
|
||||||
|
return ThreadStaticPool<Operand>.Instance.Allocate();
|
||||||
|
}
|
||||||
|
|
||||||
public static Operand Const(OperandType type, long value)
|
public static Operand Const(OperandType type, long value)
|
||||||
{
|
{
|
||||||
return type == OperandType.I32 ? new Operand((int)value) : new Operand(value);
|
return type == OperandType.I32 ? Operand().With((int)value) : Operand().With(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Operand Const(bool value)
|
public static Operand Const(bool value)
|
||||||
{
|
{
|
||||||
return new Operand(value ? 1 : 0);
|
return Operand().With(value ? 1 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Operand Const(int value)
|
public static Operand Const(int value)
|
||||||
{
|
{
|
||||||
return new Operand(value);
|
return Operand().With(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Operand Const(uint value)
|
public static Operand Const(uint value)
|
||||||
{
|
{
|
||||||
return new Operand(value);
|
return Operand().With(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Operand Const(long value)
|
public static Operand Const(long value)
|
||||||
{
|
{
|
||||||
return new Operand(value);
|
return Operand().With(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Operand Const(ulong value)
|
public static Operand Const(ulong value)
|
||||||
{
|
{
|
||||||
return new Operand(value);
|
return Operand().With(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Operand ConstF(float value)
|
public static Operand ConstF(float value)
|
||||||
{
|
{
|
||||||
return new Operand(value);
|
return Operand().With(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Operand ConstF(double value)
|
public static Operand ConstF(double value)
|
||||||
{
|
{
|
||||||
return new Operand(value);
|
return Operand().With(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Operand Label()
|
public static Operand Label()
|
||||||
{
|
{
|
||||||
return new Operand(OperandKind.Label);
|
return Operand().With(OperandKind.Label);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Operand Local(OperandType type)
|
public static Operand Local(OperandType type)
|
||||||
{
|
{
|
||||||
return new Operand(OperandKind.LocalVariable, type);
|
return Operand().With(OperandKind.LocalVariable, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Operand Register(int index, RegisterType regType, OperandType type)
|
public static Operand Register(int index, RegisterType regType, OperandType type)
|
||||||
{
|
{
|
||||||
return new Operand(index, regType, type);
|
return Operand().With(index, regType, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Operand Undef()
|
public static Operand Undef()
|
||||||
{
|
{
|
||||||
return new Operand(OperandKind.Undefined);
|
return Operand().With(OperandKind.Undefined);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MemoryOperand MemoryOp(
|
||||||
|
OperandType type,
|
||||||
|
Operand baseAddress,
|
||||||
|
Operand index = null,
|
||||||
|
Multiplier scale = Multiplier.x1,
|
||||||
|
int displacement = 0)
|
||||||
|
{
|
||||||
|
return MemoryOperand().With(type, baseAddress, index, scale, displacement);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void ResetOperandPool()
|
||||||
|
{
|
||||||
|
ThreadStaticPool<Operand>.Instance.Clear();
|
||||||
|
ThreadStaticPool<MemoryOperand>.Instance.Clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -4,10 +4,12 @@ namespace ARMeilleure.IntermediateRepresentation
|
||||||
{
|
{
|
||||||
public Instruction Instruction { get; private set; }
|
public Instruction Instruction { get; private set; }
|
||||||
|
|
||||||
|
public Operation() : base() { }
|
||||||
|
|
||||||
public Operation(
|
public Operation(
|
||||||
Instruction instruction,
|
Instruction instruction,
|
||||||
Operand destination,
|
Operand destination,
|
||||||
params Operand[] sources) : base(destination, sources.Length)
|
Operand[] sources) : base(destination, sources.Length)
|
||||||
{
|
{
|
||||||
Instruction = instruction;
|
Instruction = instruction;
|
||||||
|
|
||||||
|
@ -17,24 +19,78 @@ namespace ARMeilleure.IntermediateRepresentation
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Operation(
|
public Operation With(Instruction instruction, Operand destination)
|
||||||
|
{
|
||||||
|
With(destination, 0);
|
||||||
|
Instruction = instruction;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Operation With(Instruction instruction, Operand destination, Operand[] sources)
|
||||||
|
{
|
||||||
|
With(destination, sources.Length);
|
||||||
|
Instruction = instruction;
|
||||||
|
|
||||||
|
for (int index = 0; index < sources.Length; index++)
|
||||||
|
{
|
||||||
|
SetSource(index, sources[index]);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Operation With(Instruction instruction, Operand destination,
|
||||||
|
Operand source0)
|
||||||
|
{
|
||||||
|
With(destination, 1);
|
||||||
|
Instruction = instruction;
|
||||||
|
|
||||||
|
SetSource(0, source0);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Operation With(Instruction instruction, Operand destination,
|
||||||
|
Operand source0, Operand source1)
|
||||||
|
{
|
||||||
|
With(destination, 2);
|
||||||
|
Instruction = instruction;
|
||||||
|
|
||||||
|
SetSource(0, source0);
|
||||||
|
SetSource(1, source1);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Operation With(Instruction instruction, Operand destination,
|
||||||
|
Operand source0, Operand source1, Operand source2)
|
||||||
|
{
|
||||||
|
With(destination, 3);
|
||||||
|
Instruction = instruction;
|
||||||
|
|
||||||
|
SetSource(0, source0);
|
||||||
|
SetSource(1, source1);
|
||||||
|
SetSource(2, source2);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Operation With(
|
||||||
Instruction instruction,
|
Instruction instruction,
|
||||||
Operand[] destinations,
|
Operand[] destinations,
|
||||||
Operand[] sources) : base(destinations, sources.Length)
|
Operand[] sources)
|
||||||
{
|
{
|
||||||
|
With(destinations, sources.Length);
|
||||||
Instruction = instruction;
|
Instruction = instruction;
|
||||||
|
|
||||||
for (int index = 0; index < sources.Length; index++)
|
for (int index = 0; index < sources.Length; index++)
|
||||||
{
|
{
|
||||||
SetSource(index, sources[index]);
|
SetSource(index, sources[index]);
|
||||||
}
|
}
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void TurnIntoCopy(Operand source)
|
public void TurnIntoCopy(Operand source)
|
||||||
{
|
{
|
||||||
Instruction = Instruction.Copy;
|
Instruction = Instruction.Copy;
|
||||||
|
|
||||||
SetSources(new Operand[] { source });
|
SetSource(source);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
52
ARMeilleure/IntermediateRepresentation/OperationHelper.cs
Normal file
52
ARMeilleure/IntermediateRepresentation/OperationHelper.cs
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
namespace ARMeilleure.IntermediateRepresentation
|
||||||
|
{
|
||||||
|
static class OperationHelper
|
||||||
|
{
|
||||||
|
public static Operation Operation()
|
||||||
|
{
|
||||||
|
return ThreadStaticPool<Operation>.Instance.Allocate();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Operation Operation(Instruction instruction, Operand destination)
|
||||||
|
{
|
||||||
|
return Operation().With(instruction, destination);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Operation Operation(Instruction instruction, Operand destination,
|
||||||
|
Operand[] sources)
|
||||||
|
{
|
||||||
|
return Operation().With(instruction, destination, sources);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Operation Operation(Instruction instruction, Operand destination,
|
||||||
|
Operand source0)
|
||||||
|
{
|
||||||
|
return Operation().With(instruction, destination, source0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Operation Operation(Instruction instruction, Operand destination,
|
||||||
|
Operand source0, Operand source1)
|
||||||
|
{
|
||||||
|
return Operation().With(instruction, destination, source0, source1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Operation Operation(Instruction instruction, Operand destination,
|
||||||
|
Operand source0, Operand source1, Operand source2)
|
||||||
|
{
|
||||||
|
return Operation().With(instruction, destination, source0, source1, source2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Operation Operation(
|
||||||
|
Instruction instruction,
|
||||||
|
Operand[] destinations,
|
||||||
|
Operand[] sources)
|
||||||
|
{
|
||||||
|
return Operation().With(instruction, destinations, sources);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void ResetOperationPool()
|
||||||
|
{
|
||||||
|
ThreadStaticPool<Operation>.Instance.Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
69
ARMeilleure/ThreadStaticPool.cs
Normal file
69
ARMeilleure/ThreadStaticPool.cs
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
namespace ARMeilleure
|
||||||
|
{
|
||||||
|
public class ThreadStaticPool<T> where T : class, new()
|
||||||
|
{
|
||||||
|
[ThreadStatic]
|
||||||
|
private static ThreadStaticPool<T> _instance;
|
||||||
|
public static ThreadStaticPool<T> Instance
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_instance == null)
|
||||||
|
{
|
||||||
|
_instance = new ThreadStaticPool<T>(_poolSizeIncrement * 2);
|
||||||
|
}
|
||||||
|
return _instance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private T[] _pool;
|
||||||
|
private int _poolUsed = -1;
|
||||||
|
private int _poolSize;
|
||||||
|
private static readonly int _poolSizeIncrement = 200;
|
||||||
|
|
||||||
|
public ThreadStaticPool(int initialSize)
|
||||||
|
{
|
||||||
|
_pool = new T[initialSize];
|
||||||
|
|
||||||
|
for (int i = 0; i < initialSize; i++)
|
||||||
|
{
|
||||||
|
_pool[i] = new T();
|
||||||
|
}
|
||||||
|
|
||||||
|
_poolSize = initialSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
public T Allocate()
|
||||||
|
{
|
||||||
|
int index = Interlocked.Increment(ref _poolUsed);
|
||||||
|
if (index >= _poolSize)
|
||||||
|
{
|
||||||
|
IncreaseSize();
|
||||||
|
}
|
||||||
|
return _pool[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
private void IncreaseSize()
|
||||||
|
{
|
||||||
|
_poolSize += _poolSizeIncrement;
|
||||||
|
|
||||||
|
T[] newArray = new T[_poolSize];
|
||||||
|
Array.Copy(_pool, 0, newArray, 0, _pool.Length);
|
||||||
|
|
||||||
|
for (int i = _pool.Length; i < _poolSize; i++)
|
||||||
|
{
|
||||||
|
newArray[i] = new T();
|
||||||
|
}
|
||||||
|
|
||||||
|
Interlocked.Exchange(ref _pool, newArray);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Clear()
|
||||||
|
{
|
||||||
|
_poolUsed = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -141,7 +141,7 @@ namespace ARMeilleure.Translation
|
||||||
|
|
||||||
splitBlock2.Branch = successor;
|
splitBlock2.Branch = successor;
|
||||||
|
|
||||||
splitBlock2.Operations.AddLast(new Operation(Instruction.Branch, null));
|
splitBlock2.Operations.AddLast(OperationHelper.Operation(Instruction.Branch, null));
|
||||||
|
|
||||||
Blocks.AddBefore(successor, splitBlock2);
|
Blocks.AddBefore(successor, splitBlock2);
|
||||||
}
|
}
|
||||||
|
|
|
@ -446,14 +446,63 @@ namespace ARMeilleure.Translation
|
||||||
return Add(Instruction.ZeroExtend8, Local(type), op1);
|
return Add(Instruction.ZeroExtend8, Local(type), op1);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Operand Add(Instruction inst, Operand dest = null, params Operand[] sources)
|
private void NewNextBlockIfNeeded()
|
||||||
{
|
{
|
||||||
if (_needsNewBlock)
|
if (_needsNewBlock)
|
||||||
{
|
{
|
||||||
NewNextBlock();
|
NewNextBlock();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Operation operation = new Operation(inst, dest, sources);
|
private Operand Add(Instruction inst, Operand dest = null)
|
||||||
|
{
|
||||||
|
NewNextBlockIfNeeded();
|
||||||
|
|
||||||
|
Operation operation = OperationHelper.Operation(inst, dest);
|
||||||
|
|
||||||
|
_irBlock.Operations.AddLast(operation);
|
||||||
|
|
||||||
|
return dest;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Operand Add(Instruction inst, Operand dest, Operand[] sources)
|
||||||
|
{
|
||||||
|
NewNextBlockIfNeeded();
|
||||||
|
|
||||||
|
Operation operation = OperationHelper.Operation(inst, dest, sources);
|
||||||
|
|
||||||
|
_irBlock.Operations.AddLast(operation);
|
||||||
|
|
||||||
|
return dest;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Operand Add(Instruction inst, Operand dest, Operand source0)
|
||||||
|
{
|
||||||
|
NewNextBlockIfNeeded();
|
||||||
|
|
||||||
|
Operation operation = OperationHelper.Operation(inst, dest, source0);
|
||||||
|
|
||||||
|
_irBlock.Operations.AddLast(operation);
|
||||||
|
|
||||||
|
return dest;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Operand Add(Instruction inst, Operand dest, Operand source0, Operand source1)
|
||||||
|
{
|
||||||
|
NewNextBlockIfNeeded();
|
||||||
|
|
||||||
|
Operation operation = OperationHelper.Operation(inst, dest, source0, source1);
|
||||||
|
|
||||||
|
_irBlock.Operations.AddLast(operation);
|
||||||
|
|
||||||
|
return dest;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Operand Add(Instruction inst, Operand dest, Operand source0, Operand source1, Operand source2)
|
||||||
|
{
|
||||||
|
NewNextBlockIfNeeded();
|
||||||
|
|
||||||
|
Operation operation = OperationHelper.Operation(inst, dest, source0, source1, source2);
|
||||||
|
|
||||||
_irBlock.Operations.AddLast(operation);
|
_irBlock.Operations.AddLast(operation);
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@ using ARMeilleure.State;
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
using static ARMeilleure.IntermediateRepresentation.OperandHelper;
|
using static ARMeilleure.IntermediateRepresentation.OperandHelper;
|
||||||
|
using static ARMeilleure.IntermediateRepresentation.OperationHelper;
|
||||||
|
|
||||||
namespace ARMeilleure.Translation
|
namespace ARMeilleure.Translation
|
||||||
{
|
{
|
||||||
|
@ -299,16 +300,16 @@ namespace ARMeilleure.Translation
|
||||||
|
|
||||||
Operand addr = Local(OperandType.I64);
|
Operand addr = Local(OperandType.I64);
|
||||||
|
|
||||||
Operation loadOp = new Operation(Instruction.Load, dest, addr);
|
Operation loadOp = Operation(Instruction.Load, dest, addr);
|
||||||
|
|
||||||
block.Operations.AddFirst(loadOp);
|
block.Operations.AddFirst(loadOp);
|
||||||
|
|
||||||
Operation calcOffsOp = new Operation(Instruction.Add, addr, arg0, Const(offset));
|
Operation calcOffsOp = Operation(Instruction.Add, addr, arg0, Const(offset));
|
||||||
|
|
||||||
block.Operations.AddFirst(calcOffsOp);
|
block.Operations.AddFirst(calcOffsOp);
|
||||||
}
|
}
|
||||||
|
|
||||||
Operation loadArg0 = new Operation(Instruction.LoadArgument, arg0, Const(0));
|
Operation loadArg0 = Operation(Instruction.LoadArgument, arg0, Const(0));
|
||||||
|
|
||||||
block.Operations.AddFirst(loadArg0);
|
block.Operations.AddFirst(loadArg0);
|
||||||
}
|
}
|
||||||
|
@ -329,7 +330,7 @@ namespace ARMeilleure.Translation
|
||||||
|
|
||||||
Operand arg0 = Local(OperandType.I64);
|
Operand arg0 = Local(OperandType.I64);
|
||||||
|
|
||||||
Operation loadArg0 = new Operation(Instruction.LoadArgument, arg0, Const(0));
|
Operation loadArg0 = Operation(Instruction.LoadArgument, arg0, Const(0));
|
||||||
|
|
||||||
block.Append(loadArg0);
|
block.Append(loadArg0);
|
||||||
|
|
||||||
|
@ -348,11 +349,11 @@ namespace ARMeilleure.Translation
|
||||||
|
|
||||||
Operand addr = Local(OperandType.I64);
|
Operand addr = Local(OperandType.I64);
|
||||||
|
|
||||||
Operation calcOffsOp = new Operation(Instruction.Add, addr, arg0, Const(offset));
|
Operation calcOffsOp = Operation(Instruction.Add, addr, arg0, Const(offset));
|
||||||
|
|
||||||
block.Append(calcOffsOp);
|
block.Append(calcOffsOp);
|
||||||
|
|
||||||
Operation storeOp = new Operation(Instruction.Store, null, addr, source);
|
Operation storeOp = Operation(Instruction.Store, null, addr, source);
|
||||||
|
|
||||||
block.Append(storeOp);
|
block.Append(storeOp);
|
||||||
}
|
}
|
||||||
|
@ -362,15 +363,15 @@ namespace ARMeilleure.Translation
|
||||||
{
|
{
|
||||||
if (bit < RegsCount)
|
if (bit < RegsCount)
|
||||||
{
|
{
|
||||||
return new Operand(bit, baseType, GetOperandType(baseType, mode));
|
return OperandHelper.Register(bit, baseType, GetOperandType(baseType, mode));
|
||||||
}
|
}
|
||||||
else if (baseType == RegisterType.Integer)
|
else if (baseType == RegisterType.Integer)
|
||||||
{
|
{
|
||||||
return new Operand(bit & RegsMask, RegisterType.Flag, OperandType.I32);
|
return OperandHelper.Register(bit & RegsMask, RegisterType.Flag, OperandType.I32);
|
||||||
}
|
}
|
||||||
else if (baseType == RegisterType.Vector)
|
else if (baseType == RegisterType.Vector)
|
||||||
{
|
{
|
||||||
return new Operand(bit & RegsMask, RegisterType.FpFlag, OperandType.I32);
|
return OperandHelper.Register(bit & RegsMask, RegisterType.FpFlag, OperandType.I32);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -2,6 +2,7 @@ using ARMeilleure.IntermediateRepresentation;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
using static ARMeilleure.IntermediateRepresentation.OperandHelper;
|
using static ARMeilleure.IntermediateRepresentation.OperandHelper;
|
||||||
|
using static ARMeilleure.IntermediateRepresentation.OperationHelper;
|
||||||
|
|
||||||
namespace ARMeilleure.Translation
|
namespace ARMeilleure.Translation
|
||||||
{
|
{
|
||||||
|
@ -25,12 +26,12 @@ namespace ARMeilleure.Translation
|
||||||
|
|
||||||
Operand source = phi.GetSource(index);
|
Operand source = phi.GetSource(index);
|
||||||
|
|
||||||
predecessor.Append(new Operation(Instruction.Copy, local, source));
|
predecessor.Append(Operation(Instruction.Copy, local, source));
|
||||||
|
|
||||||
phi.SetSource(index, null);
|
phi.SetSource(index, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
Operation copyOp = new Operation(Instruction.Copy, phi.Destination, local);
|
Operation copyOp = Operation(Instruction.Copy, phi.Destination, local);
|
||||||
|
|
||||||
block.Operations.AddBefore(node, copyOp);
|
block.Operations.AddBefore(node, copyOp);
|
||||||
|
|
||||||
|
|
|
@ -161,6 +161,9 @@ namespace ARMeilleure.Translation
|
||||||
|
|
||||||
GuestFunction func = Compiler.Compile<GuestFunction>(cfg, argTypes, OperandType.I64, options);
|
GuestFunction func = Compiler.Compile<GuestFunction>(cfg, argTypes, OperandType.I64, options);
|
||||||
|
|
||||||
|
OperandHelper.ResetOperandPool();
|
||||||
|
OperationHelper.ResetOperationPool();
|
||||||
|
|
||||||
return new TranslatedFunction(func, rejit: !highCq);
|
return new TranslatedFunction(func, rejit: !highCq);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue