diff options
| author | Elliott Slaughter <eslaughter@mozilla.com> | 2012-07-16 12:28:15 -0700 |
|---|---|---|
| committer | Elliott Slaughter <eslaughter@mozilla.com> | 2012-09-07 09:21:21 -0700 |
| commit | 3f0d207b3251e598488588765b942bf6b7a4f9bb (patch) | |
| tree | 98fad8b4761bb95d63615e7e2217ca559bd4962a /src/rustc | |
| parent | fb8786fe522ed96172cf1ae8e205e3f2722e834c (diff) | |
| download | rust-3f0d207b3251e598488588765b942bf6b7a4f9bb.tar.gz rust-3f0d207b3251e598488588765b942bf6b7a4f9bb.zip | |
gc: Add stack walker for new garbage collector.
Safe points are exported in a per-module list via the crate map. A C runtime call walks the crate map at startup and aggregates the list of safe points for the program. Currently the GC doesn't actually deallocate memory on malloc and free. Adding the GC at this stage is primarily of testing value. The GC does attempt to clean up exchange heap and stack-allocated resource on failure. A result of this patch is that the user now needs to be careful about what code they write in destructors, because the GC and/or failure cleanup may need to call destructors. Specifically, calls to malloc are considered unsafe and may result in infinite loops or segfaults.
Diffstat (limited to 'src/rustc')
| -rw-r--r-- | src/rustc/middle/trans/base.rs | 17 | ||||
| -rw-r--r-- | src/rustc/middle/trans/common.rs | 4 |
2 files changed, 21 insertions, 0 deletions
diff --git a/src/rustc/middle/trans/base.rs b/src/rustc/middle/trans/base.rs index acf51691a96..315b496e661 100644 --- a/src/rustc/middle/trans/base.rs +++ b/src/rustc/middle/trans/base.rs @@ -1595,6 +1595,7 @@ fn trans_closure(ccx: @crate_ctxt, path: path, decl: ast::fn_decl, do str::as_c_str("generic") |strategy| { llvm::LLVMSetGC(fcx.llfn, strategy); } + ccx.uses_gc = true; } // Create the first basic block in the function and keep a handle on it to @@ -2438,6 +2439,20 @@ fn gather_rtcalls(ccx: @crate_ctxt, crate: @ast::crate) { } } +fn decl_gc_metadata(ccx: @crate_ctxt, llmod_id: ~str) { + if !ccx.sess.opts.gc || !ccx.uses_gc { + return; + } + + let gc_metadata_name = ~"_gc_module_metadata_" + llmod_id; + let gc_metadata = do str::as_c_str(gc_metadata_name) |buf| { + llvm::LLVMAddGlobal(ccx.llmod, T_i32(), buf) + }; + llvm::LLVMSetGlobalConstant(gc_metadata, True); + lib::llvm::SetLinkage(gc_metadata, lib::llvm::ExternalLinkage); + ccx.module_data.insert(~"_gc_module_metadata", gc_metadata); +} + fn create_module_map(ccx: @crate_ctxt) -> ValueRef { let elttype = T_struct(~[ccx.int_type, ccx.int_type]); let maptype = T_array(elttype, ccx.module_data.size() + 1u); @@ -2679,6 +2694,7 @@ fn trans_crate(sess: session::session, builder: BuilderRef_res(llvm::LLVMCreateBuilder()), shape_cx: mk_ctxt(llmod), crate_map: crate_map, + mut uses_gc: false, dbg_cx: dbg_cx, class_ctors: int_hash::<ast::def_id>(), mut do_not_commit_warning_issued: false}; @@ -2696,6 +2712,7 @@ fn trans_crate(sess: session::session, trans_mod(ccx, crate.node.module); } + decl_gc_metadata(ccx, llmod_id); fill_crate_map(ccx, crate_map); // NB: Must call force_declare_tydescs before emit_tydescs to break // cyclical dependency with shape code! See shape.rs for details. diff --git a/src/rustc/middle/trans/common.rs b/src/rustc/middle/trans/common.rs index 6b3e4063d67..7e612051565 100644 --- a/src/rustc/middle/trans/common.rs +++ b/src/rustc/middle/trans/common.rs @@ -162,6 +162,10 @@ type crate_ctxt = { builder: BuilderRef_res, shape_cx: shape::ctxt, crate_map: ValueRef, + // Set when at least one function uses GC. Needed so that + // decl_gc_metadata knows whether to link to the module metadata, which + // is not emitted by LLVM's GC pass when no functions use GC. + mut uses_gc: bool, dbg_cx: Option<debuginfo::debug_ctxt>, // Mapping from class constructors to parent class -- // used in base::trans_closure |
