From f192e623f579e09b7b5442cc707a40482b76e81e Mon Sep 17 00:00:00 2001 From: Sylvain Henry Date: Fri, 14 May 2021 17:31:38 +0200 Subject: Cmm: fix sinking after suspendThread Suppose a safe call: myCall(x,y,z) It is lowered into three unsafe calls in Cmm: r = suspendThread(...); myCall(x,y,z); resumeThread(r); Consider the following situation for myCall arguments: x = Sp[..] -- stack y = Hp[..] -- heap z = R1 -- global register r = suspendThread(...); myCall(x,y,z); resumeThread(r); The sink pass assumes that unsafe calls clobber memory (heap and stack), hence x and y assignments are not sunk after `suspendThread`. The sink pass also correctly handles global register clobbering for all unsafe calls, except `suspendThread`! `suspendThread` is special because it releases the capability the thread is running on. Hence the sink pass must also take into account global registers that are mapped into memory (in the capability). In the example above, we could get: r = suspendThread(...); z = R1 myCall(x,y,z); resumeThread(r); But this transformation isn't valid if R1 is (BaseReg->rR1) as BaseReg is invalid between suspendThread and resumeThread. This caused argument corruption at least with the C backend ("unregisterised") in #19237. Fix #19237 --- compiler/GHC/CmmToAsm/PPC/CodeGen.hs | 3 +++ compiler/GHC/CmmToAsm/SPARC/CodeGen.hs | 3 +++ compiler/GHC/CmmToAsm/X86/CodeGen.hs | 3 +++ 3 files changed, 9 insertions(+) (limited to 'compiler/GHC/CmmToAsm') diff --git a/compiler/GHC/CmmToAsm/PPC/CodeGen.hs b/compiler/GHC/CmmToAsm/PPC/CodeGen.hs index c3e66c02ac..4be45098be 100644 --- a/compiler/GHC/CmmToAsm/PPC/CodeGen.hs +++ b/compiler/GHC/CmmToAsm/PPC/CodeGen.hs @@ -2012,6 +2012,9 @@ genCCall' config gcp target dest_regs args MO_Memmove _ -> (fsLit "memmove", False) MO_Memcmp _ -> (fsLit "memcmp", False) + MO_SuspendThread -> (fsLit "suspendThread", False) + MO_ResumeThread -> (fsLit "resumeThread", False) + MO_BSwap w -> (bSwapLabel w, False) MO_BRev w -> (bRevLabel w, False) MO_PopCnt w -> (popCntLabel w, False) diff --git a/compiler/GHC/CmmToAsm/SPARC/CodeGen.hs b/compiler/GHC/CmmToAsm/SPARC/CodeGen.hs index 974aec02c2..0a5152f425 100644 --- a/compiler/GHC/CmmToAsm/SPARC/CodeGen.hs +++ b/compiler/GHC/CmmToAsm/SPARC/CodeGen.hs @@ -665,6 +665,9 @@ outOfLineMachOp_table mop MO_Memmove _ -> fsLit "memmove" MO_Memcmp _ -> fsLit "memcmp" + MO_SuspendThread -> fsLit "suspendThread" + MO_ResumeThread -> fsLit "resumeThread" + MO_BSwap w -> bSwapLabel w MO_BRev w -> bRevLabel w MO_PopCnt w -> popCntLabel w diff --git a/compiler/GHC/CmmToAsm/X86/CodeGen.hs b/compiler/GHC/CmmToAsm/X86/CodeGen.hs index 7f9b842c1b..8da259e73b 100644 --- a/compiler/GHC/CmmToAsm/X86/CodeGen.hs +++ b/compiler/GHC/CmmToAsm/X86/CodeGen.hs @@ -3395,6 +3395,9 @@ outOfLineCmmOp bid mop res args MO_Memmove _ -> fsLit "memmove" MO_Memcmp _ -> fsLit "memcmp" + MO_SuspendThread -> fsLit "suspendThread" + MO_ResumeThread -> fsLit "resumeThread" + MO_PopCnt _ -> fsLit "popcnt" MO_BSwap _ -> fsLit "bswap" {- Here the C implementation is used as there is no x86 -- cgit v1.2.1