Fix arguments count with struct return values, other fixes

This commit is contained in:
gdkchan 2019-06-19 20:21:47 -03:00
parent 0bacc3fd63
commit 9f8fbc1d8a
6 changed files with 37 additions and 26 deletions

View file

@ -5,18 +5,15 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
public int IntUsedRegisters { get; }
public int VecUsedRegisters { get; }
public int SpillRegionSize { get; }
public int MaxCallArgs { get; }
public AllocationResult(
int intUsedRegisters,
int vecUsedRegisters,
int spillRegionSize,
int maxCallArgs)
int spillRegionSize)
{
IntUsedRegisters = intUsedRegisters;
VecUsedRegisters = vecUsedRegisters;
SpillRegionSize = spillRegionSize;
MaxCallArgs = maxCallArgs;
}
}
}

View file

@ -77,7 +77,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
AllocationContext context = new AllocationContext(regMasks, _intervals.Count);
BuildIntervals(cfg, context, out int maxCallArgs);
BuildIntervals(cfg, context);
for (int index = 0; index < _intervals.Count; index++)
{
@ -115,8 +115,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
return new AllocationResult(
context.IntUsedRegisters,
context.VecUsedRegisters,
context.StackAlloc.TotalSize,
maxCallArgs);
context.StackAlloc.TotalSize);
}
private void AllocateInterval(AllocationContext context, LiveInterval current, int cIndex)
@ -774,10 +773,8 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
_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];
int mapSize = _intervals.Count;
@ -912,11 +909,6 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
{
AddIntervalCallerSavedReg(context.Masks.IntCallerSavedRegisters, operationPos, RegisterType.Integer);
AddIntervalCallerSavedReg(context.Masks.VecCallerSavedRegisters, operationPos, RegisterType.Vector);
if (maxCallArgs < operation.SourcesCount - 1)
{
maxCallArgs = operation.SourcesCount - 1;
}
}
else if (operation.Inst == Instruction.StackAlloc)
{

View file

@ -71,7 +71,7 @@ namespace ARMeilleure.CodeGen.X86
private long _jNearPosition;
private int _jNearLength;
public CodeGenContext(Stream stream, AllocationResult allocResult, int blocksCount)
public CodeGenContext(Stream stream, AllocationResult allocResult, int maxCallArgs, int blocksCount)
{
_stream = stream;
@ -79,7 +79,7 @@ namespace ARMeilleure.CodeGen.X86
Assembler = new Assembler(stream);
CallArgsRegionSize = GetCallArgsRegionSize(allocResult, out int vecCalleeSaveSize);
CallArgsRegionSize = GetCallArgsRegionSize(allocResult, maxCallArgs, out int vecCalleeSaveSize);
VecCalleeSaveSize = vecCalleeSaveSize;
@ -88,7 +88,7 @@ namespace ARMeilleure.CodeGen.X86
_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
//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 argsCount = allocResult.MaxCallArgs;
int argsCount = maxCallArgs;
//The ABI mandates that the space for at least 4 arguments
//is reserved on the stack (this is called shadow space).

View file

@ -231,7 +231,7 @@ namespace ARMeilleure.CodeGen.X86
Logger.StartPass(PassName.PreAllocation);
PreAllocator.RunPass(cfg, memory);
PreAllocator.RunPass(cfg, memory, out int maxCallArgs);
Logger.EndPass(PassName.PreAllocation, cfg);
@ -253,7 +253,7 @@ namespace ARMeilleure.CodeGen.X86
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);

View file

@ -10,8 +10,10 @@ namespace ARMeilleure.CodeGen.X86
{
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)
{
LinkedListNode<Node> nextNode;
@ -55,6 +57,24 @@ namespace ARMeilleure.CodeGen.X86
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);
HandleSameDestSrc1Copy(node, operation);
@ -597,6 +617,8 @@ namespace ARMeilleure.CodeGen.X86
{
case Instruction.Copy:
case Instruction.LoadFromContext:
case Instruction.Spill:
case Instruction.SpillArg:
case Instruction.StoreToContext:
return true;
}

View file

@ -882,7 +882,7 @@ namespace ARMeilleure.Instructions
byte[] res = new byte[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);
}
@ -891,11 +891,11 @@ namespace ARMeilleure.Instructions
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];
}
}