cmm: Expose machine's stack and return address register
authorBen Gamari <ben@smart-cactus.org>
Wed, 26 Aug 2015 22:36:59 +0000 (00:36 +0200)
committerBen Gamari <ben@smart-cactus.org>
Sun, 1 Nov 2015 14:19:47 +0000 (15:19 +0100)
We will need to use these to setup proper unwinding information for the
stg_stop_thread closure. This pokes a hole in the STG abstraction,
exposing the machine's stack pointer register so that we can accomplish
this. We also expose a dummy return address register, which corresponds
to the register used to hold the DWARF return address.

Differential Revision: https://phabricator.haskell.org/D1225

compiler/cmm/CmmExpr.hs
compiler/cmm/CmmLex.x
compiler/cmm/PprCmmExpr.hs
compiler/codeGen/CgUtils.hs
compiler/llvmGen/LlvmCodeGen/Regs.hs
compiler/nativeGen/Dwarf/Types.hs
includes/CodeGen.Platform.hs
includes/stg/MachRegs.h

index 10d0874..8a86bb4 100644 (file)
@@ -459,6 +459,15 @@ data GlobalReg
   -- (where necessary) in the native code generator.
   | BaseReg
 
+  -- The register used by the platform for the C stack pointer. This is
+  -- a break in the STG abstraction used exclusively to setup stack unwinding
+  -- information.
+  | MachSp
+
+  -- The is a dummy register used to indicate to the stack unwinder where
+  -- a routine would return to.
+  | UnwindReturnReg
+
   -- Base Register for PIC (position-independent code) calculations
   -- Only used inside the native code generator. It's exact meaning differs
   -- from platform to platform (see module PositionIndependentCode).
@@ -486,6 +495,8 @@ instance Eq GlobalReg where
    GCEnter1 == GCEnter1 = True
    GCFun == GCFun = True
    BaseReg == BaseReg = True
+   MachSp == MachSp = True
+   UnwindReturnReg == UnwindReturnReg = True
    PicBaseReg == PicBaseReg = True
    _r1 == _r2 = False
 
@@ -510,6 +521,8 @@ instance Ord GlobalReg where
    compare GCEnter1 GCEnter1 = EQ
    compare GCFun GCFun = EQ
    compare BaseReg BaseReg = EQ
+   compare MachSp MachSp = EQ
+   compare UnwindReturnReg UnwindReturnReg = EQ
    compare PicBaseReg PicBaseReg = EQ
    compare (VanillaReg _ _) _ = LT
    compare _ (VanillaReg _ _) = GT
@@ -547,6 +560,10 @@ instance Ord GlobalReg where
    compare _ GCFun = GT
    compare BaseReg _ = LT
    compare _ BaseReg = GT
+   compare MachSp _ = LT
+   compare _ MachSp = GT
+   compare UnwindReturnReg _ = LT
+   compare _ UnwindReturnReg = GT
    compare EagerBlackholeInfo _ = LT
    compare _ EagerBlackholeInfo = GT
 
index a9ad3e5..175259a 100644 (file)
@@ -110,6 +110,8 @@ $white_no_nl+           ;
   CurrentNursery        { global_reg CurrentNursery }
   HpAlloc               { global_reg HpAlloc }
   BaseReg               { global_reg BaseReg }
+  MachSp                { global_reg MachSp }
+  UnwindReturnReg       { global_reg UnwindReturnReg }
 
   $namebegin $namechar* { name }
 
index 0bb79ac..1f1c7f8 100644 (file)
@@ -262,6 +262,8 @@ pprGlobalReg gr
         SpLim          -> ptext (sLit "SpLim")
         Hp             -> ptext (sLit "Hp")
         HpLim          -> ptext (sLit "HpLim")
+        MachSp         -> ptext (sLit "MachSp")
+        UnwindReturnReg-> ptext (sLit "UnwindReturnReg")
         CCCS           -> ptext (sLit "CCCS")
         CurrentTSO     -> ptext (sLit "CurrentTSO")
         CurrentNursery -> ptext (sLit "CurrentNursery")
index 51b8ed9..a197312 100644 (file)
@@ -86,6 +86,8 @@ baseRegOffset dflags GCEnter1            = oFFSET_stgGCEnter1 dflags
 baseRegOffset dflags GCFun               = oFFSET_stgGCFun dflags
 baseRegOffset _      BaseReg             = panic "baseRegOffset:BaseReg"
 baseRegOffset _      PicBaseReg          = panic "baseRegOffset:PicBaseReg"
+baseRegOffset _      MachSp              = panic "baseRegOffset:MachSp"
+baseRegOffset _      UnwindReturnReg     = panic "baseRegOffset:UnwindReturnReg"
 
 
 -- -----------------------------------------------------------------------------
index 0048659..8ac4153 100644 (file)
@@ -76,6 +76,7 @@ lmGlobalReg dflags suf reg
         ZmmReg 4       -> zmmGlobal $ "ZMM4" ++ suf
         ZmmReg 5       -> zmmGlobal $ "ZMM5" ++ suf
         ZmmReg 6       -> zmmGlobal $ "ZMM6" ++ suf
+        MachSp         -> wordGlobal $ "MachSp" ++ suf
         _other         -> panic $ "LlvmCodeGen.Reg: GlobalReg (" ++ (show reg)
                                 ++ ") not supported!"
         -- LongReg, HpLim, CCSS, CurrentTSO, CurrentNusery, HpAlloc
index bd423b6..abded88 100644 (file)
@@ -337,7 +337,8 @@ pprFrameBlock oldUws (DwarfFrameBlock blockLbl hasInfo uws)
 
 -- | Get DWARF register ID for a given GlobalReg
 dwarfGlobalRegNo :: Platform -> GlobalReg -> Word8
-dwarfGlobalRegNo p = maybe 0 (dwarfRegNo p . RegReal) . globalRegMaybe p
+dwarfGlobalRegNo p UnwindReturnReg = dwarfReturnRegNo p
+dwarfGlobalRegNo p reg = maybe 0 (dwarfRegNo p . RegReal) $ globalRegMaybe p reg
 
 -- | Generate code for setting the unwind information for a register,
 -- optimized using its known old value in the table. Note that "Sp" is
index b41ad54..46550af 100644 (file)
@@ -815,6 +815,9 @@ globalRegMaybe CurrentTSO               = Just (RealRegSingle REG_CurrentTSO)
 # ifdef REG_CurrentNursery
 globalRegMaybe CurrentNursery           = Just (RealRegSingle REG_CurrentNursery)
 # endif
+# ifdef REG_MachSp
+globalRegMaybe MachSp                   = Just (RealRegSingle REG_MachSp)
+# endif
 globalRegMaybe _                        = Nothing
 #elif MACHREGS_NO_REGS
 globalRegMaybe _ = Nothing
index b709027..b1a0ef0 100644 (file)
 #if STOLEN_X86_REGS >= 4
 # define REG_Hp     edi
 #endif
+#define REG_MachSp  esp
 
 #define REG_XMM1    xmm0
 #define REG_XMM2    xmm1
 #define REG_R5    r8
 #define REG_R6    r9
 #define REG_SpLim r15
+#define REG_MachSp  rsp
 
 /*
 Map both Fn and Dn to register xmmn so that we can pass a function any