Fix arguments count with struct return values, other fixes

This commit is contained in:
gdkchan 2019-06-19 20:21:47 -03:00
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 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;
} }
} }
} }

View file

@ -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)
{ {

View file

@ -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).

View file

@ -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);

View file

@ -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;
} }

View file

@ -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];
} }
} }