Commit a55d581f authored by Tamar Christina's avatar Tamar Christina Committed by Ben Gamari

Fix Windows stack allocations.

On Windows we use the function `win32AllocStack` to do stack
allocations in 4k blocks and insert a stack check afterwards
to ensure the allocation returned a valid block.

The problem is this function does something that by C semantics
is pointless. The stack allocated value can never escape the
function, and the stack isn't used so the compiler just optimizes
away the entire function body.

After considering a bunch of other possibilities I think the simplest
fix is to just disable optimizations for the function.

Alternatively inline assembly is an option but the stack check function
doesn't have a very portable name as it relies on e.g. `libgcc`.

Thanks to Sergey Vinokurov for helping diagnose and test.

Test Plan: ./validate

Reviewers: bgamari, erikd, simonmar

Reviewed By: bgamari

Subscribers: rwbarton, thomie, carter

GHC Trac Issues: #14669

Differential Revision: https://phabricator.haskell.org/D4343
parent 9a57cfeb
......@@ -204,6 +204,16 @@
#define STG_UNUSED GNUC3_ATTRIBUTE(__unused__)
/* Prevent functions from being optimized.
See Note [Windows Stack allocations] */
#if defined(__clang__)
#define STG_NO_OPTIMIZE __attribute__((optnone))
#elif defined(__GNUC__) || defined(__GNUG__)
#define STG_NO_OPTIMIZE __attribute__((optimize("O0")))
#else
#define STG_NO_OPTIMIZE /* nothing */
#endif
/* -----------------------------------------------------------------------------
Global type definitions
-------------------------------------------------------------------------- */
......
......@@ -99,11 +99,17 @@ StgFunPtr StgReturn(void)
#endif
#if defined(mingw32_HOST_OS)
// On windows the stack has to be allocated 4k at a time, otherwise
// we get a segfault. The C compiler knows how to do this (it calls
// _alloca()), so we make sure that we can allocate as much stack as
// we need:
StgWord8 *win32AllocStack(void)
/*
* Note [Windows Stack allocations]
*
* On windows the stack has to be allocated 4k at a time, otherwise
* we get a segfault. The C compiler knows how to do this (it calls
* _alloca()), so we make sure that we can allocate as much stack as
* we need. However since we are doing a local stack allocation and the value
* isn't valid outside the frame, compilers are free to optimize this allocation
* and the corresponding stack check away. So to prevent that we request that
* this function never be optimized (See #14669). */
STG_NO_OPTIMIZE StgWord8 *win32AllocStack(void)
{
StgWord8 stack[RESERVED_C_STACK_BYTES + 16 + 12];
return stack;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment