From d710f8ba1f2ef8b35d3603875b454955d2d2585c Mon Sep 17 00:00:00 2001
From: Vadim Chugunov <vadimcn@gmail.com>
Date: Wed, 21 Oct 2015 09:59:24 -0700
Subject: [PATCH] Moar comments.

---
 src/librustc_back/target/windows_base.rs |  6 ++--
 src/libstd/lib.rs                        |  9 -----
 src/libstd/rt.rs                         |  5 +++
 src/libstd/sys/common/unwind/gcc.rs      |  5 +++
 src/libstd/sys/common/unwind/mod.rs      | 43 ++++++++++++++----------
 src/rtstartup/rsbegin.rs                 | 21 +++++++++++-
 src/rtstartup/rsend.rs                   |  2 ++
 7 files changed, 60 insertions(+), 31 deletions(-)

diff --git a/src/librustc_back/target/windows_base.rs b/src/librustc_back/target/windows_base.rs
index fc1e192f1e1..4fa57726ef5 100644
--- a/src/librustc_back/target/windows_base.rs
+++ b/src/librustc_back/target/windows_base.rs
@@ -65,11 +65,11 @@ pub fn opts() -> TargetOptions {
             "-nostdlib".to_string(),
         ),
         pre_link_objects_exe: vec!(
-            "crt2.o".to_string(),
-            "rsbegin.o".to_string(),
+            "crt2.o".to_string(),    // mingw C runtime initialization for executables
+            "rsbegin.o".to_string(), // Rust compiler runtime initialization, see rsbegin.rs
         ),
         pre_link_objects_dll: vec!(
-            "dllcrt2.o".to_string(),
+            "dllcrt2.o".to_string(), // mingw C runtime initialization for dlls
             "rsbegin.o".to_string(),
         ),
         late_link_args: vec!(
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index f318cde71bd..a624b352126 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -400,15 +400,6 @@ pub mod __rand {
     pub use rand::{thread_rng, ThreadRng, Rng};
 }
 
-// Rust runtime's startup objects depend on these symbols, so they must be public.
-// Since sys_common isn't public, we have to re-export them here explicitly.
-#[doc(hidden)]
-#[unstable(feature = "eh_frame_registry", issue = "0")]
-#[cfg(all(target_os="windows", target_arch = "x86", target_env="gnu"))]
-pub mod __frame_registry {
-    pub use sys_common::unwind::imp::eh_frame_registry::*;
-}
-
 // Include a number of private modules that exist solely to provide
 // the rustdoc documentation for primitive types. Using `include!`
 // because rustdoc only looks for these modules at the crate level.
diff --git a/src/libstd/rt.rs b/src/libstd/rt.rs
index 8be0c6f3b3d..44961611b7b 100644
--- a/src/libstd/rt.rs
+++ b/src/libstd/rt.rs
@@ -32,6 +32,11 @@ use thread::{self, Thread};
 // Reexport some of our utilities which are expected by other crates.
 pub use sys_common::unwind::{begin_unwind, begin_unwind_fmt};
 
+// Rust runtime's startup objects depend on these symbols, so they must be public.
+// Since sys_common isn't public, we have to re-export them here.
+#[cfg(all(target_os="windows", target_arch = "x86", target_env="gnu"))]
+pub use sys_common::unwind::imp::eh_frame_registry::*;
+
 #[cfg(not(test))]
 #[lang = "start"]
 fn lang_start(main: *const u8, argc: isize, argv: *const *const u8) -> isize {
diff --git a/src/libstd/sys/common/unwind/gcc.rs b/src/libstd/sys/common/unwind/gcc.rs
index 6d82eb7dfb1..0a598b55951 100644
--- a/src/libstd/sys/common/unwind/gcc.rs
+++ b/src/libstd/sys/common/unwind/gcc.rs
@@ -232,6 +232,7 @@ pub mod eabi {
     }
 }
 
+// See docs in the `unwind` module.
 #[cfg(all(target_os="windows", target_arch = "x86", target_env="gnu", not(test)))]
 #[lang = "eh_unwind_resume"]
 #[unwind]
@@ -241,6 +242,10 @@ unsafe extern fn rust_eh_unwind_resume(panic_ctx: *mut u8) -> ! {
 
 #[cfg(all(target_os="windows", target_arch = "x86", target_env="gnu"))]
 pub mod eh_frame_registry {
+    // The implementation of stack unwinding is (for now) deferred to libgcc_eh, however Rust
+    // crates use these Rust-specific entry points to avoid potential clashes with GCC runtime.
+    // See also: rtbegin.rs, `unwind` module.
+
     #[link(name = "gcc_eh")]
     extern {
         fn __register_frame_info(eh_frame_begin: *const u8, object: *mut u8);
diff --git a/src/libstd/sys/common/unwind/mod.rs b/src/libstd/sys/common/unwind/mod.rs
index 3978aeb39bc..e42a4694070 100644
--- a/src/libstd/sys/common/unwind/mod.rs
+++ b/src/libstd/sys/common/unwind/mod.rs
@@ -34,28 +34,35 @@
 //! object being thrown, and to decide whether it should be caught at that stack
 //! frame.  Once the handler frame has been identified, cleanup phase begins.
 //!
-//! In the cleanup phase, personality routines invoke cleanup code associated
-//! with their stack frames (i.e. destructors).  Once stack has been unwound down
-//! to the handler frame level, unwinding stops and the last personality routine
-//! transfers control to its catch block.
+//! In the cleanup phase, the unwinder invokes each personality routine again.
+//! This time it decides which (if any) cleanup code needs to be run for
+//! the current stack frame.  If so, the control is transferred to a special branch
+//! in the function body, the "landing pad", which invokes destructors, frees memory,
+//! etc.  At the end of the landing pad, control is transferred back to the unwinder
+//! and unwinding resumes.
+//!
+//! Once stack has been unwound down to the handler frame level, unwinding stops
+//! and the last personality routine transfers control to the catch block.
+//!
+//! ## `eh_personality` and `eh_unwind_resume`
+//!
+//! These language items are used by the compiler when generating unwind info.
+//! The first one is the personality routine described above.  The second one
+//! allows compilation target to customize the process of resuming unwind at the
+//! end of the landing pads.  `eh_unwind_resume` is used only if `custom_unwind_resume`
+//! flag in the target options is set.
 //!
 //! ## Frame unwind info registration
 //!
-//! Each module has its own frame unwind info section (usually ".eh_frame"), and
-//! unwinder needs to know about all of them in order for unwinding to be able to
-//! cross module boundaries.
-//!
-//! On some platforms, like Linux, this is achieved by dynamically enumerating
-//! currently loaded modules via the dl_iterate_phdr() API and finding all
-//! .eh_frame sections.
-//!
+//! Each module's image contains a frame unwind info section (usually ".eh_frame").
+//! When a module is loaded/unloaded into the process, the unwinder must be informed
+//! about the location of this section in memory. The methods of achieving that vary
+//! by the platform.
+//! On some (e.g. Linux), the unwinder can discover unwind info sections on its own
+//! (by dynamically enumerating currently loaded modules via the dl_iterate_phdr() API
+//! and finding their ".eh_frame" sections);
 //! Others, like Windows, require modules to actively register their unwind info
-//! sections by calling __register_frame_info() API at startup.  In the latter
-//! case it is essential that there is only one copy of the unwinder runtime in
-//! the process.  This is usually achieved by linking to the dynamic version of
-//! the unwind runtime.
-//!
-//! Currently Rust uses unwind runtime provided by libgcc.
+//! sections via unwinder API (see `rust_eh_register_frames`/`rust_eh_unregister_frames`).
 
 #![allow(dead_code)]
 #![allow(unused_imports)]
diff --git a/src/rtstartup/rsbegin.rs b/src/rtstartup/rsbegin.rs
index 17684b74b70..af9a01ea2e4 100644
--- a/src/rtstartup/rsbegin.rs
+++ b/src/rtstartup/rsbegin.rs
@@ -8,8 +8,21 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// rsbegin.o and rsend.o are the so called "compiler runtime startup objects".
+// They contain code needed to correctly initialize the compiler runtime.
+//
+// When an executable or dylib image is linked, all user code and libraries are
+// "sandwiched" between these two object files, so code or data from rsbegin.o
+// become first in the respective sections of the image, whereas code and data
+// from rsend.o become the last ones.  This effect can be used to place symbols
+// at the beginning or at the end of a section, as well as to insert any required
+// headers or footers.
+//
+// Note that the actual module entry point is located in the C runtime startup
+// object (usually called `crtX.o), which then invokes initialization callbacks
+// of other runtime components (registered via yet another special image section).
+
 #![feature(no_std)]
-#![feature(linkage)]
 
 #![crate_type="rlib"]
 #![no_std]
@@ -20,27 +33,33 @@ pub mod eh_frames
 {
     #[no_mangle]
     #[link_section = ".eh_frame"]
+    // Marks beginning of the stack frame unwind info section
     pub static __EH_FRAME_BEGIN__: [u8; 0] = [];
 
     // Scratch space for unwinder's internal book-keeping.
     // This is defined as `struct object` in $GCC/libgcc/unwind-dw2-fde.h.
     static mut obj: [isize; 6] = [0; 6];
 
+    // Unwind info registration/deregistration routines.
+    // See the docs of `unwind` module in libstd.
     extern {
         fn rust_eh_register_frames(eh_frame_begin: *const u8, object: *mut u8);
         fn rust_eh_unregister_frames(eh_frame_begin: *const u8, object: *mut u8);
     }
 
     unsafe fn init() {
+        // register unwind info on module startup
         rust_eh_register_frames(&__EH_FRAME_BEGIN__ as *const u8,
                                 &mut obj as *mut _ as *mut u8);
     }
 
     unsafe fn uninit() {
+        // unregister on shutdown
         rust_eh_unregister_frames(&__EH_FRAME_BEGIN__ as *const u8,
                                   &mut obj as *mut _ as *mut u8);
     }
 
+    // MSVC-specific init/uninit routine registration
     pub mod ms_init
     {
         // .CRT$X?? sections are roughly analogous to ELF's .init_array and .fini_array,
diff --git a/src/rtstartup/rsend.rs b/src/rtstartup/rsend.rs
index df7759877e9..ecb6a228e17 100644
--- a/src/rtstartup/rsend.rs
+++ b/src/rtstartup/rsend.rs
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// See rsbegin.rs for details.
+
 #![feature(no_std)]
 
 #![crate_type="rlib"]