summaryrefslogtreecommitdiff
path: root/compiler/cmm
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/cmm')
-rw-r--r--compiler/cmm/CmmLex.x4
-rw-r--r--compiler/cmm/CmmParse.y25
2 files changed, 28 insertions, 1 deletions
diff --git a/compiler/cmm/CmmLex.x b/compiler/cmm/CmmLex.x
index 1b823ccb09..bb5b4e3ae5 100644
--- a/compiler/cmm/CmmLex.x
+++ b/compiler/cmm/CmmLex.x
@@ -152,6 +152,7 @@ data CmmToken
| CmmT_foreign
| CmmT_never
| CmmT_prim
+ | CmmT_reserve
| CmmT_return
| CmmT_returns
| CmmT_import
@@ -234,7 +235,8 @@ reservedWordsFM = listToUFM $
( "foreign", CmmT_foreign ),
( "never", CmmT_never ),
( "prim", CmmT_prim ),
- ( "return", CmmT_return ),
+ ( "reserve", CmmT_reserve ),
+ ( "return", CmmT_return ),
( "returns", CmmT_returns ),
( "import", CmmT_import ),
( "switch", CmmT_switch ),
diff --git a/compiler/cmm/CmmParse.y b/compiler/cmm/CmmParse.y
index a0c9bc4eb5..8438198f7d 100644
--- a/compiler/cmm/CmmParse.y
+++ b/compiler/cmm/CmmParse.y
@@ -89,6 +89,19 @@ High-level only:
- pushing stack frames:
push (info_ptr, field1, ..., fieldN) { ... statements ... }
+ - reserving temporary stack space:
+
+ reserve N = x { ... }
+
+ this reserves an area of size N (words) on the top of the stack,
+ and binds its address to x (a local register). Typically this is
+ used for allocating temporary storage for passing to foreign
+ functions.
+
+ Note that if you make any native calls or invoke the GC in the
+ scope of the reserve block, you are responsible for ensuring that
+ the stack you reserved is laid out correctly with an info table.
+
Low-level only:
- References to Sp, R1-R8, F1-F4 etc.
@@ -302,6 +315,7 @@ import Data.Maybe
'foreign' { L _ (CmmT_foreign) }
'never' { L _ (CmmT_never) }
'prim' { L _ (CmmT_prim) }
+ 'reserve' { L _ (CmmT_reserve) }
'return' { L _ (CmmT_return) }
'returns' { L _ (CmmT_returns) }
'import' { L _ (CmmT_import) }
@@ -614,6 +628,8 @@ stmt :: { CmmParse () }
{ cmmIfThenElse $2 $4 $6 }
| 'push' '(' exprs0 ')' maybe_body
{ pushStackFrame $3 $5 }
+ | 'reserve' INT '=' lreg maybe_body
+ { reserveStackFrame (fromIntegral $2) $4 $5 }
foreignLabel :: { CmmParse CmmExpr }
: NAME { return (CmmLit (CmmLabel (mkForeignLabel $1 Nothing ForeignLabelInThisPackage IsFunction))) }
@@ -1060,6 +1076,15 @@ pushStackFrame fields body = do
emit g
withUpdFrameOff new_updfr_off body
+reserveStackFrame :: Int -> CmmParse CmmReg -> CmmParse () -> CmmParse ()
+reserveStackFrame size preg body = do
+ dflags <- getDynFlags
+ old_updfr_off <- getUpdFrameOff
+ reg <- preg
+ let frame = old_updfr_off + wORD_SIZE dflags * size
+ emitAssign reg (CmmStackSlot Old frame)
+ withUpdFrameOff frame body
+
profilingInfo dflags desc_str ty_str
= if not (gopt Opt_SccProfilingOn dflags)
then NoProfilingInfo