; cmm_init <- getCmm (mkModuleInit dflags way cost_centre_info
this_mod mb_main_mod
foreign_stubs imported_mods)
- ; return (cmm_binds ++ concat cmm_tycons
- ++ if opt_SccProfilingOn
-#if defined(mingw32_HOST_OS)
- || True
-#endif
- then [cmm_init]
- else [])
+ ; return (cmm_binds ++ concat cmm_tycons ++ [cmm_init])
}
-- Put datatype_stuff after code_stuff, because the
-- datatype closure table (for enumeration types) to
-> Code
mkModuleInit dflags way cost_centre_info this_mod mb_main_mod foreign_stubs imported_mods
= do {
-
- -- Allocate the static boolean that records if this
- -- module has been registered already
- ; emitData Data [CmmDataLabel moduleRegdLabel,
- CmmStaticLit zeroCLit]
-
- ; emitSimpleProc real_init_lbl $ do
- { -- The return-code pops the work stack by
- -- incrementing Sp, and then jumpd to the popped item
- ret_blk <- forkLabelledCode $ stmtsC
- [ CmmAssign spReg (cmmRegOffW spReg 1)
- , CmmJump (CmmLoad (cmmRegOffW spReg (-1)) wordRep) [] ]
-
- ; init_blk <- forkLabelledCode $ do
- { mod_init_code; stmtC (CmmBranch ret_blk) }
-
- ; stmtC (CmmCondBranch (cmmNeWord (CmmLit zeroCLit) mod_reg_val)
- ret_blk)
- ; stmtC (CmmBranch init_blk)
- }
-
+ if need_init_code
+ then do { -- Allocate the static boolean that records if this
+ -- module has been registered already
+ emitData Data [CmmDataLabel moduleRegdLabel,
+ CmmStaticLit zeroCLit]
+
+ ; emitSimpleProc real_init_lbl $ do
+ { ret_blk <- forkLabelledCode ret_code
+
+ ; init_blk <- forkLabelledCode $ do
+ { mod_init_code; stmtC (CmmBranch ret_blk) }
+
+ ; stmtC (CmmCondBranch (cmmNeWord (CmmLit zeroCLit) mod_reg_val)
+ ret_blk)
+ ; stmtC (CmmBranch init_blk)
+ }
+ }
+ else emitSimpleProc real_init_lbl ret_code
-- Make the "plain" procedure jump to the "real" init procedure
; emitSimpleProc plain_init_lbl jump_to_init
-- Now do local stuff
#if defined(mingw32_HOST_OS)
- ; registerForeignExports foreign_stubs
+ -- ... until the GHCi Linker can load files with constructor functions:
+ ; registerForeignExports foreign_stubs
#endif
; initCostCentres cost_centre_info
; mapCs (registerModuleImport dflags way)
(imported_mods++extra_imported_mods)
}
+ -- The return-code pops the work stack by
+ -- incrementing Sp, and then jumpd to the popped item
+ ret_code = stmtsC [ CmmAssign spReg (cmmRegOffW spReg 1)
+ , CmmJump (CmmLoad (cmmRegOffW spReg (-1)) wordRep) [] ]
+
+#if defined(mingw32_HOST_OS)
+ need_init_code = True
+#else
+ need_init_code = opt_SccProfilingOn
+#endif
-----------------------
registerModuleImport :: DynFlags -> String -> Module -> Code
Nothing -> empty
Just hs_fn -> text "extern StgClosure " <> ppr hs_fn <> text "_closure" <> semi
+
+ -- Initialise foreign exports by registering a stable pointer from an
+ -- __attribute__((constructor)) function.
+ -- The alternative is to do this from stginit functions generated in
+ -- codeGen/CodeGen.lhs; however, stginit functions have a negative impact
+ -- on binary sizes and link times because the static linker will think that
+ -- all modules that are imported directly or indirectly are actually used by
+ -- the program.
+ -- (this is bad for big umbrella modules like Graphics.Rendering.OpenGL)
+
-- the only reason for making the mingw32 (anything targetting PE, really) stick
-- out here is that the GHCi linker isn't capable of handling .ctors sections
useStaticConstructors
SchedulerStatus status;
/* all GranSim/GUM init is done in startupHaskell; sets IAmMainThread! */
-#if defined(PROFILING) || defined(mingw32_HOST_OS)
- /* mingw32 and PROFILING (still) define __stginits in .text */
startupHaskell(argc,argv,__stginit_ZCMain);
-#else
- startupHaskell(argc,argv,NULL);
-#endif
/* Register this thread as a task, so we can get timing stats about it */
#if defined(RTS_SUPPORTS_THREADS)