diff --git a/ARMeilleure/CodeGen/X86/PreAllocator.cs b/ARMeilleure/CodeGen/X86/PreAllocator.cs index 712f27f3ed..65e2e39efa 100644 --- a/ARMeilleure/CodeGen/X86/PreAllocator.cs +++ b/ARMeilleure/CodeGen/X86/PreAllocator.cs @@ -22,22 +22,16 @@ namespace ARMeilleure.CodeGen.X86 for (BasicBlock block = cctx.Cfg.Blocks.First; block != null; block = block.ListNext) { - Node nextNode; - - for (Node node = block.Operations.First; node != null; node = nextNode) + for (Node node = block.Operations.First; node != null; node = node.ListNext) { - nextNode = node.ListNext; - if (!(node is Operation operation)) { continue; } - HandleConstantCopy(block.Operations, node, operation); - - HandleSameDestSrc1Copy(block.Operations, node, operation); - - HandleFixedRegisterCopy(block.Operations, node, operation); + HandleConstantRegCopy(block.Operations, node, operation); + node = HandleDestructiveRegCopy(block.Operations, node, operation); + node = HandleConstrainedRegCopy(block.Operations, node, operation); switch (operation.Instruction) { @@ -71,17 +65,17 @@ namespace ARMeilleure.CodeGen.X86 break; case Instruction.ConvertToFPUI: - HandleConvertToFPUI(block.Operations, node, operation); + node = HandleConvertToFPUI(block.Operations, node, operation); break; case Instruction.LoadArgument: if (callConv == CallConvName.Windows) { - HandleLoadArgumentWindowsAbi(cctx, block.Operations, node, preservedArgs, operation); + node = HandleLoadArgumentWindowsAbi(cctx, block.Operations, node, preservedArgs, operation); } else /* if (callConv == CallConvName.SystemV) */ { - HandleLoadArgumentSystemVAbi(cctx, block.Operations, node, preservedArgs, operation); + node = HandleLoadArgumentSystemVAbi(cctx, block.Operations, node, preservedArgs, operation); } break; @@ -125,7 +119,7 @@ namespace ARMeilleure.CodeGen.X86 } } - private static void HandleConstantCopy(IntrusiveList nodes, Node node, Operation operation) + private static void HandleConstantRegCopy(IntrusiveList nodes, Node node, Operation operation) { if (operation.SourcesCount == 0 || IsIntrinsic(operation.Instruction)) { @@ -206,7 +200,7 @@ namespace ARMeilleure.CodeGen.X86 } } - private static Node HandleFixedRegisterCopy(IntrusiveList nodes, Node node, Operation operation) + private static Node HandleConstrainedRegCopy(IntrusiveList nodes, Node node, Operation operation) { Operand dest = operation.Destination; @@ -248,14 +242,20 @@ namespace ARMeilleure.CodeGen.X86 // Handle the many restrictions of the compare and exchange (32/64) instruction: // - The expected value should be in (E/R)AX. // - The value at the memory location is loaded to (E/R)AX. - Operand expected = operation.GetSource(1); + Operand newValue = operation.GetSource(2); Operand rax = Gpr(X86Register.Rax, expected.Type); nodes.AddBefore(node, Operation(Instruction.Copy, rax, expected)); - operation.SetSources(new Operand[] { operation.GetSource(0), rax, operation.GetSource(2) }); + // We need to store the new value into a temp, since it may + // be a constant, and this instruction does not support immediate operands. + Operand temp = Local(newValue.Type); + + nodes.AddBefore(node, Operation(Instruction.Copy, temp, newValue)); + + operation.SetSources(new Operand[] { operation.GetSource(0), rax, temp }); node = nodes.AddAfter(node, Operation(Instruction.Copy, dest, rax)); @@ -391,7 +391,7 @@ namespace ARMeilleure.CodeGen.X86 return node; } - private static Node HandleSameDestSrc1Copy(IntrusiveList nodes, Node node, Operation operation) + private static Node HandleDestructiveRegCopy(IntrusiveList nodes, Node node, Operation operation) { if (operation.Destination == null || operation.SourcesCount == 0) { @@ -683,7 +683,7 @@ namespace ARMeilleure.CodeGen.X86 Operation storeOp = Operation(Instruction.Store, null, stackAddr, source); - HandleConstantCopy(nodes, nodes.AddBefore(node, storeOp), storeOp); + HandleConstantRegCopy(nodes, nodes.AddBefore(node, storeOp), storeOp); operation.SetSource(index, stackAddr); } @@ -709,7 +709,7 @@ namespace ARMeilleure.CodeGen.X86 Operation copyOp = Operation(Instruction.Copy, argReg, source); - HandleConstantCopy(nodes, nodes.AddBefore(node, copyOp), copyOp); + HandleConstantRegCopy(nodes, nodes.AddBefore(node, copyOp), copyOp); sources[1 + retArgs + index] = argReg; } @@ -724,7 +724,7 @@ namespace ARMeilleure.CodeGen.X86 Operation spillOp = Operation(Instruction.SpillArg, null, offset, source); - HandleConstantCopy(nodes, nodes.AddBefore(node, spillOp), spillOp); + HandleConstantRegCopy(nodes, nodes.AddBefore(node, spillOp), spillOp); } if (dest != null) @@ -818,7 +818,7 @@ namespace ARMeilleure.CodeGen.X86 Operation copyOp = Operation(Instruction.Copy, argReg, source); - HandleConstantCopy(nodes, nodes.AddBefore(node, copyOp), copyOp); + HandleConstantRegCopy(nodes, nodes.AddBefore(node, copyOp), copyOp); sources.Add(argReg); } @@ -828,7 +828,7 @@ namespace ARMeilleure.CodeGen.X86 Operation spillOp = Operation(Instruction.SpillArg, null, offset, source); - HandleConstantCopy(nodes, nodes.AddBefore(node, spillOp), spillOp); + HandleConstantRegCopy(nodes, nodes.AddBefore(node, spillOp), spillOp); stackOffset += source.Type.GetSizeInBytes(); } @@ -867,9 +867,10 @@ namespace ARMeilleure.CodeGen.X86 private static void HandleTailcallSystemVAbi(IntrusiveList nodes, StackAllocator stackAlloc, Node node, Operation operation) { - List sources = new List(); - - sources.Add(operation.GetSource(0)); + List sources = new List + { + operation.GetSource(0) + }; int argsCount = operation.SourcesCount - 1; @@ -915,7 +916,7 @@ namespace ARMeilleure.CodeGen.X86 Operation copyOp = Operation(Instruction.Copy, argReg, source); - HandleConstantCopy(nodes, nodes.AddBefore(node, copyOp), copyOp); + HandleConstantRegCopy(nodes, nodes.AddBefore(node, copyOp), copyOp); sources.Add(argReg); } @@ -963,7 +964,7 @@ namespace ARMeilleure.CodeGen.X86 Operation copyOp = Operation(Instruction.Copy, argReg, source); - HandleConstantCopy(nodes, nodes.AddBefore(node, copyOp), copyOp); + HandleConstantRegCopy(nodes, nodes.AddBefore(node, copyOp), copyOp); sources[1 + index] = argReg; } @@ -982,7 +983,7 @@ namespace ARMeilleure.CodeGen.X86 operation.SetSources(sources); } - private static void HandleLoadArgumentWindowsAbi( + private static Node HandleLoadArgumentWindowsAbi( CompilerContext cctx, IntrusiveList nodes, Node node, @@ -1035,17 +1036,20 @@ namespace ARMeilleure.CodeGen.X86 ? Instruction.Load : Instruction.Copy, dest, preservedArgs[index]); - nodes.AddBefore(node, argCopyOp); + Node newNode = nodes.AddBefore(node, argCopyOp); Delete(nodes, node, operation); + + return newNode; } else { // TODO: Pass on stack. + return node; } } - private static void HandleLoadArgumentSystemVAbi( + private static Node HandleLoadArgumentSystemVAbi( CompilerContext cctx, IntrusiveList nodes, Node node, @@ -1134,13 +1138,16 @@ namespace ARMeilleure.CodeGen.X86 Operation argCopyOp = Operation(Instruction.Copy, dest, preservedArgs[index]); - nodes.AddBefore(node, argCopyOp); + Node newNode = nodes.AddBefore(node, argCopyOp); Delete(nodes, node, operation); + + return newNode; } else { // TODO: Pass on stack. + return node; } }