diff --git a/src/comp/driver/rustc.rs b/src/comp/driver/rustc.rs index 6c125f0e176da..14f4a045b945e 100644 --- a/src/comp/driver/rustc.rs +++ b/src/comp/driver/rustc.rs @@ -150,26 +150,25 @@ fn compile_input(sess: session::session, cfg: ast::crate_cfg, input: str, time(time_passes, "freevar finding", bind freevars::annotate_freevars(sess, def_map, crate)); let ty_cx = ty::mk_ctxt(sess, def_map, ext_map, ast_map, freevars); - time::<()>(time_passes, "typechecking", - bind typeck::check_crate(ty_cx, crate)); - time::<()>(time_passes, "alt checking", - bind middle::check_alt::check_crate(ty_cx, crate)); + time(time_passes, "typechecking", + bind typeck::check_crate(ty_cx, crate)); + time(time_passes, "alt checking", + bind middle::check_alt::check_crate(ty_cx, crate)); if sess.get_opts().run_typestate { time(time_passes, "typestate checking", bind middle::tstate::ck::check_crate(ty_cx, crate)); } - time(time_passes, "alias checking", - bind middle::alias::check_crate(ty_cx, crate)); - time::<()>(time_passes, "kind checking", - bind kind::check_crate(ty_cx, crate)); + let mut_map = time(time_passes, "alias checking", + bind middle::alias::check_crate(ty_cx, crate)); + time(time_passes, "kind checking", + bind kind::check_crate(ty_cx, crate)); if sess.get_opts().no_trans { ret; } let llmod = - time::(time_passes, "translation", - bind trans::trans_crate(sess, crate, - ty_cx, output, - ast_map)); - time::<()>(time_passes, "LLVM passes", - bind link::write::run_passes(sess, llmod, output)); + time(time_passes, "translation", + bind trans::trans_crate(sess, crate, ty_cx, output, + ast_map, mut_map)); + time(time_passes, "LLVM passes", + bind link::write::run_passes(sess, llmod, output)); } fn pretty_print_input(sess: session::session, cfg: ast::crate_cfg, input: str, diff --git a/src/comp/middle/alias.rs b/src/comp/middle/alias.rs index 5d0afd7154da4..45688bc831ffe 100644 --- a/src/comp/middle/alias.rs +++ b/src/comp/middle/alias.rs @@ -36,12 +36,17 @@ type scope = @[restrict]; tag local_info { arg(ast::mode); objfield(ast::mutability); } -type ctx = {tcx: ty::ctxt, local_map: std::map::hashmap}; +type mut_map = std::map::hashmap; +type ctx = {tcx: ty::ctxt, + local_map: std::map::hashmap, + mut_map: mut_map}; -fn check_crate(tcx: ty::ctxt, crate: &@ast::crate) { +fn check_crate(tcx: ty::ctxt, crate: &@ast::crate) -> mut_map { // Stores information about object fields and function // arguments that's otherwise not easily available. - let cx = @{tcx: tcx, local_map: std::map::new_int_hash()}; + let cx = @{tcx: tcx, + local_map: std::map::new_int_hash(), + mut_map: std::map::new_int_hash()}; let v = @{visit_fn: bind visit_fn(cx, _, _, _, _, _, _, _), visit_item: bind visit_item(cx, _, _, _), visit_expr: bind visit_expr(cx, _, _, _), @@ -49,6 +54,7 @@ fn check_crate(tcx: ty::ctxt, crate: &@ast::crate) { with *visit::default_visitor::()}; visit::visit_crate(*crate, @~[], visit::mk_vt(v)); tcx.sess.abort_if_errors(); + ret cx.mut_map; } fn visit_fn(cx: &@ctx, f: &ast::_fn, _tp: &[ast::ty_param], _sp: &span, @@ -409,6 +415,7 @@ fn check_lval(cx: &@ctx, dest: &@ast::expr, sc: &scope, v: &vt) { alt dest.node { ast::expr_path(p) { let dnum = ast::def_id_of_def(cx.tcx.def_map.get(dest.id)).node; + cx.mut_map.insert(dnum, ()); if is_immutable_alias(*cx, sc, dnum) { cx.tcx.sess.span_err(dest.span, "assigning to immutable alias"); } else if (is_immutable_objfield(*cx, dnum)) { diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index f587b84298660..6f41e74da69d6 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -95,7 +95,10 @@ fn type_of_explicit_args(cx: &@crate_ctxt, sp: &span, inputs: &[ty::arg]) -> t = alt arg.mode { ty::mo_alias(_) { T_ptr(t) } ty::mo_move. { T_ptr(t) } - _ { t } + _ { + if ty::type_is_structural(cx.tcx, arg.ty) { T_ptr(t) } + else { t } + } }; atys += ~[t]; } @@ -4358,14 +4361,8 @@ fn trans_bind_thunk(cx: &@local_ctxt, sp: &span, incoming_fty: &ty::t, { T_ptr(llout_arg_ty) } else { llout_arg_ty }; val = bcx.build.PointerCast(val, ty); } - if is_val { - if type_is_immediate(cx.ccx, e_ty) { - val = bcx.build.Load(val); - bcx = copy_ty(bcx, val, e_ty).bcx; - } else { - bcx = copy_ty(bcx, val, e_ty).bcx; - val = bcx.build.Load(val); - } + if is_val && type_is_immediate(cx.ccx, e_ty) { + val = bcx.build.Load(val); } llargs += ~[val]; b += 1; @@ -4375,16 +4372,7 @@ fn trans_bind_thunk(cx: &@local_ctxt, sp: &span, incoming_fty: &ty::t, none. { let arg: ValueRef = llvm::LLVMGetParam(llthunk, a); if ty::type_contains_params(cx.ccx.tcx, out_arg.ty) { - // If the argument was passed by value and isn't a - // pointer type, we need to spill it to an alloca in - // order to do a pointer cast. Argh. - if is_val && !ty::type_is_boxed(cx.ccx.tcx, out_arg.ty) { - let argp = do_spill(bcx, arg); - argp = bcx.build.PointerCast(argp, T_ptr(llout_arg_ty)); - arg = bcx.build.Load(argp); - } else { - arg = bcx.build.PointerCast(arg, llout_arg_ty); - } + arg = bcx.build.PointerCast(arg, llout_arg_ty); } llargs += ~[arg]; a += 1u; @@ -4404,7 +4392,7 @@ fn trans_bind_thunk(cx: &@local_ctxt, sp: &span, incoming_fty: &ty::t, type_of_fn_from_ty(bcx_ccx(bcx), sp, outgoing_fty, ty_param_count); lltargetfn = bcx.build.PointerCast(lltargetfn, T_ptr(T_ptr(lltargetty))); lltargetfn = bcx.build.Load(lltargetfn); - llvm::LLVMSetTailCall(bcx.build.FastCall(lltargetfn, llargs), 1); + bcx.build.FastCall(lltargetfn, llargs); build_return(bcx); finish_fn(fcx, lltop); ret {val: llthunk, ty: llthunk_ty}; @@ -4504,47 +4492,40 @@ fn trans_arg_expr(cx: &@block_ctxt, arg: &ty::arg, // be inspected. It's important for the value // to have type lldestty0 (the callee's expected type). val = llvm::LLVMGetUndef(lldestty0); - } else if (arg.mode == ty::mo_val) { - if ty::type_owns_heap_mem(ccx.tcx, e_ty) { + } else if arg.mode == ty::mo_val { + // Eliding take/drop for appending of external vectors currently + // corrupts memory. I can't figure out why, and external vectors + // are on the way out anyway, so this simply turns off the + // optimization for that case. + let is_ext_vec_plus = alt e.node { + ast::expr_binary(_, _, _) { + ty::type_is_sequence(ccx.tcx, e_ty) && + !ty::sequence_is_interior(ccx.tcx, e_ty) + } + _ { false } + }; + if !lv.is_mem && !is_ext_vec_plus { + // Do nothing for temporaries, just give them to callee + } else if ty::type_is_structural(ccx.tcx, e_ty) { let dst = alloc_ty(bcx, e_ty); + bcx = copy_val(dst.bcx, INIT, dst.val, val, e_ty).bcx; val = dst.val; - bcx = move_val_if_temp(dst.bcx, INIT, val, lv, e_ty).bcx; - } else if (lv.is_mem) { - val = load_if_immediate(bcx, val, e_ty); - bcx = copy_ty(bcx, val, e_ty).bcx; + add_clean_temp(bcx, val, e_ty); } else { - // Eliding take/drop for appending of external vectors currently - // corrupts memory. I can't figure out why, and external vectors - // are on the way out anyway, so this simply turns off the - // optimization for that case. - let is_ext_vec_plus = - alt e.node { - ast::expr_binary(_, _, _) { - ty::type_is_sequence(ccx.tcx, e_ty) && - !ty::sequence_is_interior(ccx.tcx, e_ty) - } - _ { false } - }; - if is_ext_vec_plus { - bcx = copy_ty(bcx, val, e_ty).bcx; - } else { revoke_clean(bcx, val); } + if lv.is_mem { + val = load_if_immediate(bcx, val, e_ty); + } + bcx = copy_ty(bcx, val, e_ty).bcx; + add_clean_temp(bcx, val, e_ty); } - } else if (type_is_immediate(ccx, e_ty) && !lv.is_mem) { + } else if type_is_immediate(ccx, e_ty) && !lv.is_mem { val = do_spill(bcx, val); } if !is_bot && ty::type_contains_params(ccx.tcx, arg.ty) { let lldestty = lldestty0; - if arg.mode == ty::mo_val && ty::type_is_structural(ccx.tcx, e_ty) { - lldestty = T_ptr(lldestty); - } val = bcx.build.PointerCast(val, lldestty); } - if arg.mode == ty::mo_val && ty::type_is_structural(ccx.tcx, e_ty) { - // Until here we've been treating structures by pointer; - // we are now passing it as an arg, so need to load it. - val = bcx.build.Load(val); - } // Collect arg for later if it happens to be one we've moving out. if arg.mode == ty::mo_move { @@ -4660,13 +4641,14 @@ fn trans_args(cx: &@block_ctxt, llenv: ValueRef, to_zero: to_zero, to_revoke: to_revoke}; } -fn trans_call(cx: &@block_ctxt, f: &@ast::expr, +fn trans_call(in_cx: &@block_ctxt, f: &@ast::expr, lliterbody: &option::t, args: &[@ast::expr], id: ast::node_id) -> result { // NB: 'f' isn't necessarily a function; it might be an entire self-call // expression because of the hack that allows us to process self-calls // with trans_call. - + let cx = new_scope_block_ctxt(in_cx, "call"); + in_cx.build.Br(cx.llbb); let f_res = trans_lval_gen(cx, f); let fn_ty: ty::t; alt f_res.method_ty { @@ -4731,7 +4713,7 @@ fn trans_call(cx: &@block_ctxt, f: &@ast::expr, // Retval doesn't correspond to anything really tangible // in the frame, but it's a ref all the same, so we put a // note here to drop it when we're done in this scope. - add_clean_temp(cx, retval, ret_ty); + add_clean_temp(in_cx, retval, ret_ty); } } some(_) { @@ -4748,6 +4730,10 @@ fn trans_call(cx: &@block_ctxt, f: &@ast::expr, for v: ValueRef in args_res.to_revoke { revoke_clean(bcx, v) } + bcx = trans_block_cleanups(bcx, cx); + let next_cx = new_sub_block_ctxt(in_cx, "next"); + bcx.build.Br(next_cx.llbb); + bcx = next_cx; } ret rslt(bcx, retval); } @@ -5272,7 +5258,9 @@ fn trans_fail_value(cx: &@block_ctxt, sp_opt: &option::t, ret rslt(cx, C_nil()); } -fn trans_put(cx: &@block_ctxt, e: &option::t<@ast::expr>) -> result { +fn trans_put(in_cx: &@block_ctxt, e: &option::t<@ast::expr>) -> result { + let cx = new_scope_block_ctxt(in_cx, "put"); + in_cx.build.Br(cx.llbb); let llcallee = C_nil(); let llenv = C_nil(); alt { cx.fcx.lliterbody } { @@ -5302,7 +5290,10 @@ fn trans_put(cx: &@block_ctxt, e: &option::t<@ast::expr>) -> result { } } bcx.build.FastCall(llcallee, llargs); - ret rslt(bcx, C_nil()); + bcx = trans_block_cleanups(bcx, cx); + let next_cx = new_sub_block_ctxt(in_cx, "next"); + bcx.build.Br(next_cx.llbb); + ret rslt(next_cx, C_nil()); } fn trans_uniq(cx: &@block_ctxt, contents: &@ast::expr) -> lval_result { @@ -5859,45 +5850,38 @@ fn create_llargs_for_fn_args(cx: &@fn_ctxt, proto: ast::proto, } } -fn copy_args_to_allocas(fcx: @fn_ctxt, args: &[ast::arg]) { +fn copy_args_to_allocas(fcx: @fn_ctxt, scope: @block_ctxt, + args: &[ast::arg], arg_tys: &[ty::arg]) { let bcx = new_raw_block_ctxt(fcx, fcx.llcopyargs); let arg_n: uint = 0u; for aarg: ast::arg in args { - if aarg.mode == ast::val { - let argval; - alt bcx.fcx.llargs.find(aarg.id) { - some(x) { argval = x; } - _ { - bcx_ccx(bcx).sess.span_fatal - (aarg.ty.span, "unbound arg ID in copy_args_to_allocas"); - } - } - let a = do_spill(bcx, argval); - - // Overwrite the llargs entry for this arg with its alloca. - bcx.fcx.llargs.insert(aarg.id, a); - } - arg_n += 1u; - } -} - -fn add_cleanups_for_args(bcx: &@block_ctxt, args: &[ast::arg], - arg_tys: &[ty::arg]) { - let arg_n: uint = 0u; - for aarg: ast::arg in args { - if aarg.mode == ast::val || aarg.mode == ast::move { - let argval; - alt bcx.fcx.llargs.find(aarg.id) { - some(x) { argval = x; } - _ { - bcx_ccx(bcx).sess.span_fatal - (aarg.ty.span, "unbound arg ID in add_cleanups_for_args"); - } + let arg_ty = arg_tys.(arg_n).ty; + alt aarg.mode { + ast::val. { + // Structural types are passed by pointer, and we use the + // pointed-to memory for the local. + if !ty::type_is_structural(fcx_tcx(fcx), arg_ty) { + // Overwrite the llargs entry for this arg with its alloca. + let aval = bcx.fcx.llargs.get(aarg.id); + let addr = do_spill(bcx, aval); + bcx.fcx.llargs.insert(aarg.id, addr); + + // Args that are locally assigned to need to do a local + // take/drop + if fcx.lcx.ccx.mut_map.contains_key(aarg.id) { + bcx = copy_ty(bcx, aval, arg_ty).bcx; + add_clean(scope, addr, arg_ty); + } } - add_clean(bcx, argval, arg_tys.(arg_n).ty); + } + ast::move. { + add_clean(scope, bcx.fcx.llargs.get(aarg.id), arg_ty); + } + _ {} } arg_n += 1u; } + fcx.llcopyargs = bcx.llbb; } fn is_terminated(cx: &@block_ctxt) -> bool { @@ -5996,8 +5980,15 @@ fn trans_closure(bcx_maybe: &option::t<@block_ctxt>, some(llself) { populate_fn_ctxt_from_llself(fcx, llself); } _ { } } + + // Create the first basic block in the function and keep a handle on it to + // pass to finish_fn later. + let bcx = new_top_block_ctxt(fcx); + let lltop = bcx.llbb; + let block_ty = node_id_type(cx.ccx, f.body.node.id); + let arg_tys = arg_tys_of_fn(fcx.lcx.ccx, id); - copy_args_to_allocas(fcx, f.decl.inputs); + copy_args_to_allocas(fcx, bcx, f.decl.inputs, arg_tys); // Figure out if we need to build a closure and act accordingly let res = alt f.proto { @@ -6019,12 +6010,6 @@ fn trans_closure(bcx_maybe: &option::t<@block_ctxt>, _ { none } }; - // Create the first basic block in the function and keep a handle on it to - // pass to finish_fn later. - let bcx = new_top_block_ctxt(fcx); - add_cleanups_for_args(bcx, f.decl.inputs, arg_tys); - let lltop = bcx.llbb; - let block_ty = node_id_type(cx.ccx, f.body.node.id); // This call to trans_block is the place where we bridge between // translation calls that don't have a return value (trans_crate, @@ -6150,8 +6135,8 @@ fn trans_tag_variant(cx: @local_ctxt, tag_id: ast::node_id, i += 1u; } let arg_tys = arg_tys_of_fn(cx.ccx, variant.node.id); - copy_args_to_allocas(fcx, fn_args); let bcx = new_top_block_ctxt(fcx); + copy_args_to_allocas(fcx, bcx, fn_args, arg_tys); let lltop = bcx.llbb; // Cast the tag to a type we can GEP into. @@ -6370,34 +6355,16 @@ fn create_main_wrapper(ccx: &@crate_ctxt, sp: &span, let bcx = new_top_block_ctxt(fcx); let lltop = bcx.llbb; - if takes_ivec { - let lloutputarg = llvm::LLVMGetParam(llfdecl, 0u); - let lltaskarg = llvm::LLVMGetParam(llfdecl, 1u); - let llenvarg = llvm::LLVMGetParam(llfdecl, 2u); - let llargvarg = llvm::LLVMGetParam(llfdecl, 3u); - let args = ~[lloutputarg, - lltaskarg, - llenvarg, - llargvarg]; - bcx.build.FastCall(main_llfn, args); - } else { - let lloutputarg = llvm::LLVMGetParam(llfdecl, 0u); - let lltaskarg = llvm::LLVMGetParam(llfdecl, 1u); - let llenvarg = llvm::LLVMGetParam(llfdecl, 2u); - let llargvarg = llvm::LLVMGetParam(llfdecl, 3u); - - // If the crate's main function doesn't take the args vector then - // we're responsible for freeing it - let llivecptr = alloca(bcx, val_ty(llargvarg)); - bcx.build.Store(llargvarg, llivecptr); - bcx = maybe_free_ivec_heap_part(bcx, llivecptr, - ty::mk_str(ccx.tcx)).bcx; - - let args = ~[lloutputarg, - lltaskarg, - llenvarg]; - bcx.build.FastCall(main_llfn, args); - } + let lloutputarg = llvm::LLVMGetParam(llfdecl, 0u); + let lltaskarg = llvm::LLVMGetParam(llfdecl, 1u); + let llenvarg = llvm::LLVMGetParam(llfdecl, 2u); + let llargvarg = llvm::LLVMGetParam(llfdecl, 3u); + let args = ~[lloutputarg, lltaskarg, llenvarg]; + if takes_ivec { args += ~[llargvarg]; } + bcx.build.FastCall(main_llfn, args); + // We're responsible for freeing the arg vector + bcx = maybe_free_ivec_heap_part(bcx, llargvarg, + ty::mk_str(ccx.tcx)).bcx; build_return(bcx); finish_fn(fcx, lltop); @@ -6611,7 +6578,6 @@ fn decl_native_fn_and_pair(ccx: &@crate_ctxt, sp: &span, path: &[str], let args = ty::ty_fn_args(ccx.tcx, fn_type); // Build up the list of arguments. - let drop_args: [{val: ValueRef, ty: ty::t}] = ~[]; let i = arg_n; for arg: ty::arg in args { let llarg = llvm::LLVMGetParam(fcx.llfn, i); @@ -6620,9 +6586,6 @@ fn decl_native_fn_and_pair(ccx: &@crate_ctxt, sp: &span, path: &[str], let llarg_i32 = convert_arg_to_i32(bcx, llarg, arg.ty, arg.mode); call_args += ~[llarg_i32]; } else { call_args += ~[llarg]; } - if arg.mode == ty::mo_val { - drop_args += ~[{val: llarg, ty: arg.ty}]; - } i += 1u; } let r; @@ -6652,8 +6615,7 @@ fn decl_native_fn_and_pair(ccx: &@crate_ctxt, sp: &span, path: &[str], rptr = result.rptr; } _ { - r = - trans_native_call(bcx.build, ccx.externs, + r = trans_native_call(bcx.build, ccx.externs, ccx.llmod, name, call_args); rptr = bcx.build.BitCast(fcx.llretptr, T_ptr(T_i32())); } @@ -6664,9 +6626,6 @@ fn decl_native_fn_and_pair(ccx: &@crate_ctxt, sp: &span, path: &[str], if !rty_is_nil && !uses_retptr { bcx.build.Store(r, rptr); } - for d: {val: ValueRef, ty: ty::t} in drop_args { - bcx = drop_ty(bcx, d.val, d.ty).bcx; - } build_return(bcx); finish_fn(fcx, lltop); } @@ -6980,7 +6939,8 @@ fn write_metadata(cx: &@crate_ctxt, crate: &@ast::crate) { } fn trans_crate(sess: &session::session, crate: &@ast::crate, tcx: &ty::ctxt, - output: &str, amap: &ast_map::map) -> ModuleRef { + output: &str, amap: &ast_map::map, mut_map: alias::mut_map) + -> ModuleRef { let llmod = llvm::LLVMModuleCreateWithNameInContext(str::buf("rust_out"), llvm::LLVMGetGlobalContext()); @@ -7032,6 +6992,7 @@ fn trans_crate(sess: &session::session, crate: &@ast::crate, tcx: &ty::ctxt, type_sha1s: sha1s, type_short_names: short_names, tcx: tcx, + mut_map: mut_map, stats: {mutable n_static_tydescs: 0u, mutable n_derived_tydescs: 0u, diff --git a/src/comp/middle/trans_common.rs b/src/comp/middle/trans_common.rs index 732c8305f848b..35bd5c04295ca 100644 --- a/src/comp/middle/trans_common.rs +++ b/src/comp/middle/trans_common.rs @@ -143,6 +143,7 @@ type crate_ctxt = { type_sha1s: hashmap, type_short_names: hashmap, tcx: ty::ctxt, + mut_map: alias::mut_map, stats: stats, upcalls: @upcall::upcalls, rust_object_type: TypeRef, diff --git a/src/comp/middle/trans_objects.rs b/src/comp/middle/trans_objects.rs index 8a95fb903345a..534f3648735c3 100644 --- a/src/comp/middle/trans_objects.rs +++ b/src/comp/middle/trans_objects.rs @@ -50,17 +50,17 @@ fn trans_obj(cx: @local_ctxt, sp: &span, ob: &ast::_obj, } let fcx = new_fn_ctxt(cx, sp, llctor_decl); + // Create the first block context in the function and keep a handle on it + // to pass to finish_fn later. + let bcx = new_top_block_ctxt(fcx); + let lltop = bcx.llbb; + // Both regular arguments and type parameters are handled here. create_llargs_for_fn_args(fcx, ast::proto_fn, none::, ty::ret_ty_of_fn(ccx.tcx, ctor_id), fn_args, ty_params); let arg_tys: [ty::arg] = arg_tys_of_fn(ccx, ctor_id); - copy_args_to_allocas(fcx, fn_args); - - // Create the first block context in the function and keep a handle on it - // to pass to finish_fn later. - let bcx = new_top_block_ctxt(fcx); - let lltop = bcx.llbb; + copy_args_to_allocas(fcx, bcx, fn_args, arg_tys); // Pick up the type of this object by looking at our own output type, that // is, the output type of the object constructor we're building. diff --git a/src/comp/syntax/fold.rs b/src/comp/syntax/fold.rs index 5593ddb21c6b2..b5b28e028d3ae 100644 --- a/src/comp/syntax/fold.rs +++ b/src/comp/syntax/fold.rs @@ -337,7 +337,6 @@ fn noop_fold_expr(e: &expr_, fld: ast_fold) -> expr_ { let fold_mac = bind fold_mac_(_, fld); - ret alt e { expr_vec(exprs, mut) { expr_vec(fld.map_exprs(fld.fold_expr, exprs), mut) diff --git a/src/comp/syntax/parse/parser.rs b/src/comp/syntax/parse/parser.rs index 2d11ae974d3d1..846ac3a03c273 100644 --- a/src/comp/syntax/parse/parser.rs +++ b/src/comp/syntax/parse/parser.rs @@ -1106,7 +1106,8 @@ fn parse_dot_or_call_expr_with(p: &parser, e: @ast::expr) -> @ast::expr { parse_seq(token::LPAREN, token::RPAREN, some(token::COMMA), parse_expr, p); hi = es.span.hi; - e = mk_expr(p, lo, hi, ast::expr_call(e, es.node)); + let nd = ast::expr_call(e, es.node); + e = mk_expr(p, lo, hi, nd); } } token::LBRACKET. { diff --git a/src/rt/main.ll.in b/src/rt/main.ll.in index 5f33f89da4c64..391f4d8daaf3f 100644 --- a/src/rt/main.ll.in +++ b/src/rt/main.ll.in @@ -16,12 +16,11 @@ declare i32 @rust_start(i32, i32, i32, i32) -declare external fastcc void @_rust_main(i1* nocapture, %task*, %2* nocapture, %ivec) +declare external fastcc void @_rust_main(i1* nocapture, %task*, %2* nocapture, %ivec*) define void @_rust_main_wrap(i1* nocapture, %task *, %2* nocapture, %ivec *) { - %ivec = load %ivec *%3 - tail call fastcc void @_rust_main(i1* %0, %task *%1, %2* nocapture %2, %ivec %ivec) + tail call fastcc void @_rust_main(i1* %0, %task *%1, %2* nocapture %2, %ivec* %3) ret void } diff --git a/src/test/run-pass/export-unexported-dep.rs b/src/test/run-pass/export-unexported-dep.rs index 8f1d54ea5a5d9..7f453ad6ca546 100644 --- a/src/test/run-pass/export-unexported-dep.rs +++ b/src/test/run-pass/export-unexported-dep.rs @@ -6,7 +6,7 @@ mod foo { export g; // not exported - tag t { t1; } + tag t { t1; t2; } fn f() -> t { ret t1; }