From 9f8fbc1d8a9101a65892e5ae64aa97892e6e0e89 Mon Sep 17 00:00:00 2001 From: gdkchan Date: Wed, 19 Jun 2019 20:21:47 -0300 Subject: [PATCH] Fix arguments count with struct return values, other fixes --- .../RegisterAllocators/AllocationResult.cs | 5 +--- .../CodeGen/RegisterAllocators/LinearScan.cs | 14 +++-------- ARMeilleure/CodeGen/X86/CodeGenContext.cs | 8 +++---- ARMeilleure/CodeGen/X86/CodeGenerator.cs | 4 ++-- ARMeilleure/CodeGen/X86/PreAllocator.cs | 24 ++++++++++++++++++- ARMeilleure/Instructions/SoftFallback.cs | 8 +++---- 6 files changed, 37 insertions(+), 26 deletions(-) diff --git a/ARMeilleure/CodeGen/RegisterAllocators/AllocationResult.cs b/ARMeilleure/CodeGen/RegisterAllocators/AllocationResult.cs index d217185070..94ac6991b0 100644 --- a/ARMeilleure/CodeGen/RegisterAllocators/AllocationResult.cs +++ b/ARMeilleure/CodeGen/RegisterAllocators/AllocationResult.cs @@ -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; } } } \ No newline at end of file diff --git a/ARMeilleure/CodeGen/RegisterAllocators/LinearScan.cs b/ARMeilleure/CodeGen/RegisterAllocators/LinearScan.cs index cb44c08deb..681de68e69 100644 --- a/ARMeilleure/CodeGen/RegisterAllocators/LinearScan.cs +++ b/ARMeilleure/CodeGen/RegisterAllocators/LinearScan.cs @@ -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) { diff --git a/ARMeilleure/CodeGen/X86/CodeGenContext.cs b/ARMeilleure/CodeGen/X86/CodeGenContext.cs index 46005f9248..5c0330fe60 100644 --- a/ARMeilleure/CodeGen/X86/CodeGenContext.cs +++ b/ARMeilleure/CodeGen/X86/CodeGenContext.cs @@ -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(); } - 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). diff --git a/ARMeilleure/CodeGen/X86/CodeGenerator.cs b/ARMeilleure/CodeGen/X86/CodeGenerator.cs index 50f4e417cb..8a6e8606d5 100644 --- a/ARMeilleure/CodeGen/X86/CodeGenerator.cs +++ b/ARMeilleure/CodeGen/X86/CodeGenerator.cs @@ -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); diff --git a/ARMeilleure/CodeGen/X86/PreAllocator.cs b/ARMeilleure/CodeGen/X86/PreAllocator.cs index 0099c6a030..507154e005 100644 --- a/ARMeilleure/CodeGen/X86/PreAllocator.cs +++ b/ARMeilleure/CodeGen/X86/PreAllocator.cs @@ -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 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; } diff --git a/ARMeilleure/Instructions/SoftFallback.cs b/ARMeilleure/Instructions/SoftFallback.cs index 1f5c726bcf..4a47e53d2e 100644 --- a/ARMeilleure/Instructions/SoftFallback.cs +++ b/ARMeilleure/Instructions/SoftFallback.cs @@ -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]; } }