+#endif
+
+/* -----------------------------------------------------------------------------
+ Module initialisation
+
+ The module initialisation code looks like this, roughly:
+
+ FN(__stginit_Foo) {
+ JMP_(__stginit_Foo_1_p)
+ }
+
+ FN(__stginit_Foo_1_p) {
+ ...
+ }
+
+ We have one version of the init code with a module version and the
+ 'way' attached to it. The version number helps to catch cases
+ where modules are not compiled in dependency order before being
+ linked: if a module has been compiled since any modules which depend on
+ it, then the latter modules will refer to a different version in their
+ init blocks and a link error will ensue.
+
+ The 'way' suffix helps to catch cases where modules compiled in different
+ ways are linked together (eg. profiled and non-profiled).
+
+ We provide a plain, unadorned, version of the module init code
+ which just jumps to the version with the label and way attached. The
+ reason for this is that when using foreign exports, the caller of
+ startupHaskell() must supply the name of the init function for the "top"
+ module in the program, and we don't want to require that this name
+ has the version and way info appended to it.
+ -------------------------------------------------------------------------- */
+
+#define PUSH_INIT_STACK(reg_function) \
+ *(Sp++) = (W_)reg_function
+
+#define POP_INIT_STACK() \
+ *(--Sp)
+
+#define MOD_INIT_WRAPPER(label,real_init) \
+
+
+#define START_MOD_INIT(plain_lbl, real_lbl) \
+ static int _module_registered = 0; \
+ EF_(real_lbl); \
+ FN_(plain_lbl) { \
+ FB_ \
+ JMP_(real_lbl); \
+ FE_ \
+ } \
+ FN_(real_lbl) { \
+ FB_; \
+ if (! _module_registered) { \
+ _module_registered = 1; \
+ {
+ /* extern decls go here, followed by init code */
+
+#define REGISTER_FOREIGN_EXPORT(reg_fe_binder) \
+ STGCALL1(getStablePtr,reg_fe_binder)
+
+#define REGISTER_IMPORT(reg_mod_name) \
+ PUSH_INIT_STACK(reg_mod_name)
+
+#define END_MOD_INIT() \
+ }}; \
+ JMP_(POP_INIT_STACK()); \
+ FE_ }
+
+/* -----------------------------------------------------------------------------
+ Support for _ccall_GC_ and _casm_GC.
+ -------------------------------------------------------------------------- */
+
+/*
+ * Suspending/resuming threads for doing external C-calls (_ccall_GC).
+ * These functions are defined in rts/Schedule.c.
+ */
+StgInt suspendThread ( StgRegTable *, rtsBool);
+StgRegTable * resumeThread ( StgInt, rtsBool );
+
+#define SUSPEND_THREAD(token,threaded) \
+ SaveThreadState(); \
+ token = suspendThread(BaseReg,threaded);
+
+#ifdef SMP
+#define RESUME_THREAD(token,threaded) \
+ BaseReg = resumeThread(token,threaded); \
+ LoadThreadState();
+#else
+#define RESUME_THREAD(token,threaded) \
+ (void)resumeThread(token,threaded); \
+ LoadThreadState();
+#endif
+