about summary refs log tree commit diff
path: root/src/comp
diff options
context:
space:
mode:
authorPatrick Walton <pcwalton@mimiga.net>2011-06-18 18:43:07 -0700
committerPatrick Walton <pcwalton@mimiga.net>2011-06-18 18:43:07 -0700
commit4f13879218c736e77350d56b9a053d3f009e2ddb (patch)
tree8fae1b9a8baf7664e3e8d77271db1ad8c520654f /src/comp
parent877f001512b2ce16d86d5d4cf16d81e509294d79 (diff)
downloadrust-4f13879218c736e77350d56b9a053d3f009e2ddb.tar.gz
rust-4f13879218c736e77350d56b9a053d3f009e2ddb.zip
rustc: Allocate derived tydescs before dynamically sized allocas
Diffstat (limited to 'src/comp')
-rw-r--r--src/comp/middle/trans.rs112
1 files changed, 74 insertions, 38 deletions
diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs
index eb1e1fd6a56..f2e35ad0546 100644
--- a/src/comp/middle/trans.rs
+++ b/src/comp/middle/trans.rs
@@ -191,20 +191,28 @@ type fn_ctxt =
         // administrative activities that have to happen in only one place in
         // the function, due to LLVM's quirks.
 
-        // A block for all the function's allocas, so that LLVM will coalesce
-        // them into a single alloca call.
-        mutable BasicBlockRef llallocas,
+        // A block for all the function's static allocas, so that LLVM will
+        // coalesce them into a single alloca call.
+        mutable BasicBlockRef llstaticallocas,
 
         // A block containing code that copies incoming arguments to space
-        // already allocated by code in the llallocas block.  (LLVM requires
-        // that arguments be copied to local allocas before allowing most any
-        // operation to be performed on them.)
+        // already allocated by code in one of the llallocas blocks.  (LLVM
+        // requires that arguments be copied to local allocas before allowing
+        // most any operation to be performed on them.)
         mutable BasicBlockRef llcopyargs,
 
-        // A block containing derived tydescs received from the runtime.  See
-        // description of derived_tydescs, below.
+        // The first block containing derived tydescs received from the
+        // runtime.  See description of derived_tydescs, below.
+        mutable BasicBlockRef llderivedtydescs_first,
+
+        // The last block of the llderivedtydescs group.
         mutable BasicBlockRef llderivedtydescs,
 
+        // A block for all of the dynamically sized allocas.  This must be
+        // after llderivedtydescs, because these sometimes depend on
+        // information computed from derived tydescs.
+        mutable BasicBlockRef lldynamicallocas,
+
         // FIXME: Is llcopyargs actually the block containing the allocas for
         // incoming function arguments?  Or is it merely the block containing
         // code that copies incoming args to space already alloca'd by code in
@@ -1173,11 +1181,11 @@ fn align_of(&@block_ctxt cx, &ty::t t) -> result {
 }
 
 fn alloca(&@block_ctxt cx, TypeRef t) -> ValueRef {
-    ret new_builder(cx.fcx.llallocas).Alloca(t);
+    ret new_builder(cx.fcx.llstaticallocas).Alloca(t);
 }
 
 fn array_alloca(&@block_ctxt cx, TypeRef t, ValueRef n) -> ValueRef {
-    ret new_builder(cx.fcx.llallocas).ArrayAlloca(t, n);
+    ret new_builder(cx.fcx.lldynamicallocas).ArrayAlloca(t, n);
 }
 
 
@@ -3556,7 +3564,7 @@ mod ivec {
 
         auto bcx;
         if (dynamic) {
-            bcx = llallocas_block_ctxt(cx.fcx);
+            bcx = llderivedtydescs_block_ctxt(cx.fcx);
         } else {
             bcx = cx;
         }
@@ -3565,26 +3573,25 @@ mod ivec {
         auto rslt = size_of(bcx, unit_ty);
         bcx = rslt.bcx;
         llunitsz = rslt.val;
-        if (dynamic) { bcx.fcx.llallocas = bcx.llbb; }
+
+        if (dynamic) { cx.fcx.llderivedtydescs = bcx.llbb; }
 
         auto llalen = bcx.build.Mul(llunitsz,
                                     C_uint(abi::ivec_default_length));
 
         auto llptr;
         auto llunitty = type_of_or_i8(bcx, unit_ty);
+        auto bcx_result;
         if (dynamic) {
             auto llarraysz = bcx.build.Add(llsize_of(T_opaque_ivec()),
                                            llalen);
             auto llvecptr = array_alloca(bcx, T_i8(), llarraysz);
-            llptr = bcx.build.PointerCast(llvecptr, T_ptr(T_opaque_ivec()));
-        } else {
-            llptr = alloca(bcx, T_ivec(llunitty));
-        }
 
-        auto bcx_result;
-        if (dynamic) {
             bcx_result = cx;
+            llptr = bcx_result.build.PointerCast(llvecptr,
+                                                 T_ptr(T_opaque_ivec()));
         } else {
+            llptr = alloca(bcx, T_ivec(llunitty));
             bcx_result = bcx;
         }
 
@@ -6753,10 +6760,32 @@ iter block_locals(&ast::block b) -> @ast::local {
     }
 }
 
-fn llallocas_block_ctxt(&@fn_ctxt fcx) -> @block_ctxt {
+fn llstaticallocas_block_ctxt(&@fn_ctxt fcx) -> @block_ctxt {
+    let vec[cleanup] cleanups = [];
+    ret @rec(llbb=fcx.llstaticallocas,
+             build=new_builder(fcx.llstaticallocas),
+             parent=parent_none,
+             kind=SCOPE_BLOCK,
+             mutable cleanups=cleanups,
+             sp=fcx.sp,
+             fcx=fcx);
+}
+
+fn llderivedtydescs_block_ctxt(&@fn_ctxt fcx) -> @block_ctxt {
+    let vec[cleanup] cleanups = [];
+    ret @rec(llbb=fcx.llderivedtydescs,
+             build=new_builder(fcx.llderivedtydescs),
+             parent=parent_none,
+             kind=SCOPE_BLOCK,
+             mutable cleanups=cleanups,
+             sp=fcx.sp,
+             fcx=fcx);
+}
+
+fn lldynamicallocas_block_ctxt(&@fn_ctxt fcx) -> @block_ctxt {
     let vec[cleanup] cleanups = [];
-    ret @rec(llbb=fcx.llallocas,
-             build=new_builder(fcx.llallocas),
+    ret @rec(llbb=fcx.lldynamicallocas,
+             build=new_builder(fcx.lldynamicallocas),
              parent=parent_none,
              kind=SCOPE_BLOCK,
              mutable cleanups=cleanups,
@@ -6764,16 +6793,18 @@ fn llallocas_block_ctxt(&@fn_ctxt fcx) -> @block_ctxt {
              fcx=fcx);
 }
 
+
+
 fn alloc_ty(&@block_ctxt cx, &ty::t t) -> result {
     auto val = C_int(0);
     if (ty::type_has_dynamic_size(cx.fcx.lcx.ccx.tcx, t)) {
         // NB: we have to run this particular 'size_of' in a
-        // block_ctxt built on the llallocas block for the fn,
+        // block_ctxt built on the llderivedtydescs block for the fn,
         // so that the size dominates the array_alloca that
         // comes next.
 
-        auto n = size_of(llallocas_block_ctxt(cx.fcx), t);
-        cx.fcx.llallocas = n.bcx.llbb;
+        auto n = size_of(llderivedtydescs_block_ctxt(cx.fcx), t);
+        cx.fcx.llderivedtydescs = n.bcx.llbb;
         val = array_alloca(cx, T_i8(), n.val);
     } else { val = alloca(cx, type_of(cx.fcx.lcx.ccx, cx.sp, t)); }
     // NB: since we've pushed all size calculations in this
@@ -6862,13 +6893,14 @@ fn new_local_ctxt(&@crate_ctxt ccx) -> @local_ctxt {
 }
 
 
-// Creates the standard trio of basic blocks: allocas, copy-args, and derived
-// tydescs.
+// Creates the standard quartet of basic blocks: static allocas, copy args,
+// derived tydescs, and dynamic allocas.
 fn mk_standard_basic_blocks(ValueRef llfn) ->
-   tup(BasicBlockRef, BasicBlockRef, BasicBlockRef) {
-    ret tup(llvm::LLVMAppendBasicBlock(llfn, str::buf("allocas")),
+   tup(BasicBlockRef, BasicBlockRef, BasicBlockRef, BasicBlockRef) {
+    ret tup(llvm::LLVMAppendBasicBlock(llfn, str::buf("static_allocas")),
             llvm::LLVMAppendBasicBlock(llfn, str::buf("copy_args")),
-            llvm::LLVMAppendBasicBlock(llfn, str::buf("derived_tydescs")));
+            llvm::LLVMAppendBasicBlock(llfn, str::buf("derived_tydescs")),
+            llvm::LLVMAppendBasicBlock(llfn, str::buf("dynamic_allocas")));
 }
 
 
@@ -6893,9 +6925,11 @@ fn new_fn_ctxt(@local_ctxt cx, &span sp, ValueRef llfndecl) -> @fn_ctxt {
              lltaskptr=lltaskptr,
              llenv=llenv,
              llretptr=llretptr,
-             mutable llallocas=llbbs._0,
+             mutable llstaticallocas=llbbs._0,
              mutable llcopyargs=llbbs._1,
+             mutable llderivedtydescs_first=llbbs._2,
              mutable llderivedtydescs=llbbs._2,
+             mutable lldynamicallocas=llbbs._3,
              mutable llself=none[val_self_pair],
              mutable lliterbody=none[ValueRef],
              llargs=llargs,
@@ -6973,7 +7007,7 @@ fn create_llargs_for_fn_args(&@fn_ctxt cx, ast::proto proto,
 // allocas immediately upon entry; this permits us to GEP into structures we
 // were passed and whatnot. Apparently mem2reg will mop up.
 fn copy_any_self_to_alloca(@fn_ctxt fcx, option::t[ty_self_pair] ty_self) {
-    auto bcx = llallocas_block_ctxt(fcx);
+    auto bcx = llstaticallocas_block_ctxt(fcx);
     alt ({ fcx.llself }) {
         case (some(?pair)) {
             alt (ty_self) {
@@ -7045,7 +7079,7 @@ fn ret_ty_of_fn(&@crate_ctxt ccx, ast::ann ann) -> ty::t {
 }
 
 fn populate_fn_ctxt_from_llself(@fn_ctxt fcx, val_self_pair llself) {
-    auto bcx = llallocas_block_ctxt(fcx);
+    auto bcx = llstaticallocas_block_ctxt(fcx);
     let vec[ty::t] field_tys = [];
     for (ast::obj_field f in bcx.fcx.lcx.obj_fields) {
         field_tys += [node_ann_type(bcx.fcx.lcx.ccx, f.ann)];
@@ -7088,20 +7122,22 @@ fn populate_fn_ctxt_from_llself(@fn_ctxt fcx, val_self_pair llself) {
     i = 0;
     for (ast::obj_field f in fcx.lcx.obj_fields) {
         auto rslt = GEP_tup_like(bcx, fields_tup_ty, obj_fields, [0, i]);
-        bcx = llallocas_block_ctxt(fcx);
+        bcx = llstaticallocas_block_ctxt(fcx);
         auto llfield = rslt.val;
         fcx.llobjfields.insert(f.id, llfield);
         i += 1;
     }
-    fcx.llallocas = bcx.llbb;
+    fcx.llstaticallocas = bcx.llbb;
 }
 
 
-// Ties up the llallocas -> llcopyargs -> llderivedtydescs -> lltop edges.
+// Ties up the llstaticallocas -> llcopyargs -> llderivedtydescs ->
+// lldynamicallocas -> lltop edges.
 fn finish_fn(&@fn_ctxt fcx, BasicBlockRef lltop) {
-    new_builder(fcx.llallocas).Br(fcx.llcopyargs);
-    new_builder(fcx.llcopyargs).Br(fcx.llderivedtydescs);
-    new_builder(fcx.llderivedtydescs).Br(lltop);
+    new_builder(fcx.llstaticallocas).Br(fcx.llcopyargs);
+    new_builder(fcx.llcopyargs).Br(fcx.llderivedtydescs_first);
+    new_builder(fcx.llderivedtydescs).Br(fcx.lldynamicallocas);
+    new_builder(fcx.lldynamicallocas).Br(lltop);
 }