summaryrefslogtreecommitdiff
path: root/rts/PrimOps.cmm
diff options
context:
space:
mode:
authorSimon Marlow <marlowsd@gmail.com>2014-01-16 11:55:25 +0000
committerSimon Marlow <marlowsd@gmail.com>2014-01-16 13:19:05 +0000
commiteaa37a0f69df28f051e7511d62dc104eb50a2a6b (patch)
tree3bdd681613ded1a1bfc2a37655c37ff0a39dafc8 /rts/PrimOps.cmm
parent11f5cd942e79afa7e6b21a4c084b19215ec72750 (diff)
downloadhaskell-eaa37a0f69df28f051e7511d62dc104eb50a2a6b.tar.gz
Add a way to reserve temporary stack space in high-level Cmm
We occasionally need to reserve some temporary memory in a primop for passing to a foreign function. We've been using the stack for this, but when we moved to high-level Cmm it became quite fragile because primops are in high-level Cmm and the stack is supposed to be under the control of the Cmm pipeline. So this change puts things on a firmer footing by adding a new Cmm construct 'reserve'. e.g. in decodeFloat_Int#: reserve 2 = tmp { mp_tmp1 = tmp + WDS(1); mp_tmp_w = tmp; /* Perform the operation */ ccall __decodeFloat_Int(mp_tmp1 "ptr", mp_tmp_w "ptr", arg); r1 = W_[mp_tmp1]; r2 = W_[mp_tmp_w]; } reserve is described in CmmParse.y. Unfortunately the argument to reserve must be a compile-time constant. We might have to extend the parser to allow expressions with arithmetic operators if this is too restrictive. Note also that the return instruction for the procedure must be outside the scope of the reserved stack area, so we have to extract the values from the reserved area before we close the scope. This means some more local variables (r1, r2 in the example above). The generated code is more or less identical to what we had before though.
Diffstat (limited to 'rts/PrimOps.cmm')
-rw-r--r--rts/PrimOps.cmm55
1 files changed, 33 insertions, 22 deletions
diff --git a/rts/PrimOps.cmm b/rts/PrimOps.cmm
index e539c7cde3..db65a4a268 100644
--- a/rts/PrimOps.cmm
+++ b/rts/PrimOps.cmm
@@ -571,44 +571,55 @@ stg_deRefWeakzh ( gcptr w )
stg_decodeFloatzuIntzh ( F_ arg )
{
W_ p;
- W_ mp_tmp1;
- W_ mp_tmp_w;
+ W_ tmp, mp_tmp1, mp_tmp_w, r1, r2;
STK_CHK_GEN_N (WDS(2));
- mp_tmp1 = Sp - WDS(1);
- mp_tmp_w = Sp - WDS(2);
+ reserve 2 = tmp {
- /* Perform the operation */
- ccall __decodeFloat_Int(mp_tmp1 "ptr", mp_tmp_w "ptr", arg);
+ mp_tmp1 = tmp + WDS(1);
+ mp_tmp_w = tmp;
+
+ /* Perform the operation */
+ ccall __decodeFloat_Int(mp_tmp1 "ptr", mp_tmp_w "ptr", arg);
+
+ r1 = W_[mp_tmp1];
+ r2 = W_[mp_tmp_w];
+ }
/* returns: (Int# (mantissa), Int# (exponent)) */
- return (W_[mp_tmp1], W_[mp_tmp_w]);
+ return (r1, r2);
}
stg_decodeDoublezu2Intzh ( D_ arg )
{
- W_ p;
- W_ mp_tmp1;
- W_ mp_tmp2;
- W_ mp_result1;
- W_ mp_result2;
+ W_ p, tmp;
+ W_ mp_tmp1, mp_tmp2, mp_result1, mp_result2;
+ W_ r1, r2, r3, r4;
STK_CHK_GEN_N (WDS(4));
- mp_tmp1 = Sp - WDS(1);
- mp_tmp2 = Sp - WDS(2);
- mp_result1 = Sp - WDS(3);
- mp_result2 = Sp - WDS(4);
-
- /* Perform the operation */
- ccall __decodeDouble_2Int(mp_tmp1 "ptr", mp_tmp2 "ptr",
- mp_result1 "ptr", mp_result2 "ptr",
- arg);
+ reserve 4 = tmp {
+
+ mp_tmp1 = tmp + WDS(3);
+ mp_tmp2 = tmp + WDS(2);
+ mp_result1 = tmp + WDS(1);
+ mp_result2 = tmp;
+
+ /* Perform the operation */
+ ccall __decodeDouble_2Int(mp_tmp1 "ptr", mp_tmp2 "ptr",
+ mp_result1 "ptr", mp_result2 "ptr",
+ arg);
+
+ r1 = W_[mp_tmp1];
+ r2 = W_[mp_tmp2];
+ r3 = W_[mp_result1];
+ r4 = W_[mp_result2];
+ }
/* returns:
(Int# (mant sign), Word# (mant high), Word# (mant low), Int# (expn)) */
- return (W_[mp_tmp1], W_[mp_tmp2], W_[mp_result1], W_[mp_result2]);
+ return (r1, r2, r3, r4);
}
/* -----------------------------------------------------------------------------