Startup¶
When a Dylan library (either a shared library/DLL or executable) is loaded, a number of initialization tasks need to take place:
- The Dylan run-time facilities, including the garbage collector and the main thread’s thread environment block (TEB), need to be initialized if they haven’t already been. 
- The final addresses of any - <symbol>objects referenced by the library need to be resolved, and data locations that reference symbols need to be patched to point to the resolved addresses. This is part of the “for-system” initialization.
- Top-level forms in each of the library’s source files need to be evaluated. This is the “for-user” initialization. 
The following describes how Dylan libraries are initialized under the different compiler back-ends.
LLVM¶
Initialization for programs compiled by the LLVM back-end relies on constructor functions, provided on most platforms to support (among other things) C++ constructors. The LLVM linker makes use of two different constructor priorities, system (priority 0) and user (priority 65535).
The first constructor generated at system priority within the
_glue.bc file generated for the dylan library is a call to
_Init_Run_Time, a C function defined in
sources/lib/run-time/llvm-runtime-init.c to initialize the garbage
collector and other system facilities needed by the Dylan run-time.
For each compile unit that requires it, a constructor at system priority is generated to do for-system initialization:
- When - <symbol>resolution is required, a call to- primitive-symbol-fixupis generated, passing a table of symbols to resolve and reference addresses to patch.
- If there are any system initializers in the compile unit, calls to these are also generated. These normally only occur when a class definition depends on non-static values. 
The remaining for-user initialization is done in the per-library
startup glue function, named _Init_mangled-library-name, where
mangled-library-name is the Dylan library name transformed by name
mangling. This function, generated in _glue.bc by emit-gluefile
in sources/dfmc/llvm-linker/llvm-gluefile.dylan, does the following:
- For all libraries except the Dylan library, checks whether the - *argv*runtime variable is initialized, and exits if it is not
- Checks a flag to see if the library initialization has already been done, and exits if it has 
- Sets the initialization flag 
- Calls the library startup glue functions of all libraries (except for the Dylan library) referenced by this one. 
- Calls the library’s self-init function, named - _Init_mangled-library-name- _X, which in turn calls each of the for-user init functions for each compile-unit in the library. These contain the code generated for all of the top-level forms.
- For the Dylan library only, the self-init function also calls the - %install-boot-symbolsfunction defined in- sources/dylan/symbol-table.dylan.
The startup glue function is called from a global constructor at user
priority. For the Dylan library, its execution is not delayed until
the *argv* variable is initialized (as it is for other
libraries). This ensures that the %install-boot-symbols is
performed before other libraries’ symbol resolution begins.
For executables, execution begins at the usual main entry
point. The main function, generated in _main.bc by
emit-gluefile in sources/dfmc/llvm-linker/llvm-gluefile.dylan,
simply stores its argc and argv arguments in *argc* and
*argv* runtime variables and calls the library startup glue
function.
The combination of these mechanisms results in the following execution order:
- _Init_Run_Timeis called from a Dylan-library system-priority constructor.
- The symbol fixups for the Dylan library are performed (using the slower - primitive-resolve-symbol).
- The for-user (top-level form) initializations for the Dylan library are performed. 
- %install-boot-symbolsis called, enabling the faster symbol resolver.
- Symbol fixups and other for-system initializations for other libraries are performed via their system-priority constructors. 
- The - mainentry point of the executable is entered, setting the- *argc*and- *argv*runtime variables.
- The for-user (top-level form) initializations are performed for the other libraries in dependency order. 
- Any new libraries subsequently loaded using - load-librarywill be initialized via constructors (system-priority first, then user-priority).
HARP (Win32)¶
When a Win32 DLL compiled by the Open Dylan HARP back-end is loaded,
execution starts at mangled-library-nameDll@12, where
mangled-library-name is the Dylan library name transformed by name
mangling. This entry point, generated for each library by
emit-executable-entry-points in
sources/dfmc/harp-native-cg/linker.dylan, stores the address of
the library’s glue function, named _Init_mangled-library-name, into the
_init_dylan_library variable and branches to _DylanDllEntry@12.
A DllMain entry point
receives three arguments: the module handle of the DLL, a reason code,
and a flag that indicates whether the DLL was loaded statically or
dynamically. The _DylanDllEntry@12 routine, generated in sources/harp/x86-windows-rtg/ffi-barrier.dylan, looks at the reason
code to determine what to do:
- For process attach, the routine: - Stores the module handle in a DLL-local - _module_hInstancevariable.
- Allocates and initializes the TEB and GC-TEB, and initializes the garbage collector by calling - dylan_init_memory_managerand- dylan_mm_register_thread(- DxDYLAN.dllonly).
- Calls - _dylan_initialize(described below)
 
- For thread attach, the routine clears the TLV vector slot of the TEB ( - DxDYLAN.dllonly).
- For thread detach, the routine: - Deregisters the thread by calling - dylan_mm_deregister_thread_from_teb(- DxDYLAN.dllonly).
- Dealocates the TEB ( - DxDYLAN.dllonly)
 
- For process detach, - Deregisters the main thread by calling - dylan_mm_deregister_thread_from_teb(- DxDYLAN.dllonly).
- Deinitializes the garbage collector by calling - dylan_shut_down_memory_manager(- DxDYLAN.dllonly).
 
The _dylan_initialize function (generated in
sources/harp/native-rtg/ffi-barrier.dylan):
- Calls the runtime’s - init_dylan_datafunction, which:- Calls - primitive_fixup_unimported_dylan_data
- Calls - primitive_fixup_imported_dylan_data
- Calls - primitive_register_traced_roots
 
- Sets the FFI barrier state to - $inside-dylan.
- Calls - dylan_init_thread_local(which tail-calls the- dylan_init_threadC function defined in- sources/lib/run-time/exceptions.c) passing a pointer to the- call_init_dylanfunction. This function in turn is called as an MPS trampoline.
- Resets the FFI barrier state to - $outside-dylan.
The call_init_dylan function retrieves the value of the
_init_dylan_library variable (pointing to a library startup glue
function) and performs an indirect call.
Similarly, an Win32 executable starts execution at
mangled-library-nameExe. This routine, which is also generated by
emit-executable-entry-points, stores the address of
_Init_mangled-library-name in the
_init_dylan_library variable and branches to dylan_main.