rustc: Hoist derived type descriptors to the top of the function

This commit is contained in:
Patrick Walton 2011-05-11 11:56:49 -07:00
parent c787d6d4f3
commit 26ab36afb1

View file

@ -52,6 +52,8 @@ state obj namegen(mutable int i) {
} }
} }
type derived_tydesc_info = rec(ValueRef lltydesc, bool escapes);
type glue_fns = rec(ValueRef activate_glue, type glue_fns = rec(ValueRef activate_glue,
ValueRef yield_glue, ValueRef yield_glue,
ValueRef exit_task_glue, ValueRef exit_task_glue,
@ -131,6 +133,8 @@ state type fn_ctxt = rec(ValueRef llfn,
ValueRef llenv, ValueRef llenv,
ValueRef llretptr, ValueRef llretptr,
mutable BasicBlockRef llallocas, mutable BasicBlockRef llallocas,
mutable BasicBlockRef llcopyargs,
mutable BasicBlockRef llderivedtydescs,
mutable Option.t[self_vt] llself, mutable Option.t[self_vt] llself,
mutable Option.t[ValueRef] lliterbody, mutable Option.t[ValueRef] lliterbody,
hashmap[ast.def_id, ValueRef] llargs, hashmap[ast.def_id, ValueRef] llargs,
@ -138,6 +142,7 @@ state type fn_ctxt = rec(ValueRef llfn,
hashmap[ast.def_id, ValueRef] lllocals, hashmap[ast.def_id, ValueRef] lllocals,
hashmap[ast.def_id, ValueRef] llupvars, hashmap[ast.def_id, ValueRef] llupvars,
mutable vec[ValueRef] lltydescs, mutable vec[ValueRef] lltydescs,
hashmap[ty.t, derived_tydesc_info] derived_tydescs,
@local_ctxt lcx); @local_ctxt lcx);
tag cleanup { tag cleanup {
@ -1613,7 +1618,7 @@ fn trans_stack_local_derived_tydesc(&@block_ctxt cx, ValueRef llsz,
ValueRef llalign, ValueRef llalign,
ValueRef llroottydesc, ValueRef llroottydesc,
&Option.t[ValueRef] llparamtydescs) &Option.t[ValueRef] llparamtydescs)
-> result { -> ValueRef {
auto llmyroottydesc = alloca(cx, T_tydesc(cx.fcx.lcx.ccx.tn)); auto llmyroottydesc = alloca(cx, T_tydesc(cx.fcx.lcx.ccx.tn));
// By convention, desc 0 is the root descriptor. // By convention, desc 0 is the root descriptor.
@ -1642,19 +1647,29 @@ fn trans_stack_local_derived_tydesc(&@block_ctxt cx, ValueRef llsz,
cx.build.Store(llalign, cx.build.Store(llalign,
cx.build.GEP(llmyroottydesc, vec(C_int(0), C_int(2)))); cx.build.GEP(llmyroottydesc, vec(C_int(0), C_int(2))));
ret res(cx, llmyroottydesc); ret llmyroottydesc;
} }
fn mk_derived_tydesc(&@block_ctxt cx, &ty.t t, bool escapes) -> result { fn mk_derived_tydesc(&@block_ctxt cx, &ty.t t, bool escapes) -> result {
let uint n_params = ty.count_ty_params(cx.fcx.lcx.ccx.tcx, t); alt (cx.fcx.derived_tydescs.find(t)) {
auto tys = linearize_ty_params(cx, t); case (some[derived_tydesc_info](?info)) {
// If the tydesc escapes in this context, the cached derived
// tydesc also has to be one that was marked as escaping.
if (!(escapes && !info.escapes)) { ret res(cx, info.lltydesc); }
}
case (none[derived_tydesc_info]) { /* fall through */ }
}
auto bcx = new_raw_block_ctxt(cx.fcx, cx.fcx.llderivedtydescs);
let uint n_params = ty.count_ty_params(bcx.fcx.lcx.ccx.tcx, t);
auto tys = linearize_ty_params(bcx, t);
assert (n_params == Vec.len[uint](tys._0)); assert (n_params == Vec.len[uint](tys._0));
assert (n_params == Vec.len[ValueRef](tys._1)); assert (n_params == Vec.len[ValueRef](tys._1));
auto root = get_static_tydesc(cx, t, tys._0).tydesc; auto root = get_static_tydesc(bcx, t, tys._0).tydesc;
auto bcx = cx;
auto sz = size_of(bcx, t); auto sz = size_of(bcx, t);
bcx = sz.bcx; bcx = sz.bcx;
auto align = align_of(bcx, t); auto align = align_of(bcx, t);
@ -1662,16 +1677,17 @@ fn mk_derived_tydesc(&@block_ctxt cx, &ty.t t, bool escapes) -> result {
auto v; auto v;
if (escapes) { if (escapes) {
auto tydescs = alloca(cx, T_array(T_ptr(T_tydesc(cx.fcx.lcx.ccx.tn)), auto tydescs = alloca(bcx,
1u /* for root*/ + n_params)); T_array(T_ptr(T_tydesc(bcx.fcx.lcx.ccx.tn)),
1u /* for root*/ + n_params));
auto i = 0; auto i = 0;
auto tdp = cx.build.GEP(tydescs, vec(C_int(0), C_int(i))); auto tdp = bcx.build.GEP(tydescs, vec(C_int(0), C_int(i)));
cx.build.Store(root, tdp); bcx.build.Store(root, tdp);
i += 1; i += 1;
for (ValueRef td in tys._1) { for (ValueRef td in tys._1) {
auto tdp = cx.build.GEP(tydescs, vec(C_int(0), C_int(i))); auto tdp = bcx.build.GEP(tydescs, vec(C_int(0), C_int(i)));
cx.build.Store(td, tdp); bcx.build.Store(td, tdp);
i += 1; i += 1;
} }
@ -1684,20 +1700,20 @@ fn mk_derived_tydesc(&@block_ctxt cx, &ty.t t, bool escapes) -> result {
align.val, align.val,
C_int((1u + n_params) as int), C_int((1u + n_params) as int),
lltydescsptr)); lltydescsptr));
v = res(bcx, td_val); v = td_val;
} else { } else {
auto llparamtydescs_opt; auto llparamtydescs_opt;
if (n_params == 0u) { if (n_params == 0u) {
llparamtydescs_opt = none[ValueRef]; llparamtydescs_opt = none[ValueRef];
} else { } else {
auto llparamtydescs = alloca(cx, auto llparamtydescs = alloca(bcx,
T_array(T_ptr(T_tydesc(cx.fcx.lcx.ccx.tn)), n_params)); T_array(T_ptr(T_tydesc(bcx.fcx.lcx.ccx.tn)), n_params));
auto i = 0; auto i = 0;
for (ValueRef td in tys._1) { for (ValueRef td in tys._1) {
auto tdp = cx.build.GEP(llparamtydescs, auto tdp = bcx.build.GEP(llparamtydescs,
vec(C_int(0), C_int(i))); vec(C_int(0), C_int(i)));
cx.build.Store(td, tdp); bcx.build.Store(td, tdp);
i += 1; i += 1;
} }
@ -1708,7 +1724,9 @@ fn mk_derived_tydesc(&@block_ctxt cx, &ty.t t, bool escapes) -> result {
llparamtydescs_opt); llparamtydescs_opt);
} }
ret v; bcx.fcx.derived_tydescs.insert(t, rec(lltydesc=v, escapes=escapes));
ret res(cx, v);
} }
fn get_tydesc(&@block_ctxt cx, &ty.t t, bool escapes) -> result { fn get_tydesc(&@block_ctxt cx, &ty.t t, bool escapes) -> result {
@ -1863,8 +1881,6 @@ fn make_generic_glue(&@local_ctxt cx,
&make_generic_glue_helper_fn helper, &make_generic_glue_helper_fn helper,
&vec[uint] ty_params) -> ValueRef { &vec[uint] ty_params) -> ValueRef {
auto fcx = new_fn_ctxt(cx, llfn); auto fcx = new_fn_ctxt(cx, llfn);
auto bcx = new_top_block_ctxt(fcx);
auto lltop = bcx.llbb;
// Any nontrivial glue is with values passed *by alias*; this is a // Any nontrivial glue is with values passed *by alias*; this is a
// requirement since in many contexts glue is invoked indirectly and // requirement since in many contexts glue is invoked indirectly and
@ -1882,16 +1898,22 @@ fn make_generic_glue(&@local_ctxt cx,
auto lltyparams = llvm.LLVMGetParam(llfn, 3u); auto lltyparams = llvm.LLVMGetParam(llfn, 3u);
auto copy_args_bcx = new_raw_block_ctxt(fcx, fcx.llcopyargs);
auto lltydescs = Vec.empty_mut[ValueRef](); auto lltydescs = Vec.empty_mut[ValueRef]();
auto p = 0u; auto p = 0u;
while (p < ty_param_count) { while (p < ty_param_count) {
auto llparam = bcx.build.GEP(lltyparams, vec(C_int(p as int))); auto llparam = copy_args_bcx.build.GEP(lltyparams,
llparam = bcx.build.Load(llparam); vec(C_int(p as int)));
llparam = copy_args_bcx.build.Load(llparam);
Vec.grow_set[ValueRef](lltydescs, ty_params.(p), 0 as ValueRef, Vec.grow_set[ValueRef](lltydescs, ty_params.(p), 0 as ValueRef,
llparam); llparam);
p += 1u; p += 1u;
} }
bcx.fcx.lltydescs = Vec.freeze[ValueRef](lltydescs); fcx.lltydescs = Vec.freeze[ValueRef](lltydescs);
auto bcx = new_top_block_ctxt(fcx);
auto lltop = bcx.llbb;
auto llrawptr0 = llvm.LLVMGetParam(llfn, 4u); auto llrawptr0 = llvm.LLVMGetParam(llfn, 4u);
auto llval0 = bcx.build.BitCast(llrawptr0, llty); auto llval0 = bcx.build.BitCast(llrawptr0, llty);
@ -1910,8 +1932,7 @@ fn make_generic_glue(&@local_ctxt cx,
} }
} }
// Tie up the llallocas -> lltop edge. finish_fn(fcx, lltop);
new_builder(fcx.llallocas).Br(lltop);
ret llfn; ret llfn;
} }
@ -3779,23 +3800,27 @@ fn trans_for_each(&@block_ctxt cx,
s, iter_body_llty); s, iter_body_llty);
auto fcx = new_fn_ctxt(lcx, lliterbody); auto fcx = new_fn_ctxt(lcx, lliterbody);
auto bcx = new_top_block_ctxt(fcx);
auto lltop = bcx.llbb; auto copy_args_bcx = new_raw_block_ctxt(fcx, fcx.llcopyargs);
// Populate the upvars from the environment. // Populate the upvars from the environment.
auto llremoteenvptr = bcx.build.PointerCast(fcx.llenv, llenvptrty); auto llremoteenvptr = copy_args_bcx.build.PointerCast(fcx.llenv,
llenvptrty);
auto llremotebindingsptrptr = auto llremotebindingsptrptr =
bcx.build.GEP(llremoteenvptr, vec(C_int(0), copy_args_bcx.build.GEP(llremoteenvptr,
C_int(abi.box_rc_field_body), vec(C_int(0),
C_int(abi.closure_elt_bindings))); C_int(abi.box_rc_field_body),
auto llremotebindingsptr = bcx.build.Load(llremotebindingsptrptr); C_int(abi.closure_elt_bindings)));
auto llremotebindingsptr =
copy_args_bcx.build.Load(llremotebindingsptrptr);
i = 0u; i = 0u;
while (i < upvar_count) { while (i < upvar_count) {
auto upvar_id = upvars.(i); auto upvar_id = upvars.(i);
auto llupvarptrptr = bcx.build.GEP(llremotebindingsptr, auto llupvarptrptr =
vec(C_int(0), C_int(i as int))); copy_args_bcx.build.GEP(llremotebindingsptr,
auto llupvarptr = bcx.build.Load(llupvarptrptr); vec(C_int(0), C_int(i as int)));
auto llupvarptr = copy_args_bcx.build.Load(llupvarptrptr);
fcx.llupvars.insert(upvar_id, llupvarptr); fcx.llupvars.insert(upvar_id, llupvarptr);
i += 1u; i += 1u;
@ -3803,17 +3828,17 @@ fn trans_for_each(&@block_ctxt cx,
// Populate the type parameters from the environment. // Populate the type parameters from the environment.
auto llremotetydescsptr = auto llremotetydescsptr =
bcx.build.GEP(llremoteenvptr, copy_args_bcx.build.GEP(llremoteenvptr,
vec(C_int(0), vec(C_int(0),
C_int(abi.box_rc_field_body), C_int(abi.box_rc_field_body),
C_int(abi.closure_elt_ty_params))); C_int(abi.closure_elt_ty_params)));
i = 0u; i = 0u;
while (i < tydesc_count) { while (i < tydesc_count) {
auto llremotetydescptr = bcx.build.GEP(llremotetydescsptr, auto llremotetydescptr =
vec(C_int(0), copy_args_bcx.build.GEP(llremotetydescsptr, vec(C_int(0),
C_int(i as int))); C_int(i as int)));
auto llremotetydesc = bcx.build.Load(llremotetydescptr); auto llremotetydesc = copy_args_bcx.build.Load(llremotetydescptr);
fcx.lltydescs += vec(llremotetydesc); fcx.lltydescs += vec(llremotetydesc);
i += 1u; i += 1u;
} }
@ -3821,10 +3846,11 @@ fn trans_for_each(&@block_ctxt cx,
// Add an upvar for the loop variable alias. // Add an upvar for the loop variable alias.
fcx.llupvars.insert(decl_id, llvm.LLVMGetParam(fcx.llfn, 3u)); fcx.llupvars.insert(decl_id, llvm.LLVMGetParam(fcx.llfn, 3u));
auto bcx = new_top_block_ctxt(fcx);
auto lltop = bcx.llbb;
auto r = trans_block(bcx, body); auto r = trans_block(bcx, body);
// Tie up the llallocas -> lltop edge. finish_fn(fcx, lltop);
new_builder(fcx.llallocas).Br(lltop);
r.bcx.build.RetVoid(); r.bcx.build.RetVoid();
@ -4599,8 +4625,7 @@ fn trans_bind_thunk(&@local_ctxt cx,
auto r = bcx.build.FastCall(lltargetfn, llargs); auto r = bcx.build.FastCall(lltargetfn, llargs);
bcx.build.RetVoid(); bcx.build.RetVoid();
// Tie up the llallocas -> lltop edge. finish_fn(fcx, lltop);
new_builder(fcx.llallocas).Br(lltop);
ret llthunk; ret llthunk;
} }
@ -5890,6 +5915,12 @@ fn new_sub_block_ctxt(&@block_ctxt bcx, &str n) -> @block_ctxt {
ret new_block_ctxt(bcx.fcx, parent_some(bcx), NON_SCOPE_BLOCK, n); ret new_block_ctxt(bcx.fcx, parent_some(bcx), NON_SCOPE_BLOCK, n);
} }
fn new_raw_block_ctxt(&@fn_ctxt fcx, BasicBlockRef llbb) -> @block_ctxt {
let vec[cleanup] cleanups = vec();
ret @rec(llbb=llbb, build=new_builder(llbb), parent=parent_none,
kind=NON_SCOPE_BLOCK, mutable cleanups=cleanups, fcx=fcx);
}
fn trans_block_cleanups(&@block_ctxt cx, fn trans_block_cleanups(&@block_ctxt cx,
&@block_ctxt cleanup_cx) -> @block_ctxt { &@block_ctxt cleanup_cx) -> @block_ctxt {
@ -6056,6 +6087,15 @@ fn new_local_ctxt(&@crate_ctxt ccx) -> @local_ctxt {
ccx = ccx); ccx = ccx);
} }
// Creates the standard trio of basic blocks: allocas, copy-args, and derived
// tydescs.
fn mk_standard_basic_blocks(ValueRef llfn) ->
tup(BasicBlockRef, BasicBlockRef, BasicBlockRef) {
ret tup(llvm.LLVMAppendBasicBlock(llfn, Str.buf("allocas")),
llvm.LLVMAppendBasicBlock(llfn, Str.buf("copy_args")),
llvm.LLVMAppendBasicBlock(llfn, Str.buf("derived_tydescs")));
}
// NB: must keep 4 fns in sync: // NB: must keep 4 fns in sync:
// //
// - type_of_fn_full // - type_of_fn_full
@ -6075,14 +6115,18 @@ fn new_fn_ctxt(@local_ctxt cx,
let hashmap[ast.def_id, ValueRef] lllocals = new_def_hash[ValueRef](); let hashmap[ast.def_id, ValueRef] lllocals = new_def_hash[ValueRef]();
let hashmap[ast.def_id, ValueRef] llupvars = new_def_hash[ValueRef](); let hashmap[ast.def_id, ValueRef] llupvars = new_def_hash[ValueRef]();
let BasicBlockRef llallocas = auto derived_tydescs =
llvm.LLVMAppendBasicBlock(llfndecl, Str.buf("allocas")); Map.mk_hashmap[ty.t, derived_tydesc_info](ty.hash_ty, ty.eq_ty);
auto llbbs = mk_standard_basic_blocks(llfndecl);
ret @rec(llfn=llfndecl, ret @rec(llfn=llfndecl,
lltaskptr=lltaskptr, lltaskptr=lltaskptr,
llenv=llenv, llenv=llenv,
llretptr=llretptr, llretptr=llretptr,
mutable llallocas = llallocas, mutable llallocas=llbbs._0,
mutable llcopyargs=llbbs._1,
mutable llderivedtydescs=llbbs._2,
mutable llself=none[self_vt], mutable llself=none[self_vt],
mutable lliterbody=none[ValueRef], mutable lliterbody=none[ValueRef],
llargs=llargs, llargs=llargs,
@ -6090,6 +6134,7 @@ fn new_fn_ctxt(@local_ctxt cx,
lllocals=lllocals, lllocals=lllocals,
llupvars=llupvars, llupvars=llupvars,
mutable lltydescs=Vec.empty[ValueRef](), mutable lltydescs=Vec.empty[ValueRef](),
derived_tydescs=derived_tydescs,
lcx=cx); lcx=cx);
} }
@ -6165,12 +6210,13 @@ fn copy_any_self_to_alloca(@fn_ctxt fcx,
} }
fn copy_args_to_allocas(@block_ctxt bcx, fn copy_args_to_allocas(@fn_ctxt fcx,
vec[ast.arg] args, vec[ast.arg] args,
vec[ty.arg] arg_tys) { vec[ty.arg] arg_tys) {
let uint arg_n = 0u; auto bcx = new_raw_block_ctxt(fcx, fcx.llcopyargs);
let uint arg_n = 0u;
for (ast.arg aarg in args) { for (ast.arg aarg in args) {
if (aarg.mode != ast.alias) { if (aarg.mode != ast.alias) {
auto arg_t = type_of_arg(bcx.fcx.lcx, arg_tys.(arg_n)); auto arg_t = type_of_arg(bcx.fcx.lcx, arg_tys.(arg_n));
@ -6297,6 +6343,13 @@ fn populate_fn_ctxt_from_llself(@fn_ctxt fcx, self_vt llself) {
fcx.llallocas = bcx.llbb; fcx.llallocas = bcx.llbb;
} }
// Ties up the llallocas -> llcopyargs -> llderivedtydescs -> 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);
}
fn trans_fn(@local_ctxt cx, &ast._fn f, ast.def_id fid, fn trans_fn(@local_ctxt cx, &ast._fn f, ast.def_id fid,
Option.t[tup(TypeRef, ty.t)] ty_self, Option.t[tup(TypeRef, ty.t)] ty_self,
&vec[ast.ty_param] ty_params, &ast.ann ann) { &vec[ast.ty_param] ty_params, &ast.ann ann) {
@ -6318,10 +6371,9 @@ fn trans_fn(@local_ctxt cx, &ast._fn f, ast.def_id fid,
} }
auto arg_tys = arg_tys_of_fn(fcx.lcx.ccx, ann); auto arg_tys = arg_tys_of_fn(fcx.lcx.ccx, ann);
copy_args_to_allocas(fcx, f.decl.inputs, arg_tys);
auto bcx = new_top_block_ctxt(fcx); auto bcx = new_top_block_ctxt(fcx);
copy_args_to_allocas(bcx, f.decl.inputs, arg_tys);
add_cleanups_for_args(bcx, f.decl.inputs, arg_tys); add_cleanups_for_args(bcx, f.decl.inputs, arg_tys);
auto lltop = bcx.llbb; auto lltop = bcx.llbb;
@ -6333,8 +6385,7 @@ fn trans_fn(@local_ctxt cx, &ast._fn f, ast.def_id fid,
res.bcx.build.RetVoid(); res.bcx.build.RetVoid();
} }
// Tie up the llallocas -> lltop edge. finish_fn(fcx, lltop);
new_builder(fcx.llallocas).Br(lltop);
} }
fn trans_vtbl(@local_ctxt cx, fn trans_vtbl(@local_ctxt cx,
@ -6432,9 +6483,9 @@ fn trans_obj(@local_ctxt cx, &ast._obj ob, ast.def_id oid,
fn_args, ty_params); fn_args, ty_params);
let vec[ty.arg] arg_tys = arg_tys_of_fn(ccx, ann); let vec[ty.arg] arg_tys = arg_tys_of_fn(ccx, ann);
copy_args_to_allocas(fcx, fn_args, arg_tys);
auto bcx = new_top_block_ctxt(fcx); auto bcx = new_top_block_ctxt(fcx);
copy_args_to_allocas(bcx, fn_args, arg_tys);
auto lltop = bcx.llbb; auto lltop = bcx.llbb;
auto self_ty = ret_ty_of_fn(ccx, ann); auto self_ty = ret_ty_of_fn(ccx, ann);
@ -6546,8 +6597,7 @@ fn trans_obj(@local_ctxt cx, &ast._obj ob, ast.def_id oid,
} }
bcx.build.RetVoid(); bcx.build.RetVoid();
// Tie up the llallocas -> lltop edge. finish_fn(fcx, lltop);
new_builder(fcx.llallocas).Br(lltop);
} }
fn trans_tag_variant(@local_ctxt cx, ast.def_id tag_id, fn trans_tag_variant(@local_ctxt cx, ast.def_id tag_id,
@ -6585,9 +6635,9 @@ fn trans_tag_variant(@local_ctxt cx, ast.def_id tag_id,
} }
auto arg_tys = arg_tys_of_fn(cx.ccx, variant.node.ann); auto arg_tys = arg_tys_of_fn(cx.ccx, variant.node.ann);
copy_args_to_allocas(fcx, fn_args, arg_tys);
auto bcx = new_top_block_ctxt(fcx); auto bcx = new_top_block_ctxt(fcx);
copy_args_to_allocas(bcx, fn_args, arg_tys);
auto lltop = bcx.llbb; auto lltop = bcx.llbb;
// Cast the tag to a type we can GEP into. // Cast the tag to a type we can GEP into.
@ -6632,8 +6682,7 @@ fn trans_tag_variant(@local_ctxt cx, ast.def_id tag_id,
bcx = trans_block_cleanups(bcx, find_scope_cx(bcx)); bcx = trans_block_cleanups(bcx, find_scope_cx(bcx));
bcx.build.RetVoid(); bcx.build.RetVoid();
// Tie up the llallocas -> lltop edge. finish_fn(fcx, lltop);
new_builder(fcx.llallocas).Br(lltop);
} }
// FIXME: this should do some structural hash-consing to avoid // FIXME: this should do some structural hash-consing to avoid
@ -6973,8 +7022,7 @@ fn decl_native_fn_and_pair(&@crate_ctxt ccx,
bcx.build.RetVoid(); bcx.build.RetVoid();
// Tie up the llallocas -> lltop edge. finish_fn(fcx, lltop);
new_builder(fcx.llallocas).Br(lltop);
} }
type walk_ctxt = rec(mutable vec[str] path); type walk_ctxt = rec(mutable vec[str] path);
@ -7469,15 +7517,18 @@ fn trans_vec_append_glue(@local_ctxt cx) {
let ValueRef lldst_vec_ptr = llvm.LLVMGetParam(llfn, 3u); let ValueRef lldst_vec_ptr = llvm.LLVMGetParam(llfn, 3u);
let ValueRef llsrc_vec = llvm.LLVMGetParam(llfn, 4u); let ValueRef llsrc_vec = llvm.LLVMGetParam(llfn, 4u);
let ValueRef llskipnull = llvm.LLVMGetParam(llfn, 5u); let ValueRef llskipnull = llvm.LLVMGetParam(llfn, 5u);
auto derived_tydescs =
Map.mk_hashmap[ty.t, derived_tydesc_info](ty.hash_ty, ty.eq_ty);
let BasicBlockRef llallocas = auto llbbs = mk_standard_basic_blocks(llfn);
llvm.LLVMAppendBasicBlock(llfn, Str.buf("allocas"));
auto fcx = @rec(llfn=llfn, auto fcx = @rec(llfn=llfn,
lltaskptr=lltaskptr, lltaskptr=lltaskptr,
llenv=C_null(T_ptr(T_nil())), llenv=C_null(T_ptr(T_nil())),
llretptr=C_null(T_ptr(T_nil())), llretptr=C_null(T_ptr(T_nil())),
mutable llallocas = llallocas, mutable llallocas = llbbs._0,
mutable llcopyargs = llbbs._1,
mutable llderivedtydescs = llbbs._2,
mutable llself=none[self_vt], mutable llself=none[self_vt],
mutable lliterbody=none[ValueRef], mutable lliterbody=none[ValueRef],
llargs=new_def_hash[ValueRef](), llargs=new_def_hash[ValueRef](),
@ -7485,6 +7536,7 @@ fn trans_vec_append_glue(@local_ctxt cx) {
lllocals=new_def_hash[ValueRef](), lllocals=new_def_hash[ValueRef](),
llupvars=new_def_hash[ValueRef](), llupvars=new_def_hash[ValueRef](),
mutable lltydescs=Vec.empty[ValueRef](), mutable lltydescs=Vec.empty[ValueRef](),
derived_tydescs=derived_tydescs,
lcx=cx); lcx=cx);
auto bcx = new_top_block_ctxt(fcx); auto bcx = new_top_block_ctxt(fcx);
@ -7590,8 +7642,7 @@ fn trans_vec_append_glue(@local_ctxt cx) {
copy_src_cx.build.Store(llnew_vec, lldst_vec_ptr); copy_src_cx.build.Store(llnew_vec, lldst_vec_ptr);
copy_src_cx.build.RetVoid(); copy_src_cx.build.RetVoid();
// Tie up the llallocas -> lltop edge. finish_fn(fcx, lltop);
new_builder(fcx.llallocas).Br(lltop);
} }