Fix arguments count with struct return values, other fixes
This commit is contained in:
parent
0bacc3fd63
commit
9f8fbc1d8a
6 changed files with 37 additions and 26 deletions
|
@ -5,18 +5,15 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
||||||
public int IntUsedRegisters { get; }
|
public int IntUsedRegisters { get; }
|
||||||
public int VecUsedRegisters { get; }
|
public int VecUsedRegisters { get; }
|
||||||
public int SpillRegionSize { get; }
|
public int SpillRegionSize { get; }
|
||||||
public int MaxCallArgs { get; }
|
|
||||||
|
|
||||||
public AllocationResult(
|
public AllocationResult(
|
||||||
int intUsedRegisters,
|
int intUsedRegisters,
|
||||||
int vecUsedRegisters,
|
int vecUsedRegisters,
|
||||||
int spillRegionSize,
|
int spillRegionSize)
|
||||||
int maxCallArgs)
|
|
||||||
{
|
{
|
||||||
IntUsedRegisters = intUsedRegisters;
|
IntUsedRegisters = intUsedRegisters;
|
||||||
VecUsedRegisters = vecUsedRegisters;
|
VecUsedRegisters = vecUsedRegisters;
|
||||||
SpillRegionSize = spillRegionSize;
|
SpillRegionSize = spillRegionSize;
|
||||||
MaxCallArgs = maxCallArgs;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -77,7 +77,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
||||||
|
|
||||||
AllocationContext context = new AllocationContext(regMasks, _intervals.Count);
|
AllocationContext context = new AllocationContext(regMasks, _intervals.Count);
|
||||||
|
|
||||||
BuildIntervals(cfg, context, out int maxCallArgs);
|
BuildIntervals(cfg, context);
|
||||||
|
|
||||||
for (int index = 0; index < _intervals.Count; index++)
|
for (int index = 0; index < _intervals.Count; index++)
|
||||||
{
|
{
|
||||||
|
@ -115,8 +115,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
||||||
return new AllocationResult(
|
return new AllocationResult(
|
||||||
context.IntUsedRegisters,
|
context.IntUsedRegisters,
|
||||||
context.VecUsedRegisters,
|
context.VecUsedRegisters,
|
||||||
context.StackAlloc.TotalSize,
|
context.StackAlloc.TotalSize);
|
||||||
maxCallArgs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AllocateInterval(AllocationContext context, LiveInterval current, int cIndex)
|
private void AllocateInterval(AllocationContext context, LiveInterval current, int cIndex)
|
||||||
|
@ -774,10 +773,8 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
||||||
_parentIntervals = _intervals.ToArray();
|
_parentIntervals = _intervals.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void BuildIntervals(ControlFlowGraph cfg, AllocationContext context, out int maxCallArgs)
|
private void BuildIntervals(ControlFlowGraph cfg, AllocationContext context)
|
||||||
{
|
{
|
||||||
maxCallArgs = 0;
|
|
||||||
|
|
||||||
_blockRanges = new LiveRange[cfg.Blocks.Count];
|
_blockRanges = new LiveRange[cfg.Blocks.Count];
|
||||||
|
|
||||||
int mapSize = _intervals.Count;
|
int mapSize = _intervals.Count;
|
||||||
|
@ -912,11 +909,6 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
||||||
{
|
{
|
||||||
AddIntervalCallerSavedReg(context.Masks.IntCallerSavedRegisters, operationPos, RegisterType.Integer);
|
AddIntervalCallerSavedReg(context.Masks.IntCallerSavedRegisters, operationPos, RegisterType.Integer);
|
||||||
AddIntervalCallerSavedReg(context.Masks.VecCallerSavedRegisters, operationPos, RegisterType.Vector);
|
AddIntervalCallerSavedReg(context.Masks.VecCallerSavedRegisters, operationPos, RegisterType.Vector);
|
||||||
|
|
||||||
if (maxCallArgs < operation.SourcesCount - 1)
|
|
||||||
{
|
|
||||||
maxCallArgs = operation.SourcesCount - 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (operation.Inst == Instruction.StackAlloc)
|
else if (operation.Inst == Instruction.StackAlloc)
|
||||||
{
|
{
|
||||||
|
|
|
@ -71,7 +71,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
private long _jNearPosition;
|
private long _jNearPosition;
|
||||||
private int _jNearLength;
|
private int _jNearLength;
|
||||||
|
|
||||||
public CodeGenContext(Stream stream, AllocationResult allocResult, int blocksCount)
|
public CodeGenContext(Stream stream, AllocationResult allocResult, int maxCallArgs, int blocksCount)
|
||||||
{
|
{
|
||||||
_stream = stream;
|
_stream = stream;
|
||||||
|
|
||||||
|
@ -79,7 +79,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
|
|
||||||
Assembler = new Assembler(stream);
|
Assembler = new Assembler(stream);
|
||||||
|
|
||||||
CallArgsRegionSize = GetCallArgsRegionSize(allocResult, out int vecCalleeSaveSize);
|
CallArgsRegionSize = GetCallArgsRegionSize(allocResult, maxCallArgs, out int vecCalleeSaveSize);
|
||||||
|
|
||||||
VecCalleeSaveSize = vecCalleeSaveSize;
|
VecCalleeSaveSize = vecCalleeSaveSize;
|
||||||
|
|
||||||
|
@ -88,7 +88,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
_jumps = new List<Jump>();
|
_jumps = new List<Jump>();
|
||||||
}
|
}
|
||||||
|
|
||||||
private int GetCallArgsRegionSize(AllocationResult allocResult, out int vecCalleeSaveSize)
|
private int GetCallArgsRegionSize(AllocationResult allocResult, int maxCallArgs, out int vecCalleeSaveSize)
|
||||||
{
|
{
|
||||||
//We need to add 8 bytes to the total size, as the call to this
|
//We need to add 8 bytes to the total size, as the call to this
|
||||||
//function already pushed 8 bytes (the return address).
|
//function already pushed 8 bytes (the return address).
|
||||||
|
@ -101,7 +101,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
|
|
||||||
int calleeSaveRegionSize = BitUtils.CountBits(intMask) * 8 + vecCalleeSaveSize + 8;
|
int calleeSaveRegionSize = BitUtils.CountBits(intMask) * 8 + vecCalleeSaveSize + 8;
|
||||||
|
|
||||||
int argsCount = allocResult.MaxCallArgs;
|
int argsCount = maxCallArgs;
|
||||||
|
|
||||||
//The ABI mandates that the space for at least 4 arguments
|
//The ABI mandates that the space for at least 4 arguments
|
||||||
//is reserved on the stack (this is called shadow space).
|
//is reserved on the stack (this is called shadow space).
|
||||||
|
|
|
@ -231,7 +231,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
|
|
||||||
Logger.StartPass(PassName.PreAllocation);
|
Logger.StartPass(PassName.PreAllocation);
|
||||||
|
|
||||||
PreAllocator.RunPass(cfg, memory);
|
PreAllocator.RunPass(cfg, memory, out int maxCallArgs);
|
||||||
|
|
||||||
Logger.EndPass(PassName.PreAllocation, cfg);
|
Logger.EndPass(PassName.PreAllocation, cfg);
|
||||||
|
|
||||||
|
@ -253,7 +253,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
|
|
||||||
using (MemoryStream stream = new MemoryStream())
|
using (MemoryStream stream = new MemoryStream())
|
||||||
{
|
{
|
||||||
CodeGenContext context = new CodeGenContext(stream, allocResult, cfg.Blocks.Count);
|
CodeGenContext context = new CodeGenContext(stream, allocResult, maxCallArgs, cfg.Blocks.Count);
|
||||||
|
|
||||||
WritePrologue(context);
|
WritePrologue(context);
|
||||||
|
|
||||||
|
|
|
@ -10,8 +10,10 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
{
|
{
|
||||||
static class PreAllocator
|
static class PreAllocator
|
||||||
{
|
{
|
||||||
public static void RunPass(ControlFlowGraph cfg, MemoryManager memory)
|
public static void RunPass(ControlFlowGraph cfg, MemoryManager memory, out int maxCallArgs)
|
||||||
{
|
{
|
||||||
|
maxCallArgs = 0;
|
||||||
|
|
||||||
foreach (BasicBlock block in cfg.Blocks)
|
foreach (BasicBlock block in cfg.Blocks)
|
||||||
{
|
{
|
||||||
LinkedListNode<Node> nextNode;
|
LinkedListNode<Node> nextNode;
|
||||||
|
@ -55,6 +57,24 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
ReplaceNegateWithXor(node, operation);
|
ReplaceNegateWithXor(node, operation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Get the maximum number of arguments used on a call. On windows,
|
||||||
|
//when a struct is returned from the call, we also need to pass
|
||||||
|
//the pointer where the struct should be written on the first argument.
|
||||||
|
if (inst == Instruction.Call)
|
||||||
|
{
|
||||||
|
int argsCount = operation.SourcesCount - 1;
|
||||||
|
|
||||||
|
if (operation.Dest != null && operation.Dest.Type == OperandType.V128)
|
||||||
|
{
|
||||||
|
argsCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (maxCallArgs < argsCount)
|
||||||
|
{
|
||||||
|
maxCallArgs = argsCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
HandleFixedRegisterCopy(node, operation);
|
HandleFixedRegisterCopy(node, operation);
|
||||||
|
|
||||||
HandleSameDestSrc1Copy(node, operation);
|
HandleSameDestSrc1Copy(node, operation);
|
||||||
|
@ -597,6 +617,8 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
{
|
{
|
||||||
case Instruction.Copy:
|
case Instruction.Copy:
|
||||||
case Instruction.LoadFromContext:
|
case Instruction.LoadFromContext:
|
||||||
|
case Instruction.Spill:
|
||||||
|
case Instruction.SpillArg:
|
||||||
case Instruction.StoreToContext:
|
case Instruction.StoreToContext:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -882,7 +882,7 @@ namespace ARMeilleure.Instructions
|
||||||
byte[] res = new byte[16];
|
byte[] res = new byte[16];
|
||||||
byte[] table = new byte[tb.Length * 16];
|
byte[] table = new byte[tb.Length * 16];
|
||||||
|
|
||||||
for (byte index = 0; index < tb.Length; index++)
|
for (byte index = 0; index < tb.Length; index++)
|
||||||
{
|
{
|
||||||
Buffer.BlockCopy(tb[index].ToArray(), 0, table, index * 16, 16);
|
Buffer.BlockCopy(tb[index].ToArray(), 0, table, index * 16, 16);
|
||||||
}
|
}
|
||||||
|
@ -891,11 +891,11 @@ namespace ARMeilleure.Instructions
|
||||||
|
|
||||||
for (byte index = 0; index < bytes; index++)
|
for (byte index = 0; index < bytes; index++)
|
||||||
{
|
{
|
||||||
byte tblIdx = v[index];
|
byte tblIndex = v[index];
|
||||||
|
|
||||||
if (tblIdx < table.Length)
|
if (tblIndex < table.Length)
|
||||||
{
|
{
|
||||||
res[index] = table[tblIdx];
|
res[index] = table[tblIndex];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue