From ef50d0e668635824cc5ed86aaa385dd6f3181b53 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Mon, 31 Jan 2011 18:06:35 -0800 Subject: More work on derived tydescs. Can compile simple tests with generic objects. --- src/comp/middle/trans.rs | 78 ++++++++++++++++++++++++++++++------------------ 1 file changed, 49 insertions(+), 29 deletions(-) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 8eb614e5..7755ed93 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -997,7 +997,7 @@ fn get_tydesc(&@block_ctxt cx, @ty.t t) -> result { vec(p2i(bcx.fcx.ccx.crate_ptr), sz.val, align.val, - C_int(n_params as int), + C_int((1u + n_params) as int), bcx.build.PtrToInt(tydescs, T_int()))); ret res(v.bcx, v.bcx.build.IntToPtr(v.val, T_ptr(T_tydesc()))); @@ -2193,6 +2193,34 @@ fn lval_val(@block_ctxt cx, ValueRef val) -> lval_result { llobj=none[ValueRef]); } +fn lval_generic_fn(@block_ctxt cx, + ty.ty_params_and_ty tpt, + ast.def_id fn_id, + &ast.ann ann) + -> lval_result { + + check (cx.fcx.ccx.fn_pairs.contains_key(fn_id)); + auto lv = lval_val(cx, cx.fcx.ccx.fn_pairs.get(fn_id)); + auto monoty = node_ann_type(cx.fcx.ccx, ann); + auto tys = ty.resolve_ty_params(tpt, monoty); + + if (_vec.len[@ty.t](tys) != 0u) { + auto bcx = cx; + let vec[ValueRef] tydescs = vec(); + for (@ty.t t in tys) { + auto td = get_tydesc(bcx, t); + bcx = td.bcx; + append[ValueRef](tydescs, td.val); + } + auto gen = rec( item_type = tpt._1, + tydescs = tydescs ); + lv = rec(res = res(bcx, lv.res.val), + generic = some[generic_info](gen) + with lv); + } + ret lv; +} + fn trans_path(@block_ctxt cx, &ast.path p, &option.t[ast.def] dopt, &ast.ann ann) -> lval_result { alt (dopt) { @@ -2215,39 +2243,33 @@ fn trans_path(@block_ctxt cx, &ast.path p, &option.t[ast.def] dopt, ret lval_mem(cx, cx.fcx.llobjfields.get(did)); } case (ast.def_fn(?did)) { - check (cx.fcx.ccx.fn_pairs.contains_key(did)); - check (cx.fcx.ccx.item_ids.contains_key(did)); - + check (cx.fcx.ccx.items.contains_key(did)); auto fn_item = cx.fcx.ccx.items.get(did); - auto lv = lval_val(cx, cx.fcx.ccx.fn_pairs.get(did)); - auto monoty = node_ann_type(cx.fcx.ccx, ann); - auto tys = ty.resolve_ty_params(fn_item, monoty); - - if (_vec.len[@ty.t](tys) != 0u) { - auto bcx = cx; - let vec[ValueRef] tydescs = vec(); - for (@ty.t t in tys) { - auto td = get_tydesc(bcx, t); - bcx = td.bcx; - append[ValueRef](tydescs, td.val); - } - auto gen = rec( item_type = ty.item_ty(fn_item)._1, - tydescs = tydescs ); - lv = rec(res = res(bcx, lv.res.val), - generic = some[generic_info](gen) - with lv); - } - - ret lv; + ret lval_generic_fn(cx, ty.item_ty(fn_item), did, ann); } case (ast.def_obj(?did)) { - check (cx.fcx.ccx.fn_pairs.contains_key(did)); - ret lval_val(cx, cx.fcx.ccx.fn_pairs.get(did)); + check (cx.fcx.ccx.items.contains_key(did)); + auto fn_item = cx.fcx.ccx.items.get(did); + ret lval_generic_fn(cx, ty.item_ty(fn_item), did, ann); } case (ast.def_variant(?tid, ?vid)) { check (cx.fcx.ccx.tags.contains_key(tid)); if (cx.fcx.ccx.fn_pairs.contains_key(vid)) { - ret lval_val(cx, cx.fcx.ccx.fn_pairs.get(vid)); + check (cx.fcx.ccx.items.contains_key(tid)); + auto tag_item = cx.fcx.ccx.items.get(tid); + auto params = ty.item_ty(tag_item)._0; + auto fty = ty.plain_ty(ty.ty_nil); + alt (tag_item.node) { + case (ast.item_tag(_, ?variants, _, _)) { + for (ast.variant v in variants) { + if (v.id == vid) { + fty = node_ann_type(cx.fcx.ccx, + v.ann); + } + } + } + } + ret lval_generic_fn(cx, tup(params, fty), vid, ann); } else { // Nullary variants are just scalar constants. check (cx.fcx.ccx.item_ids.contains_key(vid)); @@ -3798,7 +3820,6 @@ fn collect_item(&@crate_ctxt cx, @ast.item i) -> @crate_ctxt { alt (i.node) { case (ast.item_fn(?name, ?f, _, ?fid, ?ann)) { - // TODO: type-params cx.items.insert(fid, i); if (! cx.obj_methods.contains_key(fid)) { decl_fn_and_pair(cx, "fn", name, ann, fid); @@ -3806,7 +3827,6 @@ fn collect_item(&@crate_ctxt cx, @ast.item i) -> @crate_ctxt { } case (ast.item_obj(?name, ?ob, _, ?oid, ?ann)) { - // TODO: type-params cx.items.insert(oid, i); decl_fn_and_pair(cx, "obj_ctor", name, ann, oid); for (@ast.method m in ob.methods) { -- cgit v1.2.3 From 8ef22972dbe50b2e05c8983769a638fd5b6a23b5 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Tue, 1 Feb 2011 14:56:21 -0800 Subject: Add ty_type. --- src/comp/middle/trans.rs | 1 + 1 file changed, 1 insertion(+) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 7755ed93..2926b78c 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -471,6 +471,7 @@ fn type_of_inner(@crate_ctxt cx, @ty.t t) -> TypeRef { case (ty.ty_param(_)) { ret T_typaram_ptr(); } + case (ty.ty_type) { ret T_ptr(T_tydesc()); } } fail; } -- cgit v1.2.3 From eb16942c1de42c2f30f7e0eb0ff69371a167f7bd Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Tue, 1 Feb 2011 14:57:03 -0800 Subject: Use dynamic GEP and silly offset-encoding on tydescs. Successful call into a derived tydesc. --- src/comp/middle/trans.rs | 110 ++++++++++++++++++++++++++++++----------------- 1 file changed, 70 insertions(+), 40 deletions(-) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 2926b78c..446b4f10 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -16,6 +16,7 @@ import back.x86; import back.abi; import middle.ty.pat_ty; +import middle.ty.plain_ty; import util.common; import util.common.append; @@ -341,7 +342,7 @@ fn type_of_fn_full(@crate_ctxt cx, @ty.t output) -> TypeRef { let vec[TypeRef] atys = vec(T_taskptr()); - auto fn_ty = ty.plain_ty(ty.ty_fn(inputs, output)); + auto fn_ty = plain_ty(ty.ty_fn(inputs, output)); auto ty_param_count = ty.count_ty_params(fn_ty); auto i = 0u; while (i < ty_param_count) { @@ -869,7 +870,7 @@ fn GEP_tup_like(@block_ctxt cx, @ty.t t, // flattened the incoming structure. auto s = split_type(t, ixs, 0u); - auto prefix_ty = ty.plain_ty(ty.ty_tup(s.prefix)); + auto prefix_ty = plain_ty(ty.ty_tup(s.prefix)); auto bcx = cx; auto sz = size_of(bcx, prefix_ty); bcx = sz.bcx; @@ -985,7 +986,12 @@ fn get_tydesc(&@block_ctxt cx, @ty.t t) -> result { auto i = 0; for (ValueRef td in tys._1) { auto tdp = cx.build.GEP(tydescs, vec(C_int(0), C_int(i))); - cx.build.Store(td, tdp); + if (i == 0) { + cx.build.Store(root, tdp); + } else { + cx.build.Store(td, tdp); + } + i += 1; } auto bcx = cx; @@ -1023,19 +1029,30 @@ fn make_tydesc(@crate_ctxt cx, @ty.t t, vec[ast.def_id] typaram_defs) { auto glue_fn_ty = T_ptr(T_fn(vec(T_taskptr(), T_ptr(T_ptr(T_tydesc())), pvoid), T_void())); + + // FIXME: this adjustment has to do with the ridiculous encoding of + // glue-pointer-constants in the tydesc records: They are tydesc-relative + // displacements. This is purely for compatibility with rustboot and + // should go when it is discarded. + fn off(ValueRef tydescp, + ValueRef gluefn) -> ValueRef { + ret i2p(llvm.LLVMConstSub(p2i(gluefn), p2i(tydescp)), + val_ty(gluefn)); + } + + auto name = sanitize(cx.names.next("tydesc_" + ty.ty_to_str(t))); + auto gvar = llvm.LLVMAddGlobal(cx.llmod, T_tydesc(), _str.buf(name)); auto tydesc = C_struct(vec(C_null(T_ptr(T_ptr(T_tydesc()))), llsize_of(llty), llalign_of(llty), - take_glue, // take_glue_off - drop_glue, // drop_glue_off + off(gvar, take_glue), // take_glue_off + off(gvar, drop_glue), // drop_glue_off C_null(glue_fn_ty), // free_glue_off C_null(glue_fn_ty), // sever_glue_off C_null(glue_fn_ty), // mark_glue_off C_null(glue_fn_ty), // obj_drop_glue_off C_null(glue_fn_ty))); // is_stateful - auto name = sanitize(cx.names.next("tydesc_" + ty.ty_to_str(t))); - auto gvar = llvm.LLVMAddGlobal(cx.llmod, val_ty(tydesc), _str.buf(name)); llvm.LLVMSetInitializer(gvar, tydesc); llvm.LLVMSetGlobalConstant(gvar, True); llvm.LLVMSetLinkage(gvar, lib.llvm.LLVMPrivateLinkage @@ -1322,8 +1339,8 @@ fn iter_structural_ty(@block_ctxt cx, ValueRef box_cell, val_and_ty_fn f) -> result { auto box_ptr = cx.build.Load(box_cell); - auto tnil = ty.plain_ty(ty.ty_nil); - auto tbox = ty.plain_ty(ty.ty_box(tnil)); + auto tnil = plain_ty(ty.ty_nil); + auto tbox = plain_ty(ty.ty_box(tnil)); auto inner_cx = new_sub_block_ctxt(cx, "iter box"); auto next_cx = new_sub_block_ctxt(cx, "next"); @@ -1524,7 +1541,7 @@ fn iter_sequence(@block_ctxt cx, ret iter_sequence_body(cx, v, et, f, false); } case (ty.ty_str) { - auto et = ty.plain_ty(ty.ty_machine(common.ty_u8)); + auto et = plain_ty(ty.ty_machine(common.ty_u8)); ret iter_sequence_body(cx, v, et, f, true); } case (_) { fail; } @@ -1542,6 +1559,15 @@ fn call_tydesc_glue_full(@block_ctxt cx, ValueRef v, lltydescs = cx.build.Load(lltydescs); auto llfnptr = cx.build.GEP(tydesc, vec(C_int(0), C_int(field))); auto llfn = cx.build.Load(llfnptr); + + // FIXME: this adjustment has to do with the ridiculous encoding of + // glue-pointer-constants in the tydesc records: They are tydesc-relative + // displacements. This is purely for compatibility with rustboot and + // should go when it is discarded. + llfn = cx.build.IntToPtr(cx.build.Add(cx.build.PtrToInt(llfn, T_int()), + cx.build.PtrToInt(tydesc, T_int())), + val_ty(llfn)); + cx.build.FastCall(llfn, vec(cx.fcx.lltaskptr, lltydescs, llrawptr)); } @@ -2259,7 +2285,7 @@ fn trans_path(@block_ctxt cx, &ast.path p, &option.t[ast.def] dopt, check (cx.fcx.ccx.items.contains_key(tid)); auto tag_item = cx.fcx.ccx.items.get(tid); auto params = ty.item_ty(tag_item)._0; - auto fty = ty.plain_ty(ty.ty_nil); + auto fty = plain_ty(ty.ty_nil); alt (tag_item.node) { case (ast.item_tag(_, ?variants, _, _)) { for (ast.variant v in variants) { @@ -2635,7 +2661,7 @@ fn trans_bind(@block_ctxt cx, @ast.expr f, } // Synthesize a closure type. - let @ty.t bindings_ty = ty.plain_ty(ty.ty_tup(bound_tys)); + let @ty.t bindings_ty = plain_ty(ty.ty_tup(bound_tys)); let TypeRef lltarget_ty = type_of(bcx.fcx.ccx, ty.expr_ty(f)); let TypeRef llbindings_ty = type_of(bcx.fcx.ccx, bindings_ty); let TypeRef llclosure_ty = T_closure_ptr(lltarget_ty, @@ -3593,52 +3619,52 @@ fn trans_obj(@crate_ctxt cx, &ast._obj ob, ast.def_id oid, } // Synthesize an obj body type. - let @ty.t fields_ty = ty.plain_ty(ty.ty_tup(obj_fields)); - let TypeRef llfields_ty = type_of(bcx.fcx.ccx, fields_ty); - let TypeRef llobj_body_ty = - T_ptr(T_box(T_struct(vec(T_ptr(T_tydesc()), - llfields_ty)))); + let @ty.t fields_ty = plain_ty(ty.ty_tup(obj_fields)); + let @ty.t body_ty = plain_ty(ty.ty_tup(vec(plain_ty(ty.ty_type), + fields_ty))); + let @ty.t boxed_body_ty = plain_ty(ty.ty_box(body_ty)); + + let TypeRef llboxed_body_ty = type_of(cx, boxed_body_ty); // Malloc a box for the body. - auto r = trans_malloc_inner(bcx, llobj_body_ty); - bcx = r.bcx; - auto box = r.val; - auto rc = bcx.build.GEP(box, - vec(C_int(0), - C_int(abi.box_rc_field_refcnt))); - auto body = bcx.build.GEP(box, - vec(C_int(0), - C_int(abi.box_rc_field_body))); - bcx.build.Store(C_int(1), rc); + auto box = trans_malloc_inner(bcx, llboxed_body_ty); + bcx = box.bcx; + auto rc = GEP_tup_like(bcx, boxed_body_ty, box.val, + vec(0, abi.box_rc_field_refcnt)); + bcx = rc.bcx; + auto body = GEP_tup_like(bcx, boxed_body_ty, box.val, + vec(0, abi.box_rc_field_body)); + bcx = body.bcx; + bcx.build.Store(C_int(1), rc.val); // Store body tydesc. auto body_tydesc = - bcx.build.GEP(body, - vec(C_int(0), - C_int(abi.obj_body_elt_tydesc))); + GEP_tup_like(bcx, body_ty, body.val, + vec(0, abi.obj_body_elt_tydesc)); + bcx = body_tydesc.bcx; - auto fields_tydesc = get_tydesc(r.bcx, fields_ty); + auto fields_tydesc = get_tydesc(bcx, fields_ty); bcx = fields_tydesc.bcx; - bcx.build.Store(fields_tydesc.val, body_tydesc); + bcx.build.Store(fields_tydesc.val, body_tydesc.val); // Copy args into body fields. auto body_fields = - bcx.build.GEP(body, - vec(C_int(0), - C_int(abi.obj_body_elt_fields))); + GEP_tup_like(bcx, body_ty, body.val, + vec(0, abi.obj_body_elt_fields)); + bcx = body_fields.bcx; let int i = 0; for (ast.obj_field f in ob.fields) { auto arg = bcx.fcx.llargs.get(f.id); arg = load_scalar_or_boxed(bcx, arg, arg_tys.(i).ty); - auto field = bcx.build.GEP(body_fields, - vec(C_int(0),C_int(i))); - bcx = copy_ty(bcx, INIT, field, arg, arg_tys.(i).ty).bcx; + auto field = GEP_tup_like(bcx, fields_ty, body_fields.val, + vec(0, i)); + bcx = field.bcx; + bcx = copy_ty(bcx, INIT, field.val, arg, arg_tys.(i).ty).bcx; i += 1; } - // Store box ptr in outer pair. - auto p = bcx.build.PointerCast(box, llbox_ty); + auto p = bcx.build.PointerCast(box.val, llbox_ty); bcx.build.Store(p, pair_box); } bcx.build.Ret(bcx.build.Load(pair)); @@ -4030,6 +4056,10 @@ fn p2i(ValueRef v) -> ValueRef { ret llvm.LLVMConstPtrToInt(v, T_int()); } +fn i2p(ValueRef v, TypeRef t) -> ValueRef { + ret llvm.LLVMConstIntToPtr(v, t); +} + fn trans_exit_task_glue(@crate_ctxt cx) { let vec[TypeRef] T_args = vec(); let vec[ValueRef] V_args = vec(); -- cgit v1.2.3 From 70bf54bcac587c0bc8a3a593bda75115e4c23aa8 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Tue, 1 Feb 2011 16:23:48 -0800 Subject: Implement 'else if' --- src/comp/middle/trans.rs | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 446b4f10..c08147fe 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -1957,8 +1957,9 @@ fn join_results(@block_ctxt parent_cx, ret res(join_cx, phi); } -fn trans_if(@block_ctxt cx, @ast.expr cond, - &ast.block thn, &option.t[ast.block] els) -> result { +fn trans_if(@block_ctxt cx, @ast.expr cond, &ast.block thn, + &vec[tup(@ast.expr, ast.block)] elifs, + &option.t[ast.block] els) -> result { auto cond_res = trans_expr(cx, cond); @@ -1968,11 +1969,25 @@ fn trans_if(@block_ctxt cx, @ast.expr cond, auto else_cx = new_scope_block_ctxt(cx, "else"); auto else_res = res(else_cx, C_nil()); - alt (els) { - case (some[ast.block](?eblk)) { - else_res = trans_block(else_cx, eblk); + auto num_elifs = _vec.len[tup(@ast.expr, ast.block)](elifs); + if (num_elifs > 0u) { + auto next_elif = elifs.(0u); + auto next_elifthn = next_elif._0; + auto next_elifcnd = next_elif._1; + auto rest_elifs = _vec.shift[tup(@ast.expr, ast.block)](elifs); + else_res = trans_if(else_cx, next_elifthn, next_elifcnd, + rest_elifs, els); + } + + /* else: FIXME: rustboot has a problem here + with preconditions inside an else block */ + if (num_elifs == 0u) { + alt (els) { + case (some[ast.block](?eblk)) { + else_res = trans_block(else_cx, eblk); + } + case (_) { /* fall through */ } } - case (_) { /* fall through */ } } cond_res.bcx.build.CondBr(cond_res.val, @@ -2901,8 +2916,8 @@ fn trans_expr(@block_ctxt cx, @ast.expr e) -> result { ret trans_binary(cx, op, x, y); } - case (ast.expr_if(?cond, ?thn, ?els, _)) { - ret trans_if(cx, cond, thn, els); + case (ast.expr_if(?cond, ?thn, ?elifs, ?els, _)) { + ret trans_if(cx, cond, thn, elifs, els); } case (ast.expr_for(?decl, ?seq, ?body, _)) { -- cgit v1.2.3 From f22dc4d581760d365392323a431f4787f31ae130 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Tue, 1 Feb 2011 18:02:57 -0800 Subject: Fix buggy argument assembly for upcall_get_type_desc. Can now complete calls to glue of derived tydescs. --- src/comp/middle/trans.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index c08147fe..c955340e 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -983,14 +983,14 @@ fn get_tydesc(&@block_ctxt cx, @ty.t t) -> result { auto root = cx.fcx.ccx.tydescs.get(t); auto tydescs = cx.build.Alloca(T_array(T_ptr(T_tydesc()), n_params)); + auto i = 0; + auto tdp = cx.build.GEP(tydescs, vec(C_int(0), C_int(i))); + cx.build.Store(root, tdp); + i += 1; for (ValueRef td in tys._1) { auto tdp = cx.build.GEP(tydescs, vec(C_int(0), C_int(i))); - if (i == 0) { - cx.build.Store(root, tdp); - } else { - cx.build.Store(td, tdp); - } + cx.build.Store(td, tdp); i += 1; } -- cgit v1.2.3 From 8e963f63a8d076c8e2f162ba27c49e6cb1dacb96 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Wed, 2 Feb 2011 15:23:49 -0800 Subject: Add trace and trap helpers to trans for low level diagnostics. --- src/comp/middle/trans.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index c955340e..d091e3ad 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -4186,6 +4186,24 @@ fn declare_intrinsics(ModuleRef llmod) -> hashmap[str,ValueRef] { ret intrinsics; } + +fn trace_str(@block_ctxt cx, str s) { + trans_upcall(cx, "upcall_trace_str", vec(p2i(C_cstr(cx.fcx.ccx, s)))); +} + +fn trace_word(@block_ctxt cx, ValueRef v) { + trans_upcall(cx, "upcall_trace_word", vec(v)); +} + +fn trace_ptr(@block_ctxt cx, ValueRef v) { + trace_word(cx, cx.build.PtrToInt(v, T_int())); +} + +fn trap(@block_ctxt bcx) { + let vec[ValueRef] v = vec(); + bcx.build.Call(bcx.fcx.ccx.intrinsics.get("llvm.trap"), v); +} + fn check_module(ModuleRef llmod) { auto pm = mk_pass_manager(); llvm.LLVMAddVerifierPass(pm.llpm); -- cgit v1.2.3 From c42a2d2bfb9cf8b4b44f28942d2d3f2838611c19 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Wed, 2 Feb 2011 15:25:53 -0800 Subject: Change decl_upcall to decl_upcall_glue, more correct name. --- src/comp/middle/trans.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index d091e3ad..dff95974 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -612,7 +612,7 @@ fn decl_glue(ModuleRef llmod, str s) -> ValueRef { ret decl_cdecl_fn(llmod, s, T_fn(vec(T_taskptr()), T_void())); } -fn decl_upcall(ModuleRef llmod, uint _n) -> ValueRef { +fn decl_upcall_glue(ModuleRef llmod, uint _n) -> ValueRef { // It doesn't actually matter what type we come up with here, at the // moment, as we cast the upcall function pointers to int before passing // them to the indirect upcall-invocation glue. But eventually we'd like @@ -4324,7 +4324,7 @@ fn make_glues(ModuleRef llmod) -> @glue_fns { T_fn(vec(T_taskptr()), T_void())), upcall_glues = - _vec.init_fn[ValueRef](bind decl_upcall(llmod, _), + _vec.init_fn[ValueRef](bind decl_upcall_glue(llmod, _), abi.n_upcall_glues as uint), no_op_type_glue = make_no_op_type_glue(llmod), memcpy_glue = make_memcpy_glue(llmod), -- cgit v1.2.3 From c61ff989850f2f77fad9fd1f032632d559e8edab Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Wed, 2 Feb 2011 15:26:16 -0800 Subject: Handle missing case in linearize_ty_params. --- src/comp/middle/trans.rs | 1 + 1 file changed, 1 insertion(+) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index dff95974..66ce8186 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -943,6 +943,7 @@ fn linearize_ty_params(@block_ctxt cx, @ty.t t) r.defs += pid; } } + case (_) { } } ret t; } -- cgit v1.2.3 From b37995664b0149ee92269a3e11f7f6228fe48cc7 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Wed, 2 Feb 2011 15:28:11 -0800 Subject: Store tydesc for whole body, not just fields, in objs and closures. Handles unusual field alignment. --- src/comp/middle/trans.rs | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 66ce8186..36f54ea8 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -1185,16 +1185,12 @@ fn make_drop_glue(@block_ctxt cx, ValueRef v, @ty.t t) -> result { vec(C_int(0), C_int(abi.box_rc_field_body))); - auto fields = - cx.build.GEP(body, - vec(C_int(0), - C_int(abi.obj_body_elt_fields))); auto tydescptr = cx.build.GEP(body, vec(C_int(0), C_int(abi.obj_body_elt_tydesc))); - call_tydesc_glue_full(cx, fields, cx.build.Load(tydescptr), + call_tydesc_glue_full(cx, body, cx.build.Load(tydescptr), abi.tydesc_field_drop_glue_off); // Then free the body. @@ -1223,17 +1219,12 @@ fn make_drop_glue(@block_ctxt cx, ValueRef v, @ty.t t) -> result { vec(C_int(0), C_int(abi.box_rc_field_body))); - auto bindings = - cx.build.GEP(body, - vec(C_int(0), - C_int(abi.closure_elt_bindings))); - auto tydescptr = cx.build.GEP(body, vec(C_int(0), C_int(abi.closure_elt_tydesc))); - call_tydesc_glue_full(cx, bindings, cx.build.Load(tydescptr), + call_tydesc_glue_full(cx, body, cx.build.Load(tydescptr), abi.tydesc_field_drop_glue_off); @@ -3659,9 +3650,9 @@ fn trans_obj(@crate_ctxt cx, &ast._obj ob, ast.def_id oid, vec(0, abi.obj_body_elt_tydesc)); bcx = body_tydesc.bcx; - auto fields_tydesc = get_tydesc(bcx, fields_ty); - bcx = fields_tydesc.bcx; - bcx.build.Store(fields_tydesc.val, body_tydesc.val); + auto body_td = get_tydesc(bcx, body_ty); + bcx = body_td.bcx; + bcx.build.Store(body_td.val, body_tydesc.val); // Copy args into body fields. auto body_fields = -- cgit v1.2.3 From c863427b64f51fd55cc6191ed08cbfb88034d05b Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Wed, 2 Feb 2011 16:22:11 -0800 Subject: Hack to work around apparent LLVM bug? --- src/comp/middle/trans.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 36f54ea8..3db5be5f 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -3229,7 +3229,13 @@ fn new_block_ctxt(@fn_ctxt cx, block_parent parent, // Use this when you're at the top block of a function or the like. fn new_top_block_ctxt(@fn_ctxt fcx) -> @block_ctxt { - ret new_block_ctxt(fcx, parent_none, SCOPE_BLOCK, "function top level"); + auto cx = new_block_ctxt(fcx, parent_none, SCOPE_BLOCK, + "function top level"); + + // FIXME: hack to give us some spill room to make up for an LLVM + // bug where it destroys its own callee-saves. + cx.build.Alloca(T_array(T_int(), 10u)); + ret cx; } // Use this when you're at a curly-brace or similar lexical scope. -- cgit v1.2.3 From ce17fe2a90737425eed9305cd24e4c6f71b78dbd Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Wed, 2 Feb 2011 17:49:15 -0800 Subject: Attempt to put out burning tinderbox. --- src/comp/middle/trans.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 3db5be5f..b1c84ace 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -1218,13 +1218,17 @@ fn make_drop_glue(@block_ctxt cx, ValueRef v, @ty.t t) -> result { cx.build.GEP(v, vec(C_int(0), C_int(abi.box_rc_field_body))); + auto bindings = + cx.build.GEP(body, + vec(C_int(0), + C_int(abi.closure_elt_bindings))); auto tydescptr = cx.build.GEP(body, vec(C_int(0), C_int(abi.closure_elt_tydesc))); - call_tydesc_glue_full(cx, body, cx.build.Load(tydescptr), + call_tydesc_glue_full(cx, bindings, cx.build.Load(tydescptr), abi.tydesc_field_drop_glue_off); -- cgit v1.2.3 From be97a77be81d286b1ae90c1050da1c7c0477ea3f Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 3 Feb 2011 14:40:57 -0800 Subject: Capture typarams into obj, independent of body tydesc. --- src/comp/middle/trans.rs | 95 +++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 77 insertions(+), 18 deletions(-) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index b1c84ace..4610cef6 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -75,6 +75,7 @@ state type crate_ctxt = rec(session.session sess, hashmap[ast.def_id, ValueRef] consts, hashmap[ast.def_id,()] obj_methods, hashmap[@ty.t, ValueRef] tydescs, + vec[ast.ty_param] obj_typarams, vec[ast.obj_field] obj_fields, @glue_fns glues, namegen names, @@ -327,6 +328,24 @@ fn T_opaque_closure_ptr() -> TypeRef { T_nil()); } +fn T_captured_tydescs(uint n) -> TypeRef { + ret T_struct(_vec.init_elt[TypeRef](T_ptr(T_tydesc()), n)); +} + +fn T_obj(uint n_captured_tydescs, TypeRef llfields_ty) -> TypeRef { + ret T_struct(vec(T_ptr(T_tydesc()), + T_captured_tydescs(n_captured_tydescs), + llfields_ty)); +} + +fn T_obj_ptr(uint n_captured_tydescs, TypeRef llfields_ty) -> TypeRef { + ret T_ptr(T_box(T_obj(n_captured_tydescs, llfields_ty))); +} + +fn T_opaque_obj_ptr() -> TypeRef { + ret T_obj_ptr(0u, T_nil()); +} + fn type_of(@crate_ctxt cx, @ty.t t) -> TypeRef { let TypeRef llty = type_of_inner(cx, t); @@ -455,11 +474,9 @@ fn type_of_inner(@crate_ctxt cx, @ty.t t) -> TypeRef { mtys += T_ptr(mty); } let TypeRef vtbl = T_struct(mtys); - let TypeRef body = T_struct(vec(T_ptr(T_tydesc()), - T_nil())); - let TypeRef pair = - T_struct(vec(T_ptr(vtbl), - T_ptr(T_box(body)))); + let TypeRef pair = T_struct(vec(T_ptr(vtbl), + T_opaque_obj_ptr())); + auto abs_pair = llvm.LLVMResolveTypeHandle(th.llth); llvm.LLVMRefineType(abs_pair, pair); abs_pair = llvm.LLVMResolveTypeHandle(th.llth); @@ -963,6 +980,7 @@ fn get_tydesc(&@block_ctxt cx, @ty.t t) -> result { // Is the supplied type a type param? If so, return the passed-in tydesc. alt (ty.type_param(t)) { case (some[ast.def_id](?id)) { + check (cx.fcx.lltydescs.contains_key(id)); ret res(cx, cx.fcx.lltydescs.get(id)); } case (none[ast.def_id]) { /* fall through */ } @@ -3474,7 +3492,7 @@ fn ret_ty_of_fn(ast.ann ann) -> @ty.t { ret ret_ty_of_fn_ty(ty.ann_to_type(ann)); } -fn create_llobjfields_for_fields(@block_ctxt cx, ValueRef llself) { +fn populate_fn_ctxt_from_llself(@block_ctxt cx, ValueRef llself) { let vec[TypeRef] llfield_tys = vec(); @@ -3482,11 +3500,9 @@ fn create_llobjfields_for_fields(@block_ctxt cx, ValueRef llself) { llfield_tys += node_type(cx.fcx.ccx, f.ann); } - let TypeRef llfields_ty = T_struct(llfield_tys); - let TypeRef lltydesc_ty = T_ptr(T_tydesc()); - let TypeRef llobj_body_ty = T_struct(vec(lltydesc_ty, - llfields_ty)); - let TypeRef llobj_box_ty = T_ptr(T_box(llobj_body_ty)); + auto n_typarams = _vec.len[ast.ty_param](cx.fcx.ccx.obj_typarams); + let TypeRef llobj_box_ty = T_obj_ptr(n_typarams, + T_struct(llfield_tys)); auto box_cell = cx.build.GEP(llself, @@ -3497,12 +3513,28 @@ fn create_llobjfields_for_fields(@block_ctxt cx, ValueRef llself) { box_ptr = cx.build.PointerCast(box_ptr, llobj_box_ty); + auto obj_typarams = cx.build.GEP(box_ptr, + vec(C_int(0), + C_int(abi.box_rc_field_body), + C_int(abi.obj_body_elt_typarams))); + auto obj_fields = cx.build.GEP(box_ptr, vec(C_int(0), C_int(abi.box_rc_field_body), C_int(abi.obj_body_elt_fields))); let int i = 0; + + for (ast.ty_param p in cx.fcx.ccx.obj_typarams) { + let ValueRef lltyparam = cx.build.GEP(obj_typarams, + vec(C_int(0), + C_int(i))); + lltyparam = cx.build.Load(lltyparam); + cx.fcx.lltydescs.insert(p.id, lltyparam); + i += 1; + } + + i = 0; for (ast.obj_field f in cx.fcx.ccx.obj_fields) { let ValueRef llfield = cx.build.GEP(obj_fields, vec(C_int(0), @@ -3529,7 +3561,7 @@ fn trans_fn(@crate_ctxt cx, &ast._fn f, ast.def_id fid, alt (fcx.llself) { case (some[ValueRef](?llself)) { - create_llobjfields_for_fields(bcx, llself); + populate_fn_ctxt_from_llself(bcx, llself); } case (_) { } @@ -3623,10 +3655,11 @@ fn trans_obj(@crate_ctxt cx, &ast._obj ob, ast.def_id oid, C_int(abi.obj_field_box))); bcx.build.Store(vtbl, pair_vtbl); - let TypeRef llbox_ty = T_ptr(T_box(T_struct(vec(T_ptr(T_tydesc()), - T_nil())))); - if (_vec.len[ty.arg](arg_tys) == 0u) { - // Store null into pair, if no args. + let TypeRef llbox_ty = T_opaque_obj_ptr(); + + if (_vec.len[ast.ty_param](ty_params) == 0u && + _vec.len[ty.arg](arg_tys) == 0u) { + // Store null into pair, if no args or typarams. bcx.build.Store(C_null(llbox_ty), pair_box); } else { // Malloc a box for the body and copy args in. @@ -3636,8 +3669,16 @@ fn trans_obj(@crate_ctxt cx, &ast._obj ob, ast.def_id oid, } // Synthesize an obj body type. + auto tydesc_ty = plain_ty(ty.ty_type); + let vec[@ty.t] tps = vec(); + for (ast.ty_param tp in ty_params) { + append[@ty.t](tps, tydesc_ty); + } + + let @ty.t typarams_ty = plain_ty(ty.ty_tup(tps)); let @ty.t fields_ty = plain_ty(ty.ty_tup(obj_fields)); - let @ty.t body_ty = plain_ty(ty.ty_tup(vec(plain_ty(ty.ty_type), + let @ty.t body_ty = plain_ty(ty.ty_tup(vec(tydesc_ty, + typarams_ty, fields_ty))); let @ty.t boxed_body_ty = plain_ty(ty.ty_box(body_ty)); @@ -3664,13 +3705,28 @@ fn trans_obj(@crate_ctxt cx, &ast._obj ob, ast.def_id oid, bcx = body_td.bcx; bcx.build.Store(body_td.val, body_tydesc.val); + // Copy typarams into captured typarams. + auto body_typarams = + GEP_tup_like(bcx, body_ty, body.val, + vec(0, abi.obj_body_elt_typarams)); + bcx = body_typarams.bcx; + let int i = 0; + for (ast.ty_param tp in ty_params) { + auto typaram = bcx.fcx.lltydescs.get(tp.id); + auto capture = GEP_tup_like(bcx, typarams_ty, body_typarams.val, + vec(0, i)); + bcx = capture.bcx; + bcx = copy_ty(bcx, INIT, capture.val, typaram, tydesc_ty).bcx; + i += 1; + } + // Copy args into body fields. auto body_fields = GEP_tup_like(bcx, body_ty, body.val, vec(0, abi.obj_body_elt_fields)); bcx = body_fields.bcx; - let int i = 0; + i = 0; for (ast.obj_field f in ob.fields) { auto arg = bcx.fcx.llargs.get(f.id); arg = load_scalar_or_boxed(bcx, arg, arg_tys.(i).ty); @@ -3792,6 +3848,7 @@ fn trans_item(@crate_ctxt cx, &ast.item item) { } case (ast.item_obj(?name, ?ob, ?tps, ?oid, ?ann)) { auto sub_cx = @rec(path=cx.path + "." + name, + obj_typarams=tps, obj_fields=ob.fields with *cx); trans_obj(sub_cx, ob, oid, tps, ann); } @@ -4353,6 +4410,7 @@ fn trans_crate(session.session sess, @ast.crate crate, str output, auto hasher = ty.hash_ty; auto eqer = ty.eq_ty; auto tydescs = map.mk_hashmap[@ty.t,ValueRef](hasher, eqer); + let vec[ast.ty_param] obj_typarams = vec(); let vec[ast.obj_field] obj_fields = vec(); auto cx = @rec(sess = sess, @@ -4369,6 +4427,7 @@ fn trans_crate(session.session sess, @ast.crate crate, str output, consts = new_def_hash[ValueRef](), obj_methods = new_def_hash[()](), tydescs = tydescs, + obj_typarams = obj_typarams, obj_fields = obj_fields, glues = glues, names = namegen(0), -- cgit v1.2.3 From 57bb9d809bb029caf7b38042a433153bb965e1fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20=C3=81vila=20de=20Esp=C3=ADndola?= Date: Fri, 4 Feb 2011 11:10:04 -0500 Subject: Parse function declarations. --- src/comp/middle/trans.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 4610cef6..22f4109f 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -3553,10 +3553,10 @@ fn trans_fn(@crate_ctxt cx, &ast._fn f, ast.def_id fid, auto fcx = new_fn_ctxt(cx, cx.path, llfndecl); create_llargs_for_fn_args(fcx, ty_self, ret_ty_of_fn(ann), - f.inputs, ty_params); + f.decl.inputs, ty_params); auto bcx = new_top_block_ctxt(fcx); - copy_args_to_allocas(bcx, ty_self, f.inputs, + copy_args_to_allocas(bcx, ty_self, f.decl.inputs, arg_tys_of_fn(ann)); alt (fcx.llself) { -- cgit v1.2.3 From 74f71d387eceb4235bae89a400292ad6ecde8ca1 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Tue, 8 Feb 2011 11:47:53 -0800 Subject: Overhaul ABI. All retptrs, all the time. --- src/comp/middle/trans.rs | 478 ++++++++++++++++++++++------------------------- 1 file changed, 224 insertions(+), 254 deletions(-) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 22f4109f..9e59cf57 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -83,9 +83,9 @@ state type crate_ctxt = rec(session.session sess, state type fn_ctxt = rec(ValueRef llfn, ValueRef lltaskptr, - ValueRef llclosure, + ValueRef llenv, + ValueRef llretptr, mutable option.t[ValueRef] llself, - mutable option.t[ValueRef] llretptr, hashmap[ast.def_id, ValueRef] llargs, hashmap[ast.def_id, ValueRef] llobjfields, hashmap[ast.def_id, ValueRef] lllocals, @@ -239,13 +239,23 @@ fn T_task() -> TypeRef { )); } +fn T_glue_fn() -> TypeRef { + // Bit of a kludge: pick the fn typeref out of the tydesc.. + let vec[TypeRef] tydesc_elts = _vec.init_elt[TypeRef](T_nil(), 10u); + llvm.LLVMGetStructElementTypes(T_tydesc(), + _vec.buf[TypeRef](tydesc_elts)); + ret llvm.LLVMGetElementType(tydesc_elts.(abi.tydesc_field_drop_glue_off)); +} + fn T_tydesc() -> TypeRef { auto th = mk_type_handle(); auto abs_tydesc = llvm.LLVMResolveTypeHandle(th.llth); auto tydescpp = T_ptr(T_ptr(abs_tydesc)); auto pvoid = T_ptr(T_i8()); - auto glue_fn_ty = T_ptr(T_fn(vec(T_taskptr(), + auto glue_fn_ty = T_ptr(T_fn(vec(T_ptr(T_nil()), + T_taskptr(), + T_ptr(T_nil()), tydescpp, pvoid), T_void())); auto tydesc = T_struct(vec(tydescpp, // first_param @@ -354,25 +364,31 @@ fn type_of(@crate_ctxt cx, @ty.t t) -> TypeRef { ret llty; } -// NB: this must match trans_args and create_llargs_for_fn_args. + +// NB: must keep 4 fns in sync: +// +// - type_of_fn_full +// - create_llargs_for_fn_args. +// - new_fn_ctxt +// - trans_args + fn type_of_fn_full(@crate_ctxt cx, option.t[TypeRef] obj_self, vec[ty.arg] inputs, @ty.t output) -> TypeRef { - let vec[TypeRef] atys = vec(T_taskptr()); - - auto fn_ty = plain_ty(ty.ty_fn(inputs, output)); - auto ty_param_count = ty.count_ty_params(fn_ty); - auto i = 0u; - while (i < ty_param_count) { - atys += T_ptr(T_tydesc()); - i += 1u; - } + let vec[TypeRef] atys = vec(); + // Arg 0: Output pointer. if (ty.type_has_dynamic_size(output)) { atys += T_typaram_ptr(); + } else { + atys += T_ptr(type_of(cx, output)); } + // Arg 1: Task pointer. + atys += T_taskptr(); + + // Arg 2: Env (closure-bindings / self-obj) alt (obj_self) { case (some[TypeRef](?t)) { check (t as int != 0); @@ -383,6 +399,16 @@ fn type_of_fn_full(@crate_ctxt cx, } } + // Args >3: ty params ... + auto ty_param_count = + ty.count_ty_params(plain_ty(ty.ty_fn(inputs, output))); + auto i = 0u; + while (i < ty_param_count) { + atys += T_ptr(T_tydesc()); + i += 1u; + } + + // ... then explicit args. for (ty.arg arg in inputs) { if (ty.type_has_dynamic_size(arg.ty)) { check (arg.mode == ast.alias); @@ -399,14 +425,7 @@ fn type_of_fn_full(@crate_ctxt cx, } } - auto ret_ty; - if (ty.type_is_nil(output) || ty.type_has_dynamic_size(output)) { - ret_ty = llvm.LLVMVoidType(); - } else { - ret_ty = type_of(cx, output); - } - - ret T_fn(atys, ret_ty); + ret T_fn(atys, llvm.LLVMVoidType()); } fn type_of_fn(@crate_ctxt cx, vec[ty.arg] inputs, @ty.t output) -> TypeRef { @@ -663,9 +682,11 @@ fn trans_upcall(@block_ctxt cx, str name, vec[ValueRef] args) -> result { let ValueRef llglue = cx.fcx.ccx.glues.upcall_glues.(n); let vec[ValueRef] call_args = vec(cx.fcx.lltaskptr, llupcall); + for (ValueRef a in args) { call_args += cx.build.ZExtOrBitCast(a, T_int()); } + ret res(cx, cx.build.FastCall(llglue, call_args)); } @@ -1044,10 +1065,7 @@ fn make_tydesc(@crate_ctxt cx, @ty.t t, vec[ast.def_id] typaram_defs) { auto drop_glue = make_generic_glue(cx, t, "drop", dg, typaram_defs); auto llty = type_of(cx, t); - auto pvoid = T_ptr(T_i8()); - auto glue_fn_ty = T_ptr(T_fn(vec(T_taskptr(), - T_ptr(T_ptr(T_tydesc())), - pvoid), T_void())); + auto glue_fn_ty = T_ptr(T_glue_fn()); // FIXME: this adjustment has to do with the ridiculous encoding of // glue-pointer-constants in the tydesc records: They are tydesc-relative @@ -1082,9 +1100,7 @@ fn make_tydesc(@crate_ctxt cx, @ty.t t, vec[ast.def_id] typaram_defs) { fn make_generic_glue(@crate_ctxt cx, @ty.t t, str name, val_and_ty_fn helper, vec[ast.def_id] typaram_defs) -> ValueRef { - auto llfnty = T_fn(vec(T_taskptr(), - T_ptr(T_ptr(T_tydesc())), - T_ptr(T_i8())), T_void()); + auto llfnty = T_glue_fn(); auto fn_name = cx.names.next("_rust_" + name) + "." + ty.ty_to_str(t); fn_name = sanitize(fn_name); @@ -1102,7 +1118,7 @@ fn make_generic_glue(@crate_ctxt cx, @ty.t t, str name, llty = type_of(cx, t); } - auto lltyparams = llvm.LLVMGetParam(llfn, 1u); + auto lltyparams = llvm.LLVMGetParam(llfn, 3u); auto p = 0; for (ast.def_id d in typaram_defs) { auto llparam = bcx.build.GEP(lltyparams, vec(C_int(p))); @@ -1111,7 +1127,7 @@ fn make_generic_glue(@crate_ctxt cx, @ty.t t, str name, p += 1; } - auto llrawptr = llvm.LLVMGetParam(llfn, 2u); + auto llrawptr = llvm.LLVMGetParam(llfn, 4u); auto llval = bcx.build.BitCast(llrawptr, llty); re = helper(bcx, llval, t); @@ -1582,7 +1598,11 @@ fn call_tydesc_glue_full(@block_ctxt cx, ValueRef v, cx.build.PtrToInt(tydesc, T_int())), val_ty(llfn)); - cx.build.FastCall(llfn, vec(cx.fcx.lltaskptr, lltydescs, llrawptr)); + cx.build.FastCall(llfn, vec(C_null(T_ptr(T_nil())), + cx.fcx.lltaskptr, + C_null(T_ptr(T_nil())), + lltydescs, + llrawptr)); } fn call_tydesc_glue(@block_ctxt cx, ValueRef v, @ty.t t, int field) { @@ -2467,103 +2487,6 @@ fn trans_cast(@block_ctxt cx, @ast.expr e, &ast.ann ann) -> result { ret e_res; } - -// NB: this must match type_of_fn_full and create_llargs_for_fn_args. -fn trans_args(@block_ctxt cx, - ValueRef llclosure, - option.t[ValueRef] llobj, - option.t[generic_info] gen, - &vec[@ast.expr] es, - @ty.t fn_ty) - -> tup(@block_ctxt, vec[ValueRef], option.t[ValueRef]) { - let vec[ValueRef] vs = vec(cx.fcx.lltaskptr); - let @block_ctxt bcx = cx; - - let vec[ty.arg] args = ty.ty_fn_args(fn_ty); - - let option.t[ValueRef] llretslot_opt = none[ValueRef]; - - alt (gen) { - case (some[generic_info](?g)) { - for (ValueRef t in g.tydescs) { - vs += t; - } - args = ty.ty_fn_args(g.item_type); - if (ty.type_has_dynamic_size(ty.ty_fn_ret(g.item_type))) { - auto retty = ty.ty_fn_ret(fn_ty); - auto llretty = type_of(cx.fcx.ccx, retty); - auto llretslot = cx.build.Alloca(llretty); - vs += cx.build.PointerCast(llretslot, T_ptr(T_i8())); - llretslot_opt = some[ValueRef](llretslot); - } - } - case (_) { } - } - - alt (llobj) { - case (some[ValueRef](?ob)) { - // Every object is always found in memory, - // and not-yet-loaded (as part of an lval x.y - // doted method-call). - vs += cx.build.Load(ob); - } - case (_) { - vs += llclosure; - } - } - - auto i = 0u; - for (@ast.expr e in es) { - auto mode = args.(i).mode; - - auto val; - if (ty.type_is_structural(ty.expr_ty(e))) { - auto re = trans_expr(bcx, e); - val = re.val; - bcx = re.bcx; - if (mode == ast.val) { - // 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); - } - } else if (mode == ast.alias) { - let lval_result lv; - if (ty.is_lval(e)) { - lv = trans_lval(bcx, e); - } else { - auto r = trans_expr(bcx, e); - lv = lval_val(r.bcx, r.val); - } - bcx = lv.res.bcx; - - if (lv.is_mem) { - val = lv.res.val; - } else { - // Non-mem but we're trying to alias; synthesize an - // alloca, spill to it and pass its address. - auto llty = val_ty(lv.res.val); - auto llptr = lv.res.bcx.build.Alloca(llty); - lv.res.bcx.build.Store(lv.res.val, llptr); - val = llptr; - } - - } else { - auto re = trans_expr(bcx, e); - val = re.val; - bcx = re.bcx; - } - - if (ty.type_has_dynamic_size(args.(i).ty)) { - val = bcx.build.PointerCast(val, T_typaram_ptr()); - } - - vs += val; - i += 1u; - } - - ret tup(bcx, vs, llretslot_opt); -} - fn trans_bind_thunk(@crate_ctxt cx, @ty.t incoming_fty, @ty.t outgoing_fty, @@ -2577,15 +2500,13 @@ fn trans_bind_thunk(@crate_ctxt cx, let TypeRef llthunk_ty = get_pair_fn_ty(type_of(cx, incoming_fty)); let ValueRef llthunk = decl_fastcall_fn(cx.llmod, s, llthunk_ty); - let @ty.t rty = ret_ty_of_fn_ty(incoming_fty); - // FIXME: handle ty params properly. let vec[ast.ty_param] ty_params = vec(); auto fcx = new_fn_ctxt(cx, s, llthunk); auto bcx = new_top_block_ctxt(fcx); - auto llclosure = bcx.build.PointerCast(fcx.llclosure, llclosure_ty); + auto llclosure = bcx.build.PointerCast(fcx.llenv, llclosure_ty); auto llbody = bcx.build.GEP(llclosure, vec(C_int(0), @@ -2603,7 +2524,8 @@ fn trans_bind_thunk(@crate_ctxt cx, vec(C_int(0), C_int(abi.fn_field_box))); lltargetclosure = bcx.build.Load(lltargetclosure); - let vec[ValueRef] llargs = vec(fcx.lltaskptr, + let vec[ValueRef] llargs = vec(fcx.llretptr, + fcx.lltaskptr, lltargetclosure); let uint a = 0u; let int b = 0; @@ -2635,20 +2557,7 @@ fn trans_bind_thunk(@crate_ctxt cx, C_int(abi.fn_field_code))); lltargetfn = bcx.build.Load(lltargetfn); auto r = bcx.build.FastCall(lltargetfn, llargs); - - alt (fcx.llretptr) { - case (some[ValueRef](?llptr)) { - bcx.build.Store(bcx.build.Load(r), llptr); - bcx.build.RetVoid(); - } - case (none[ValueRef]) { - if (ty.type_is_nil(rty)) { - bcx.build.RetVoid(); - } else { - bcx.build.Ret(r); - } - } - } + bcx.build.RetVoid(); ret llthunk; } @@ -2766,11 +2675,123 @@ fn trans_bind(@block_ctxt cx, @ast.expr f, } } +// NB: must keep 4 fns in sync: +// +// - type_of_fn_full +// - create_llargs_for_fn_args. +// - new_fn_ctxt +// - trans_args + +fn trans_args(@block_ctxt cx, + ValueRef llenv, + option.t[ValueRef] llobj, + option.t[generic_info] gen, + &vec[@ast.expr] es, + @ty.t fn_ty) + -> tup(@block_ctxt, vec[ValueRef], ValueRef) { + + let vec[ty.arg] args = ty.ty_fn_args(fn_ty); + let vec[ValueRef] llargs = vec(); + let vec[ValueRef] lltydescs = vec(); + let @block_ctxt bcx = cx; + + + // Arg 0: Output pointer. + auto retty = ty.ty_fn_ret(fn_ty); + auto llretslot = cx.build.Alloca(type_of(cx.fcx.ccx, retty)); + alt (gen) { + case (some[generic_info](?g)) { + lltydescs = g.tydescs; + args = ty.ty_fn_args(g.item_type); + retty = ty.ty_fn_ret(g.item_type); + } + case (_) { + } + } + if (ty.type_has_dynamic_size(retty)) { + llargs += cx.build.PointerCast(llretslot, T_typaram_ptr()); + } else { + llargs += llretslot; + } + + + // Arg 1: Task pointer. + llargs += cx.fcx.lltaskptr; + + // Arg 2: Env (closure-bindings / self-obj) + alt (llobj) { + case (some[ValueRef](?ob)) { + // Every object is always found in memory, + // and not-yet-loaded (as part of an lval x.y + // doted method-call). + llargs += cx.build.Load(ob); + } + case (_) { + llargs += llenv; + } + } + + // Args >3: ty_params ... + llargs += lltydescs; + + // ... then explicit args. + auto i = 0u; + for (@ast.expr e in es) { + auto mode = args.(i).mode; + + auto val; + if (ty.type_is_structural(ty.expr_ty(e))) { + auto re = trans_expr(bcx, e); + val = re.val; + bcx = re.bcx; + if (mode == ast.val) { + // 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); + } + } else if (mode == ast.alias) { + let lval_result lv; + if (ty.is_lval(e)) { + lv = trans_lval(bcx, e); + } else { + auto r = trans_expr(bcx, e); + lv = lval_val(r.bcx, r.val); + } + bcx = lv.res.bcx; + + if (lv.is_mem) { + val = lv.res.val; + } else { + // Non-mem but we're trying to alias; synthesize an + // alloca, spill to it and pass its address. + auto llty = val_ty(lv.res.val); + auto llptr = lv.res.bcx.build.Alloca(llty); + lv.res.bcx.build.Store(lv.res.val, llptr); + val = llptr; + } + + } else { + auto re = trans_expr(bcx, e); + val = re.val; + bcx = re.bcx; + } + + if (ty.type_has_dynamic_size(args.(i).ty)) { + val = bcx.build.PointerCast(val, T_typaram_ptr()); + } + + llargs += val; + i += 1u; + } + + ret tup(bcx, llargs, llretslot); +} + fn trans_call(@block_ctxt cx, @ast.expr f, vec[@ast.expr] args, &ast.ann ann) -> result { auto f_res = trans_lval(cx, f); auto faddr = f_res.res.val; - auto llclosure = C_null(T_opaque_closure_ptr()); + auto llenv = C_null(T_opaque_closure_ptr()); alt (f_res.llobj) { case (some[ValueRef](_)) { @@ -2785,52 +2806,34 @@ fn trans_call(@block_ctxt cx, @ast.expr f, C_int(abi.fn_field_code))); faddr = bcx.build.Load(faddr); - llclosure = bcx.build.GEP(pair, vec(C_int(0), - C_int(abi.fn_field_box))); - llclosure = bcx.build.Load(llclosure); + auto llclosure = bcx.build.GEP(pair, + vec(C_int(0), + C_int(abi.fn_field_box))); + llenv = bcx.build.Load(llclosure); } } auto fn_ty = ty.expr_ty(f); auto ret_ty = ty.ann_to_type(ann); auto args_res = trans_args(f_res.res.bcx, - llclosure, f_res.llobj, + llenv, f_res.llobj, f_res.generic, args, fn_ty); auto bcx = args_res._0; - auto real_retval = bcx.build.FastCall(faddr, args_res._1); - auto retval = real_retval; - - if (ty.type_is_nil(ret_ty)) { - retval = C_nil(); + auto llargs = args_res._1; + auto llretslot = args_res._2; + + bcx.build.FastCall(faddr, llargs); + auto retval = C_nil(); + + if (!ty.type_is_nil(ret_ty)) { + retval = load_scalar_or_boxed(bcx, llretslot, ret_ty); + // 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. + find_scope_cx(cx).cleanups += clean(bind drop_ty(_, retval, ret_ty)); } - // Check for a generic retslot. - alt (args_res._2) { - - case (some[ValueRef](?llretslot)) { - retval = load_scalar_or_boxed(bcx, llretslot, ret_ty); - } - - case (none[ValueRef]) { - if (! (ty.type_is_scalar(ret_ty) || - ty.type_is_boxed(ret_ty))) { - // Structured returns come back as first-class values. This is - // nice for LLVM but wrong for us; we treat structured values - // by pointer in most of our code here. So spill it to an - // alloca. - auto local = bcx.build.Alloca(type_of(cx.fcx.ccx, ret_ty)); - bcx.build.Store(retval, local); - retval = local; - } - } - } - - // 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. - find_scope_cx(cx).cleanups += clean(bind drop_ty(_, retval, ret_ty)); - ret res(bcx, retval); } @@ -3091,18 +3094,7 @@ fn trans_ret(@block_ctxt cx, &option.t[@ast.expr] e) -> result { auto r = trans_expr(cx, x); bcx = r.bcx; val = r.val; - - // A return is an implicit copy into a newborn anonymous - // 'return value' in the caller frame. - bcx = incr_all_refcnts(bcx, val, t).bcx; - - if (ty.type_is_structural(t)) { - // We usually treat structurals by-pointer; in particular, - // trans_expr will have given us a structure pointer. But in - // this case we're about to return. LLVM wants a first-class - // value here (which makes sense; the frame is going away!) - val = r.bcx.build.Load(val); - } + bcx = copy_ty(bcx, INIT, cx.fcx.llretptr, val, t).bcx; } case (_) { /* fall through */ } } @@ -3122,34 +3114,6 @@ fn trans_ret(@block_ctxt cx, &option.t[@ast.expr] e) -> result { } } - alt (e) { - case (some[@ast.expr](?ex)) { - auto t = ty.expr_ty(ex); - - if (ty.type_is_nil(t)) { - bcx.build.RetVoid(); - val = C_nil(); - ret res(bcx, val); // FIXME: early return needed due to - // typestate bug - } - - alt (cx.fcx.llretptr) { - case (some[ValueRef](?llptr)) { - // Generic return via tydesc + retptr. - bcx = copy_ty(bcx, INIT, llptr, val, t).bcx; - bcx.build.RetVoid(); - } - case (none[ValueRef]) { - val = bcx.build.Ret(val); - } - } - ret res(bcx, val); - } - case (_) { /* fall through */ } - } - - // FIXME: until LLVM has a unit type, we are moving around - // C_nil values rather than their void type. bcx.build.RetVoid(); ret res(bcx, C_nil()); } @@ -3360,12 +3324,20 @@ fn trans_block(@block_ctxt cx, &ast.block b) -> result { ret res(bcx, r.val); } +// NB: must keep 4 fns in sync: +// +// - type_of_fn_full +// - create_llargs_for_fn_args. +// - new_fn_ctxt +// - trans_args + fn new_fn_ctxt(@crate_ctxt cx, str name, ValueRef llfndecl) -> @fn_ctxt { - let ValueRef lltaskptr = llvm.LLVMGetParam(llfndecl, 0u); - let ValueRef llclosure = llvm.LLVMGetParam(llfndecl, 1u); + let ValueRef llretptr = llvm.LLVMGetParam(llfndecl, 0u); + let ValueRef lltaskptr = llvm.LLVMGetParam(llfndecl, 1u); + let ValueRef llenv = llvm.LLVMGetParam(llfndecl, 2u); let hashmap[ast.def_id, ValueRef] llargs = new_def_hash[ValueRef](); let hashmap[ast.def_id, ValueRef] llobjfields = new_def_hash[ValueRef](); @@ -3374,9 +3346,9 @@ fn new_fn_ctxt(@crate_ctxt cx, ret @rec(llfn=llfndecl, lltaskptr=lltaskptr, - llclosure=llclosure, + llenv=llenv, + llretptr=llretptr, mutable llself=none[ValueRef], - mutable llretptr=none[ValueRef], llargs=llargs, llobjfields=llobjfields, lllocals=lllocals, @@ -3384,13 +3356,28 @@ fn new_fn_ctxt(@crate_ctxt cx, ccx=cx); } -// NB: this must match trans_args and type_of_fn_full. +// NB: must keep 4 fns in sync: +// +// - type_of_fn_full +// - create_llargs_for_fn_args. +// - new_fn_ctxt +// - trans_args + fn create_llargs_for_fn_args(&@fn_ctxt cx, option.t[TypeRef] ty_self, @ty.t ret_ty, &vec[ast.arg] args, &vec[ast.ty_param] ty_params) { - let uint arg_n = 1u; + + alt (ty_self) { + case (some[TypeRef](_)) { + cx.llself = some[ValueRef](cx.llenv); + } + case (_) { + } + } + + auto arg_n = 3u; for (ast.ty_param tp in ty_params) { auto llarg = llvm.LLVMGetParam(cx.llfn, arg_n); @@ -3399,23 +3386,6 @@ fn create_llargs_for_fn_args(&@fn_ctxt cx, arg_n += 1u; } - if (ty.type_has_dynamic_size(ret_ty)) { - cx.llretptr = some[ValueRef](llvm.LLVMGetParam(cx.llfn, arg_n)); - arg_n += 1u; - } - - alt (ty_self) { - case (some[TypeRef](_)) { - auto llself = llvm.LLVMGetParam(cx.llfn, arg_n); - check (llself as int != 0); - cx.llself = some[ValueRef](llself); - arg_n += 1u; - } - case (_) { - // llclosure, we don't know what it is. - arg_n += 1u; - } - } for (ast.arg arg in args) { auto llarg = llvm.LLVMGetParam(cx.llfn, arg_n); @@ -3645,7 +3615,7 @@ fn trans_obj(@crate_ctxt cx, &ast._obj ob, ast.def_id oid, copy_args_to_allocas(bcx, none[TypeRef], fn_args, arg_tys); auto llself_ty = type_of(cx, ret_ty_of_fn(ann)); - auto pair = bcx.build.Alloca(llself_ty); + auto pair = bcx.fcx.llretptr; auto vtbl = trans_vtbl(cx, llself_ty, ob, ty_params); auto pair_vtbl = bcx.build.GEP(pair, vec(C_int(0), @@ -3740,7 +3710,7 @@ fn trans_obj(@crate_ctxt cx, &ast._obj ob, ast.def_id oid, auto p = bcx.build.PointerCast(box.val, llbox_ty); bcx.build.Store(p, pair_box); } - bcx.build.Ret(bcx.build.Load(pair)); + bcx.build.RetVoid(); } fn trans_tag_variant(@crate_ctxt cx, ast.def_id tag_id, @@ -3779,11 +3749,12 @@ fn trans_tag_variant(@crate_ctxt cx, ast.def_id tag_id, // FIXME: better name. llvm.LLVMAddTypeName(cx.llmod, _str.buf("tag"), lltagty); - auto lltagptr = bcx.build.Alloca(lltagty); - auto lldiscrimptr = bcx.build.GEP(lltagptr, vec(C_int(0), C_int(0))); + auto lldiscrimptr = bcx.build.GEP(fcx.llretptr, + vec(C_int(0), C_int(0))); bcx.build.Store(C_int(index), lldiscrimptr); - auto llblobptr = bcx.build.GEP(lltagptr, vec(C_int(0), C_int(1))); + auto llblobptr = bcx.build.GEP(fcx.llretptr, + vec(C_int(0), C_int(1))); // First, generate the union type. let vec[TypeRef] llargtys = vec(); @@ -3804,9 +3775,8 @@ fn trans_tag_variant(@crate_ctxt cx, ast.def_id tag_id, i += 1u; } - auto lltagval = bcx.build.Load(lltagptr); bcx = trans_block_cleanups(bcx, find_scope_cx(bcx)); - bcx.build.Ret(lltagval); + bcx.build.RetVoid(); } // FIXME: this should do some structural hash-consing to avoid @@ -4142,9 +4112,9 @@ fn trans_exit_task_glue(@crate_ctxt cx) { let ValueRef lltaskptr = llvm.LLVMGetParam(llfn, 0u); auto fcx = @rec(llfn=llfn, lltaskptr=lltaskptr, - llclosure=C_null(T_opaque_closure_ptr()), + llenv=C_null(T_opaque_closure_ptr()), + llretptr=C_null(T_ptr(T_nil())), mutable llself=none[ValueRef], - mutable llretptr=none[ValueRef], llargs=new_def_hash[ValueRef](), llobjfields=new_def_hash[ValueRef](), lllocals=new_def_hash[ValueRef](), -- cgit v1.2.3 From 2f25d9c983c5730d79cc14278e666b8eb6531b10 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Tue, 8 Feb 2011 17:05:53 -0800 Subject: Handle subtle view-shift on outptr in generic calls. Can construct generic objs now. --- src/comp/middle/trans.rs | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 9e59cf57..4401f885 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -2710,6 +2710,14 @@ fn trans_args(@block_ctxt cx, } if (ty.type_has_dynamic_size(retty)) { llargs += cx.build.PointerCast(llretslot, T_typaram_ptr()); + } else if (ty.count_ty_params(retty) != 0u) { + // It's possible that the callee has some generic-ness somewhere in + // its return value -- say a method signature within an obj or a fn + // type deep in a structure -- which the caller has a concrete view + // of. If so, cast the caller's view of the restlot to the callee's + // view, for the sake of making a type-compatible call. + llargs += cx.build.PointerCast(llretslot, + T_ptr(type_of(cx.fcx.ccx, retty))); } else { llargs += llretslot; } -- cgit v1.2.3 From 8c0d35066bcc0ab0eb35818f4de63bccee097e5c Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Wed, 9 Feb 2011 09:54:58 -0800 Subject: Elide passed-typarams when tydescs are captured. Un-XFAIL generic-obj.rs. --- src/comp/middle/trans.rs | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 4401f885..2a9c32da 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -399,13 +399,15 @@ fn type_of_fn_full(@crate_ctxt cx, } } - // Args >3: ty params ... - auto ty_param_count = - ty.count_ty_params(plain_ty(ty.ty_fn(inputs, output))); - auto i = 0u; - while (i < ty_param_count) { - atys += T_ptr(T_tydesc()); - i += 1u; + // Args >3: ty params, if not acquired via capture... + if (obj_self == none[TypeRef]) { + auto ty_param_count = + ty.count_ty_params(plain_ty(ty.ty_fn(inputs, output))); + auto i = 0u; + while (i < ty_param_count) { + atys += T_ptr(T_tydesc()); + i += 1u; + } } // ... then explicit args. @@ -3387,11 +3389,13 @@ fn create_llargs_for_fn_args(&@fn_ctxt cx, auto arg_n = 3u; - for (ast.ty_param tp in ty_params) { - auto llarg = llvm.LLVMGetParam(cx.llfn, arg_n); - check (llarg as int != 0); - cx.lltydescs.insert(tp.id, llarg); - arg_n += 1u; + if (ty_self == none[TypeRef]) { + for (ast.ty_param tp in ty_params) { + auto llarg = llvm.LLVMGetParam(cx.llfn, arg_n); + check (llarg as int != 0); + cx.lltydescs.insert(tp.id, llarg); + arg_n += 1u; + } } -- cgit v1.2.3 From 378c0087ca7572cd17726c704fe04d57bf4687af Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Sun, 30 Jan 2011 17:18:19 -0500 Subject: Parse 'be' statement. Pass tailcall tests. No actual tailcalls yet. --- src/comp/middle/trans.rs | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 2a9c32da..499ab027 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -3128,6 +3128,11 @@ fn trans_ret(@block_ctxt cx, &option.t[@ast.expr] e) -> result { ret res(bcx, C_nil()); } +fn trans_be(@block_ctxt cx, @ast.expr e) -> result { + // FIXME: So this isn't actually a tail call + ret trans_ret(cx, some(e)); +} + fn init_local(@block_ctxt cx, @ast.local local) -> result { // Make a note to drop this slot on the way out. @@ -3178,6 +3183,10 @@ fn trans_stmt(@block_ctxt cx, &ast.stmt s) -> result { bcx = trans_ret(cx, e).bcx; } + case (ast.stmt_be(?e)) { + bcx = trans_be(cx, e).bcx; + } + case (ast.stmt_expr(?e)) { bcx = trans_expr(cx, e).bcx; } -- cgit v1.2.3 From f17a3421e01399bcc1a6f8540273d7b4440397a1 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Wed, 9 Feb 2011 22:36:37 -0500 Subject: Cleanup for 'be' statement and comments about future typestate --- src/comp/middle/trans.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 499ab027..45d54e6a 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -3129,7 +3129,10 @@ fn trans_ret(@block_ctxt cx, &option.t[@ast.expr] e) -> result { } fn trans_be(@block_ctxt cx, @ast.expr e) -> result { - // FIXME: So this isn't actually a tail call + // FIXME: This should be a typestate precondition + check ast.is_call_expr(e); + // FIXME: Turn this into a real tail call once + // calling convention issues are settled ret trans_ret(cx, some(e)); } -- cgit v1.2.3 From 140d6fd96468c51746d0d44bd6a9c4fdb6de30a9 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 10 Feb 2011 14:59:20 -0800 Subject: Switch "." to "_" in name mangling, makes gdb happier. Also factor out into sep() helper. --- src/comp/middle/trans.rs | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 45d54e6a..dbcdaed1 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -121,6 +121,10 @@ tag block_parent { state type result = rec(mutable @block_ctxt bcx, mutable ValueRef val); +fn sep() -> str { + ret "_"; +} + fn res(@block_ctxt bcx, ValueRef val) -> result { ret rec(mutable bcx = bcx, mutable val = val); @@ -1104,7 +1108,7 @@ fn make_generic_glue(@crate_ctxt cx, @ty.t t, str name, vec[ast.def_id] typaram_defs) -> ValueRef { auto llfnty = T_glue_fn(); - auto fn_name = cx.names.next("_rust_" + name) + "." + ty.ty_to_str(t); + auto fn_name = cx.names.next("_rust_" + name) + sep() + ty.ty_to_str(t); fn_name = sanitize(fn_name); auto llfn = decl_fastcall_fn(cx.llmod, fn_name, llfnty); @@ -2498,7 +2502,7 @@ fn trans_bind_thunk(@crate_ctxt cx, // Construct a thunk-call with signature incoming_fty, and that copies // args forward into a call to outgoing_fty. - let str s = cx.names.next("_rust_thunk") + "." + cx.path; + let str s = cx.names.next("_rust_thunk") + sep() + cx.path; let TypeRef llthunk_ty = get_pair_fn_ty(type_of(cx, incoming_fty)); let ValueRef llthunk = decl_fastcall_fn(cx.llmod, s, llthunk_ty); @@ -3592,10 +3596,10 @@ fn trans_vtbl(@crate_ctxt cx, TypeRef self_ty, } } - let @crate_ctxt mcx = @rec(path=cx.path + "." + m.node.ident + let @crate_ctxt mcx = @rec(path=cx.path + sep() + m.node.ident with *cx); - let str s = cx.names.next("_rust_method") + "." + mcx.path; + let str s = cx.names.next("_rust_method") + sep() + mcx.path; let ValueRef llfn = decl_fastcall_fn(cx.llmod, s, llfnty); cx.item_ids.insert(m.node.id, llfn); @@ -3606,7 +3610,7 @@ fn trans_vtbl(@crate_ctxt cx, TypeRef self_ty, auto vtbl = C_struct(methods); auto gvar = llvm.LLVMAddGlobal(cx.llmod, val_ty(vtbl), - _str.buf("_rust_vtbl" + "." + cx.path)); + _str.buf("_rust_vtbl" + sep() + cx.path)); llvm.LLVMSetInitializer(gvar, vtbl); llvm.LLVMSetGlobalConstant(gvar, True); llvm.LLVMSetLinkage(gvar, lib.llvm.LLVMPrivateLinkage @@ -3837,21 +3841,21 @@ fn trans_const(@crate_ctxt cx, @ast.expr e, fn trans_item(@crate_ctxt cx, &ast.item item) { alt (item.node) { case (ast.item_fn(?name, ?f, ?tps, ?fid, ?ann)) { - auto sub_cx = @rec(path=cx.path + "." + name with *cx); + auto sub_cx = @rec(path=cx.path + sep() + name with *cx); trans_fn(sub_cx, f, fid, none[TypeRef], tps, ann); } case (ast.item_obj(?name, ?ob, ?tps, ?oid, ?ann)) { - auto sub_cx = @rec(path=cx.path + "." + name, + auto sub_cx = @rec(path=cx.path + sep() + name, obj_typarams=tps, obj_fields=ob.fields with *cx); trans_obj(sub_cx, ob, oid, tps, ann); } case (ast.item_mod(?name, ?m, _)) { - auto sub_cx = @rec(path=cx.path + "." + name with *cx); + auto sub_cx = @rec(path=cx.path + sep() + name with *cx); trans_mod(sub_cx, m); } case (ast.item_tag(?name, ?variants, ?tps, ?tag_id)) { - auto sub_cx = @rec(path=cx.path + "." + name with *cx); + auto sub_cx = @rec(path=cx.path + sep() + name with *cx); auto i = 0; for (ast.variant variant in variants) { trans_tag_variant(sub_cx, tag_id, variant, i, tps); @@ -3859,7 +3863,7 @@ fn trans_item(@crate_ctxt cx, &ast.item item) { } } case (ast.item_const(?name, _, ?expr, ?cid, ?ann)) { - auto sub_cx = @rec(path=cx.path + "." + name with *cx); + auto sub_cx = @rec(path=cx.path + sep() + name with *cx); trans_const(sub_cx, expr, cid, ann); } case (_) { /* fall through */ } @@ -3890,11 +3894,11 @@ fn decl_fn_and_pair(@crate_ctxt cx, auto llfty = get_pair_fn_ty(llpairty); // Declare the function itself. - let str s = cx.names.next("_rust_" + kind) + "." + name; + let str s = cx.names.next("_rust_" + kind) + sep() + name; let ValueRef llfn = decl_fastcall_fn(cx.llmod, s, llfty); // Declare the global constant pair that points to it. - let str ps = cx.names.next("_rust_" + kind + "_pair") + "." + name; + let str ps = cx.names.next("_rust_" + kind + "_pair") + sep() + name; let ValueRef gvar = llvm.LLVMAddGlobal(cx.llmod, llpairty, _str.buf(ps)); auto pair = C_struct(vec(llfn, @@ -4208,8 +4212,8 @@ fn trans_main_fn(@crate_ctxt cx, ValueRef llcrate) { auto llargc = llvm.LLVMGetParam(llmain, 0u); auto llargv = llvm.LLVMGetParam(llmain, 1u); - check (cx.item_names.contains_key("_rust.main")); - auto llrust_main = cx.item_names.get("_rust.main"); + check (cx.item_names.contains_key("_rust" + sep() + "main")); + auto llrust_main = cx.item_names.get("_rust" + sep() + "main"); // // Emit the moral equivalent of: -- cgit v1.2.3 From c958eebf5d17f5fd52805ed08e4a7efc6c3caf21 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 10 Feb 2011 15:00:16 -0800 Subject: Change more of trans to rely on tydescs when dealing with generics. --- src/comp/middle/trans.rs | 103 ++++++++++++++++++++++++++++++----------------- 1 file changed, 66 insertions(+), 37 deletions(-) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index dbcdaed1..6399b900 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -2704,7 +2704,10 @@ fn trans_args(@block_ctxt cx, // Arg 0: Output pointer. auto retty = ty.ty_fn_ret(fn_ty); - auto llretslot = cx.build.Alloca(type_of(cx.fcx.ccx, retty)); + auto llretslot_res = alloc_ty(bcx, retty); + bcx = llretslot_res.bcx; + auto llretslot = llretslot_res.val; + alt (gen) { case (some[generic_info](?g)) { lltydescs = g.tydescs; @@ -2715,7 +2718,7 @@ fn trans_args(@block_ctxt cx, } } if (ty.type_has_dynamic_size(retty)) { - llargs += cx.build.PointerCast(llretslot, T_typaram_ptr()); + llargs += bcx.build.PointerCast(llretslot, T_typaram_ptr()); } else if (ty.count_ty_params(retty) != 0u) { // It's possible that the callee has some generic-ness somewhere in // its return value -- say a method signature within an obj or a fn @@ -2723,14 +2726,14 @@ fn trans_args(@block_ctxt cx, // of. If so, cast the caller's view of the restlot to the callee's // view, for the sake of making a type-compatible call. llargs += cx.build.PointerCast(llretslot, - T_ptr(type_of(cx.fcx.ccx, retty))); + T_ptr(type_of(bcx.fcx.ccx, retty))); } else { llargs += llretslot; } // Arg 1: Task pointer. - llargs += cx.fcx.lltaskptr; + llargs += bcx.fcx.lltaskptr; // Arg 2: Env (closure-bindings / self-obj) alt (llobj) { @@ -2738,7 +2741,7 @@ fn trans_args(@block_ctxt cx, // Every object is always found in memory, // and not-yet-loaded (as part of an lval x.y // doted method-call). - llargs += cx.build.Load(ob); + llargs += bcx.build.Load(ob); } case (_) { llargs += llenv; @@ -2848,25 +2851,32 @@ fn trans_call(@block_ctxt cx, @ast.expr f, find_scope_cx(cx).cleanups += clean(bind drop_ty(_, retval, ret_ty)); } + // log "call-result type: " + val_str(retval); ret res(bcx, retval); } fn trans_tup(@block_ctxt cx, vec[ast.elt] elts, &ast.ann ann) -> result { - auto t = node_ann_type(cx.fcx.ccx, ann); - auto llty = type_of(cx.fcx.ccx, t); - auto tup_val = cx.build.Alloca(llty); + auto bcx = cx; + auto t = node_ann_type(bcx.fcx.ccx, ann); + auto llty = type_of(bcx.fcx.ccx, t); + auto tup_res = alloc_ty(bcx, t); + auto tup_val = tup_res.val; + bcx = tup_res.bcx; + find_scope_cx(cx).cleanups += clean(bind drop_ty(_, tup_val, t)); let int i = 0; - auto r = res(cx, C_nil()); + for (ast.elt e in elts) { - auto t = ty.expr_ty(e.expr); - auto src_res = trans_expr(r.bcx, e.expr); - auto dst_elt = r.bcx.build.GEP(tup_val, vec(C_int(0), C_int(i))); - r = copy_ty(src_res.bcx, INIT, dst_elt, src_res.val, t); + auto e_ty = ty.expr_ty(e.expr); + auto src_res = trans_expr(bcx, e.expr); + bcx = src_res.bcx; + auto dst_res = GEP_tup_like(bcx, t, tup_val, vec(0, i)); + bcx = dst_res.bcx; + bcx = copy_ty(src_res.bcx, INIT, dst_res.val, src_res.val, e_ty).bcx; i += 1; } - ret res(r.bcx, tup_val); + ret res(bcx, tup_val); } fn trans_vec(@block_ctxt cx, vec[@ast.expr] args, @@ -2891,44 +2901,58 @@ fn trans_vec(@block_ctxt cx, vec[@ast.expr] args, // FIXME: pass tydesc properly. auto sub = trans_upcall(bcx, "upcall_new_vec", vec(data_sz, C_int(0))); + bcx = sub.bcx; auto llty = type_of(bcx.fcx.ccx, t); - auto vec_val = sub.bcx.build.IntToPtr(sub.val, llty); + auto vec_val = bcx.build.IntToPtr(sub.val, llty); find_scope_cx(bcx).cleanups += clean(bind drop_ty(_, vec_val, t)); - auto body = sub.bcx.build.GEP(vec_val, vec(C_int(0), - C_int(abi.vec_elt_data))); + auto body = bcx.build.GEP(vec_val, vec(C_int(0), + C_int(abi.vec_elt_data))); + + auto pseudo_tup_ty = + plain_ty(ty.ty_tup(_vec.init_elt[@ty.t](unit_ty, + _vec.len[@ast.expr](args)))); let int i = 0; + for (@ast.expr e in args) { - auto src_res = trans_expr(sub.bcx, e); - auto dst_elt = sub.bcx.build.GEP(body, vec(C_int(0), C_int(i))); - sub = copy_ty(src_res.bcx, INIT, dst_elt, src_res.val, unit_ty); + auto src_res = trans_expr(bcx, e); + bcx = src_res.bcx; + auto dst_res = GEP_tup_like(bcx, pseudo_tup_ty, body, vec(0, i)); + bcx = dst_res.bcx; + bcx = copy_ty(bcx, INIT, dst_res.val, src_res.val, unit_ty).bcx; i += 1; } - auto fill = sub.bcx.build.GEP(vec_val, - vec(C_int(0), C_int(abi.vec_elt_fill))); - sub.bcx.build.Store(data_sz, fill); + auto fill = bcx.build.GEP(vec_val, + vec(C_int(0), C_int(abi.vec_elt_fill))); + bcx.build.Store(data_sz, fill); - ret res(sub.bcx, vec_val); + ret res(bcx, vec_val); } fn trans_rec(@block_ctxt cx, vec[ast.field] fields, &ast.ann ann) -> result { - auto t = node_ann_type(cx.fcx.ccx, ann); - auto llty = type_of(cx.fcx.ccx, t); - auto rec_val = cx.build.Alloca(llty); + + auto bcx = cx; + auto t = node_ann_type(bcx.fcx.ccx, ann); + auto llty = type_of(bcx.fcx.ccx, t); + auto rec_res = alloc_ty(bcx, t); + auto rec_val = rec_res.val; + bcx = rec_res.bcx; + find_scope_cx(cx).cleanups += clean(bind drop_ty(_, rec_val, t)); let int i = 0; - auto r = res(cx, C_nil()); + for (ast.field f in fields) { - auto t = ty.expr_ty(f.expr); - auto src_res = trans_expr(r.bcx, f.expr); - auto dst_elt = r.bcx.build.GEP(rec_val, vec(C_int(0), C_int(i))); - // FIXME: calculate copy init-ness in typestate. - r = copy_ty(src_res.bcx, INIT, dst_elt, src_res.val, t); + auto e_ty = ty.expr_ty(f.expr); + auto src_res = trans_expr(bcx, f.expr); + bcx = src_res.bcx; + auto dst_res = GEP_tup_like(bcx, t, rec_val, vec(0, i)); + bcx = dst_res.bcx; + bcx = copy_ty(src_res.bcx, INIT, dst_res.val, src_res.val, e_ty).bcx; i += 1; } - ret res(r.bcx, rec_val); + ret res(bcx, rec_val); } @@ -3300,8 +3324,7 @@ iter block_locals(&ast.block b) -> @ast.local { } } -fn alloc_local(@block_ctxt cx, @ast.local local) -> result { - auto t = node_ann_type(cx.fcx.ccx, local.ann); +fn alloc_ty(@block_ctxt cx, @ty.t t) -> result { auto val = C_int(0); auto bcx = cx; if (ty.type_has_dynamic_size(t)) { @@ -3311,10 +3334,16 @@ fn alloc_local(@block_ctxt cx, @ast.local local) -> result { } else { val = bcx.build.Alloca(type_of(cx.fcx.ccx, t)); } - bcx.fcx.lllocals.insert(local.id, val); ret res(bcx, val); } +fn alloc_local(@block_ctxt cx, @ast.local local) -> result { + auto t = node_ann_type(cx.fcx.ccx, local.ann); + auto r = alloc_ty(cx, t); + r.bcx.fcx.lllocals.insert(local.id, r.val); + ret r; +} + fn trans_block(@block_ctxt cx, &ast.block b) -> result { auto bcx = cx; -- cgit v1.2.3 From 7c25fb5628c398b79b9293b6b31d62936dcba613 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 10 Feb 2011 17:33:08 -0800 Subject: Fix bug in trans_field, un-XFAIL two more tests. --- src/comp/middle/trans.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 6399b900..4135a6e5 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -2376,10 +2376,8 @@ fn trans_path(@block_ctxt cx, &ast.path p, &option.t[ast.def] dopt, fn trans_field(@block_ctxt cx, &ast.span sp, @ast.expr base, &ast.ident field, &ast.ann ann) -> lval_result { - auto lv = trans_lval(cx, base); - auto r = lv.res; + auto r = trans_expr(cx, base); r = autoderef(r.bcx, r.val, ty.expr_ty(base)); - check (lv.is_mem); auto t = ty.expr_ty(base); alt (t.struct) { case (ty.ty_tup(?fields)) { -- cgit v1.2.3 From 7446af747d83622c849ec9f29c0365aa7bf4e697 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 10 Feb 2011 19:40:02 -0800 Subject: Translate pat_lit, un-XFAIL alt-pattern-lit.rs for rustc. --- src/comp/middle/trans.rs | 42 ++++++++++++++++++++++++++++++------------ 1 file changed, 30 insertions(+), 12 deletions(-) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 4135a6e5..bedfad97 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -1838,6 +1838,24 @@ fn trans_unary(@block_ctxt cx, ast.unop op, fail; } +// FIXME: implement proper structural comparison. + +fn trans_compare(@block_ctxt cx, ast.binop op, + ValueRef lhs, ValueRef rhs) -> ValueRef { + auto cmp = lib.llvm.LLVMIntEQ; + alt (op) { + case (ast.eq) { cmp = lib.llvm.LLVMIntEQ; } + case (ast.ne) { cmp = lib.llvm.LLVMIntNE; } + + // FIXME (issue #57): switch by signedness. + case (ast.lt) { cmp = lib.llvm.LLVMIntSLT; } + case (ast.le) { cmp = lib.llvm.LLVMIntSLE; } + case (ast.ge) { cmp = lib.llvm.LLVMIntSGE; } + case (ast.gt) { cmp = lib.llvm.LLVMIntSGT; } + } + ret cx.build.ICmp(cmp, lhs, rhs); +} + fn trans_eager_binop(@block_ctxt cx, ast.binop op, ValueRef lhs, ValueRef rhs) -> ValueRef { @@ -1857,18 +1875,7 @@ fn trans_eager_binop(@block_ctxt cx, ast.binop op, case (ast.lsr) { ret cx.build.LShr(lhs, rhs); } case (ast.asr) { ret cx.build.AShr(lhs, rhs); } case (_) { - auto cmp = lib.llvm.LLVMIntEQ; - alt (op) { - case (ast.eq) { cmp = lib.llvm.LLVMIntEQ; } - case (ast.ne) { cmp = lib.llvm.LLVMIntNE; } - - // FIXME (issue #57): switch by signedness. - case (ast.lt) { cmp = lib.llvm.LLVMIntSLT; } - case (ast.le) { cmp = lib.llvm.LLVMIntSLE; } - case (ast.ge) { cmp = lib.llvm.LLVMIntSGE; } - case (ast.gt) { cmp = lib.llvm.LLVMIntSGT; } - } - ret cx.build.ICmp(cmp, lhs, rhs); + ret trans_compare(cx, op, lhs, rhs); } } fail; @@ -2132,6 +2139,16 @@ fn trans_pat_match(@block_ctxt cx, @ast.pat pat, ValueRef llval, alt (pat.node) { case (ast.pat_wild(_)) { ret res(cx, llval); } case (ast.pat_bind(_, _, _)) { ret res(cx, llval); } + + case (ast.pat_lit(?lt, ?ann)) { + auto lllit = trans_lit(cx.fcx.ccx, *lt, ann); + auto lleq = trans_compare(cx, ast.eq, llval, lllit); + + auto matched_cx = new_sub_block_ctxt(cx, "matched_cx"); + cx.build.CondBr(lleq, matched_cx.llbb, next_cx.llbb); + ret res(matched_cx, llval); + } + case (ast.pat_tag(?id, ?subpats, ?vdef_opt, ?ann)) { auto lltagptr = cx.build.GEP(llval, vec(C_int(0), C_int(0))); auto lltag = cx.build.Load(lltagptr); @@ -2184,6 +2201,7 @@ fn trans_pat_binding(@block_ctxt cx, @ast.pat pat, ValueRef llval) -> result { alt (pat.node) { case (ast.pat_wild(_)) { ret res(cx, llval); } + case (ast.pat_lit(_, _)) { ret res(cx, llval); } case (ast.pat_bind(?id, ?def_id, ?ann)) { auto ty = node_ann_type(cx.fcx.ccx, ann); auto llty = type_of(cx.fcx.ccx, ty); -- cgit v1.2.3 From 0ebfb8227c190609e80af3fb52b9813c4b282cc0 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Sun, 13 Feb 2011 00:49:04 -0500 Subject: Add support for unsigned binops. Closes #57 --- src/comp/middle/trans.rs | 70 +++++++++++++++++++++++++++++++++++++----------- 1 file changed, 54 insertions(+), 16 deletions(-) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index bedfad97..c1a4aa6f 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -1840,33 +1840,67 @@ fn trans_unary(@block_ctxt cx, ast.unop op, // FIXME: implement proper structural comparison. -fn trans_compare(@block_ctxt cx, ast.binop op, +fn trans_compare(@block_ctxt cx, ast.binop op, @ty.t intype, ValueRef lhs, ValueRef rhs) -> ValueRef { auto cmp = lib.llvm.LLVMIntEQ; alt (op) { case (ast.eq) { cmp = lib.llvm.LLVMIntEQ; } case (ast.ne) { cmp = lib.llvm.LLVMIntNE; } - // FIXME (issue #57): switch by signedness. - case (ast.lt) { cmp = lib.llvm.LLVMIntSLT; } - case (ast.le) { cmp = lib.llvm.LLVMIntSLE; } - case (ast.ge) { cmp = lib.llvm.LLVMIntSGE; } - case (ast.gt) { cmp = lib.llvm.LLVMIntSGT; } + case (ast.lt) { + if (ty.type_is_signed(intype)) { + cmp = lib.llvm.LLVMIntSLT; + } else { + cmp = lib.llvm.LLVMIntULT; + } + } + case (ast.le) { + if (ty.type_is_signed(intype)) { + cmp = lib.llvm.LLVMIntSLE; + } else { + cmp = lib.llvm.LLVMIntULE; + } + } + case (ast.gt) { + if (ty.type_is_signed(intype)) { + cmp = lib.llvm.LLVMIntSGT; + } else { + cmp = lib.llvm.LLVMIntUGT; + } + } + case (ast.ge) { + if (ty.type_is_signed(intype)) { + cmp = lib.llvm.LLVMIntSGE; + } else { + cmp = lib.llvm.LLVMIntUGE; + } + } } ret cx.build.ICmp(cmp, lhs, rhs); } -fn trans_eager_binop(@block_ctxt cx, ast.binop op, +fn trans_eager_binop(@block_ctxt cx, ast.binop op, @ty.t intype, ValueRef lhs, ValueRef rhs) -> ValueRef { alt (op) { case (ast.add) { ret cx.build.Add(lhs, rhs); } case (ast.sub) { ret cx.build.Sub(lhs, rhs); } - // FIXME (issue #57): switch by signedness. case (ast.mul) { ret cx.build.Mul(lhs, rhs); } - case (ast.div) { ret cx.build.SDiv(lhs, rhs); } - case (ast.rem) { ret cx.build.SRem(lhs, rhs); } + case (ast.div) { + if (ty.type_is_signed(intype)) { + ret cx.build.SDiv(lhs, rhs); + } else { + ret cx.build.UDiv(lhs, rhs); + } + } + case (ast.rem) { + if (ty.type_is_signed(intype)) { + ret cx.build.SRem(lhs, rhs); + } else { + ret cx.build.URem(lhs, rhs); + } + } case (ast.bitor) { ret cx.build.Or(lhs, rhs); } case (ast.bitand) { ret cx.build.And(lhs, rhs); } @@ -1875,7 +1909,7 @@ fn trans_eager_binop(@block_ctxt cx, ast.binop op, case (ast.lsr) { ret cx.build.LShr(lhs, rhs); } case (ast.asr) { ret cx.build.AShr(lhs, rhs); } case (_) { - ret trans_compare(cx, op, lhs, rhs); + ret trans_compare(cx, op, intype, lhs, rhs); } } fail; @@ -1950,10 +1984,12 @@ fn trans_binary(@block_ctxt cx, ast.binop op, case (_) { // Remaining cases are eager: auto lhs = trans_expr(cx, a); - lhs = autoderef(lhs.bcx, lhs.val, ty.expr_ty(a)); + auto lhty = ty.expr_ty(a); + lhs = autoderef(lhs.bcx, lhs.val, lhty); auto rhs = trans_expr(lhs.bcx, b); - rhs = autoderef(rhs.bcx, rhs.val, ty.expr_ty(b)); - ret res(rhs.bcx, trans_eager_binop(rhs.bcx, op, + auto rhty = ty.expr_ty(b); + rhs = autoderef(rhs.bcx, rhs.val, rhty); + ret res(rhs.bcx, trans_eager_binop(rhs.bcx, op, lhty, lhs.val, rhs.val)); } } @@ -2142,7 +2178,8 @@ fn trans_pat_match(@block_ctxt cx, @ast.pat pat, ValueRef llval, case (ast.pat_lit(?lt, ?ann)) { auto lllit = trans_lit(cx.fcx.ccx, *lt, ann); - auto lleq = trans_compare(cx, ast.eq, llval, lllit); + auto lltype = ty.ann_to_type(ann); + auto lleq = trans_compare(cx, ast.eq, lltype, llval, lllit); auto matched_cx = new_sub_block_ctxt(cx, "matched_cx"); cx.build.CondBr(lleq, matched_cx.llbb, next_cx.llbb); @@ -3035,7 +3072,8 @@ fn trans_expr(@block_ctxt cx, @ast.expr e) -> result { auto lhs_val = load_scalar_or_boxed(lhs_res.res.bcx, lhs_res.res.val, t); auto rhs_res = trans_expr(lhs_res.res.bcx, src); - auto v = trans_eager_binop(rhs_res.bcx, op, lhs_val, rhs_res.val); + auto v = trans_eager_binop(rhs_res.bcx, op, t, + lhs_val, rhs_res.val); // FIXME: calculate copy init-ness in typestate. ret copy_ty(rhs_res.bcx, DROP_EXISTING, lhs_res.res.val, v, t); -- cgit v1.2.3 From 59bce06a967b3806c3d874b8956857f0f01287e1 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Mon, 14 Feb 2011 15:52:38 -0800 Subject: Expand expr_rec to take its optional trailing 'with' parameter. --- src/comp/middle/trans.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index c1a4aa6f..972683e9 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -2984,7 +2984,10 @@ fn trans_vec(@block_ctxt cx, vec[@ast.expr] args, } fn trans_rec(@block_ctxt cx, vec[ast.field] fields, - &ast.ann ann) -> result { + option.t[@ast.expr] base, &ast.ann ann) -> result { + + // FIXME: handle presence of a nonempty base. + check (base == none[@ast.expr]); auto bcx = cx; auto t = node_ann_type(bcx.fcx.ccx, ann); @@ -3099,8 +3102,8 @@ fn trans_expr(@block_ctxt cx, @ast.expr e) -> result { ret trans_tup(cx, args, ann); } - case (ast.expr_rec(?args, ?ann)) { - ret trans_rec(cx, args, ann); + case (ast.expr_rec(?args, ?base, ?ann)) { + ret trans_rec(cx, args, base, ann); } // lval cases fall through to trans_lval and then -- cgit v1.2.3 From 84dd64b6cf047444e03b94e63e00508ecc4046aa Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Mon, 14 Feb 2011 16:33:51 -0800 Subject: Switch ast.is_call_expr check in trans to non-typestate form. --- src/comp/middle/trans.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 972683e9..1bf278a7 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -3215,7 +3215,7 @@ fn trans_ret(@block_ctxt cx, &option.t[@ast.expr] e) -> result { fn trans_be(@block_ctxt cx, @ast.expr e) -> result { // FIXME: This should be a typestate precondition - check ast.is_call_expr(e); + check (ast.is_call_expr(e)); // FIXME: Turn this into a real tail call once // calling convention issues are settled ret trans_ret(cx, some(e)); -- cgit v1.2.3 From f1f33abdeba156523d6db1752bbff75dc4088724 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Mon, 14 Feb 2011 17:46:28 -0800 Subject: Move all non-decl/non-expr stmts to exprs. --- src/comp/middle/trans.rs | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 1bf278a7..e140ddcc 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -3106,6 +3106,26 @@ fn trans_expr(@block_ctxt cx, @ast.expr e) -> result { ret trans_rec(cx, args, base, ann); } + case (ast.expr_fail) { + ret trans_fail(cx, e.span, "explicit failure"); + } + + case (ast.expr_log(?a)) { + ret trans_log(cx, a); + } + + case (ast.expr_check_expr(?a)) { + ret trans_check_expr(cx, a); + } + + case (ast.expr_ret(?e)) { + ret trans_ret(cx, e); + } + + case (ast.expr_be(?e)) { + ret trans_be(cx, e); + } + // lval cases fall through to trans_lval and then // possibly load the result (if it's non-structural). @@ -3255,26 +3275,6 @@ fn init_local(@block_ctxt cx, @ast.local local) -> result { fn trans_stmt(@block_ctxt cx, &ast.stmt s) -> result { auto bcx = cx; alt (s.node) { - case (ast.stmt_log(?a)) { - bcx = trans_log(cx, a).bcx; - } - - case (ast.stmt_check_expr(?a)) { - bcx = trans_check_expr(cx, a).bcx; - } - - case (ast.stmt_fail) { - bcx = trans_fail(cx, s.span, "explicit failure").bcx; - } - - case (ast.stmt_ret(?e)) { - bcx = trans_ret(cx, e).bcx; - } - - case (ast.stmt_be(?e)) { - bcx = trans_be(cx, e).bcx; - } - case (ast.stmt_expr(?e)) { bcx = trans_expr(cx, e).bcx; } -- cgit v1.2.3 From 15a01f5c3691a152793d8933a7be9d16a0fc7030 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Mon, 14 Feb 2011 17:58:32 -0800 Subject: Add basic front-end support for expr_put. --- src/comp/middle/trans.rs | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index e140ddcc..c8f21dff 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -3122,6 +3122,10 @@ fn trans_expr(@block_ctxt cx, @ast.expr e) -> result { ret trans_ret(cx, e); } + case (ast.expr_ret(?e)) { + ret trans_put(cx, e); + } + case (ast.expr_be(?e)) { ret trans_be(cx, e); } @@ -3199,6 +3203,11 @@ fn trans_fail(@block_ctxt cx, common.span sp, str fail_str) -> result { ret trans_upcall(cx, "upcall_fail", args); } +fn trans_put(@block_ctxt cx, &option.t[@ast.expr] e) -> result { + cx.fcx.ccx.sess.unimpl("put expr"); + fail; +} + fn trans_ret(@block_ctxt cx, &option.t[@ast.expr] e) -> result { auto bcx = cx; auto val = C_nil(); -- cgit v1.2.3 From 4a72a23171d87fb5a0f9b7ad039944856b93bf0f Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Mon, 14 Feb 2011 18:17:31 -0800 Subject: Add basic front-end support for 'for each' loops. --- src/comp/middle/trans.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index c8f21dff..c4e5c9c4 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -2116,6 +2116,15 @@ fn trans_for(@block_ctxt cx, bind inner(_, local, _, _, body)); } +fn trans_for_each(@block_ctxt cx, + @ast.decl decl, + @ast.expr seq, + &ast.block body) -> result { + cx.fcx.ccx.sess.unimpl("for each loop"); + fail; +} + + fn trans_while(@block_ctxt cx, @ast.expr cond, &ast.block body) -> result { @@ -3035,6 +3044,10 @@ fn trans_expr(@block_ctxt cx, @ast.expr e) -> result { ret trans_for(cx, decl, seq, body); } + case (ast.expr_for_each(?decl, ?seq, ?body, _)) { + ret trans_for_each(cx, decl, seq, body); + } + case (ast.expr_while(?cond, ?body, _)) { ret trans_while(cx, cond, body); } -- cgit v1.2.3 From 9ae89bd404803be6b820189d8e0480b3395d05ee Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Tue, 15 Feb 2011 12:20:30 -0800 Subject: Add _mutable unop. --- src/comp/middle/trans.rs | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index c4e5c9c4..72a4fe5c 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -1834,6 +1834,9 @@ fn trans_unary(@block_ctxt cx, ast.unop op, } ret res(sub.bcx, val); } + case (ast._mutable) { + ret trans_expr(cx, e); + } } fail; } -- cgit v1.2.3 From d4bf67dde638fdeea4361daf16bee421d479628e Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Tue, 15 Feb 2011 18:16:13 -0800 Subject: Translate record extension. --- src/comp/middle/trans.rs | 44 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 36 insertions(+), 8 deletions(-) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 72a4fe5c..7d3f9997 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -2998,9 +2998,6 @@ fn trans_vec(@block_ctxt cx, vec[@ast.expr] args, fn trans_rec(@block_ctxt cx, vec[ast.field] fields, option.t[@ast.expr] base, &ast.ann ann) -> result { - // FIXME: handle presence of a nonempty base. - check (base == none[@ast.expr]); - auto bcx = cx; auto t = node_ann_type(bcx.fcx.ccx, ann); auto llty = type_of(bcx.fcx.ccx, t); @@ -3011,13 +3008,44 @@ fn trans_rec(@block_ctxt cx, vec[ast.field] fields, find_scope_cx(cx).cleanups += clean(bind drop_ty(_, rec_val, t)); let int i = 0; - for (ast.field f in fields) { - auto e_ty = ty.expr_ty(f.expr); - auto src_res = trans_expr(bcx, f.expr); - bcx = src_res.bcx; + auto base_val = C_nil(); + + alt (base) { + case (none[@ast.expr]) { } + case (some[@ast.expr](?bexp)) { + auto base_res = trans_expr(bcx, bexp); + bcx = base_res.bcx; + base_val = base_res.val; + } + } + + let vec[ty.field] ty_fields = vec(); + alt (t.struct) { + case (ty.ty_rec(?flds)) { ty_fields = flds; } + } + + for (ty.field tf in ty_fields) { + auto e_ty = tf.ty; auto dst_res = GEP_tup_like(bcx, t, rec_val, vec(0, i)); bcx = dst_res.bcx; - bcx = copy_ty(src_res.bcx, INIT, dst_res.val, src_res.val, e_ty).bcx; + + auto expr_provided = false; + auto src_res = res(bcx, C_nil()); + + for (ast.field f in fields) { + if (_str.eq(f.ident, tf.ident)) { + expr_provided = true; + src_res = trans_expr(bcx, f.expr); + } + } + if (!expr_provided) { + src_res = GEP_tup_like(bcx, t, base_val, vec(0, i)); + src_res = res(src_res.bcx, + load_scalar_or_boxed(bcx, src_res.val, e_ty)); + } + + bcx = src_res.bcx; + bcx = copy_ty(bcx, INIT, dst_res.val, src_res.val, e_ty).bcx; i += 1; } ret res(bcx, rec_val); -- cgit v1.2.3 From 012fa69ea500aa31cb3dd2cd3df67ecd3eefd44e Mon Sep 17 00:00:00 2001 From: Rafael Avila de Espindola Date: Wed, 16 Feb 2011 14:02:02 -0500 Subject: More typechecking for native types and the needed plumbing in codegen. --- src/comp/middle/trans.rs | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 7d3f9997..037fd69f 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -70,6 +70,7 @@ state type crate_ctxt = rec(session.session sess, hashmap[str, ValueRef] item_names, hashmap[ast.def_id, ValueRef] item_ids, hashmap[ast.def_id, @ast.item] items, + hashmap[ast.def_id, @ast.native_item] native_items, hashmap[ast.def_id, @tag_info] tags, hashmap[ast.def_id, ValueRef] fn_pairs, hashmap[ast.def_id, ValueRef] consts, @@ -440,6 +441,7 @@ fn type_of_fn(@crate_ctxt cx, vec[ty.arg] inputs, @ty.t output) -> TypeRef { fn type_of_inner(@crate_ctxt cx, @ty.t t) -> TypeRef { alt (t.struct) { + case (ty.ty_native) { ret T_ptr(T_i8()); } case (ty.ty_nil) { ret T_nil(); } case (ty.ty_bool) { ret T_bool(); } case (ty.ty_int) { ret T_int(); } @@ -2429,6 +2431,12 @@ fn trans_path(@block_ctxt cx, &ast.path p, &option.t[ast.def] dopt, check (cx.fcx.ccx.consts.contains_key(did)); ret lval_mem(cx, cx.fcx.ccx.consts.get(did)); } + case (ast.def_native_fn(?did)) { + check (cx.fcx.ccx.native_items.contains_key(did)); + auto fn_item = cx.fcx.ccx.native_items.get(did); + ret lval_generic_fn(cx, ty.native_item_ty(fn_item), + did, ann); + } case (_) { cx.fcx.ccx.sess.unimpl("def variant in trans"); } @@ -4053,6 +4061,18 @@ fn decl_fn_and_pair(@crate_ctxt cx, cx.fn_pairs.insert(id, gvar); } +fn collect_native_item(&@crate_ctxt cx, @ast.native_item i) -> @crate_ctxt { + alt (i.node) { + case (ast.native_item_fn(?name, _, _, ?fid, ?ann)) { + cx.native_items.insert(fid, i); + if (! cx.obj_methods.contains_key(fid)) { + decl_fn_and_pair(cx, "fn", name, ann, fid); + } + } + case (_) { /* fall through */ } + } + ret cx; +} fn collect_item(&@crate_ctxt cx, @ast.item i) -> @crate_ctxt { @@ -4101,7 +4121,8 @@ fn collect_items(@crate_ctxt cx, @ast.crate crate) { let fold.ast_fold[@crate_ctxt] fld = fold.new_identity_fold[@crate_ctxt](); - fld = @rec( update_env_for_item = bind collect_item(_,_) + fld = @rec( update_env_for_item = bind collect_item(_,_), + update_env_for_native_item = bind collect_native_item(_,_) with *fld ); fold.fold_crate[@crate_ctxt](cx, fld, crate); @@ -4559,6 +4580,7 @@ fn trans_crate(session.session sess, @ast.crate crate, str output, item_names = new_str_hash[ValueRef](), item_ids = new_def_hash[ValueRef](), items = new_def_hash[@ast.item](), + native_items = new_def_hash[@ast.native_item](), tags = new_def_hash[@tag_info](), fn_pairs = new_def_hash[ValueRef](), consts = new_def_hash[ValueRef](), -- cgit v1.2.3 From f50caa75c20f997a578d70c696cc9c1bf9fa40fe Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Wed, 16 Feb 2011 11:33:14 -0800 Subject: Wrap long line in last commit. --- src/comp/middle/trans.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 037fd69f..282a62d6 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -70,7 +70,8 @@ state type crate_ctxt = rec(session.session sess, hashmap[str, ValueRef] item_names, hashmap[ast.def_id, ValueRef] item_ids, hashmap[ast.def_id, @ast.item] items, - hashmap[ast.def_id, @ast.native_item] native_items, + hashmap[ast.def_id, + @ast.native_item] native_items, hashmap[ast.def_id, @tag_info] tags, hashmap[ast.def_id, ValueRef] fn_pairs, hashmap[ast.def_id, ValueRef] consts, -- cgit v1.2.3 From a63696dfe2bd47d34925a3ad44db9d2ede949e36 Mon Sep 17 00:00:00 2001 From: Rafael Avila de Espindola Date: Wed, 16 Feb 2011 15:34:59 -0500 Subject: Add a more specialized decl_native_fn_and_pair. Native functions now have the right name. --- src/comp/middle/trans.rs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 282a62d6..94fa9f91 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -4062,12 +4062,24 @@ fn decl_fn_and_pair(@crate_ctxt cx, cx.fn_pairs.insert(id, gvar); } +fn decl_native_fn_and_pair(@crate_ctxt cx, + str name, + &ast.ann ann, + ast.def_id id) { + + auto llpairty = node_type(cx, ann); + auto llfty = get_pair_fn_ty(llpairty); + + let ValueRef llfn = decl_fastcall_fn(cx.llmod, name, llfty); + cx.item_ids.insert(id, llfn); +} + fn collect_native_item(&@crate_ctxt cx, @ast.native_item i) -> @crate_ctxt { alt (i.node) { case (ast.native_item_fn(?name, _, _, ?fid, ?ann)) { cx.native_items.insert(fid, i); if (! cx.obj_methods.contains_key(fid)) { - decl_fn_and_pair(cx, "fn", name, ann, fid); + decl_native_fn_and_pair(cx, name, ann, fid); } } case (_) { /* fall through */ } -- cgit v1.2.3 From 07c7888037cb74ca33459946145608a854aae6ed Mon Sep 17 00:00:00 2001 From: Rafael Avila de Espindola Date: Wed, 16 Feb 2011 16:16:11 -0500 Subject: Don't add the rust arguments to native functions. We now produce the correct arguments for native functions. --- src/comp/middle/trans.rs | 45 ++++++++++++++++++++++++++++++--------------- 1 file changed, 30 insertions(+), 15 deletions(-) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 94fa9f91..e3e68d4b 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -370,6 +370,26 @@ fn type_of(@crate_ctxt cx, @ty.t t) -> TypeRef { ret llty; } +fn type_of_explicit_args(@crate_ctxt cx, + vec[ty.arg] inputs) -> vec[TypeRef] { + let vec[TypeRef] atys = vec(); + for (ty.arg arg in inputs) { + if (ty.type_has_dynamic_size(arg.ty)) { + check (arg.mode == ast.alias); + atys += T_typaram_ptr(); + } else { + let TypeRef t = type_of(cx, arg.ty); + alt (arg.mode) { + case (ast.alias) { + t = T_ptr(t); + } + case (_) { /* fall through */ } + } + atys += t; + } + } + ret atys; +} // NB: must keep 4 fns in sync: // @@ -417,21 +437,7 @@ fn type_of_fn_full(@crate_ctxt cx, } // ... then explicit args. - for (ty.arg arg in inputs) { - if (ty.type_has_dynamic_size(arg.ty)) { - check (arg.mode == ast.alias); - atys += T_typaram_ptr(); - } else { - let TypeRef t = type_of(cx, arg.ty); - alt (arg.mode) { - case (ast.alias) { - t = T_ptr(t); - } - case (_) { /* fall through */ } - } - atys += t; - } - } + atys += type_of_explicit_args(cx, inputs); ret T_fn(atys, llvm.LLVMVoidType()); } @@ -440,6 +446,12 @@ fn type_of_fn(@crate_ctxt cx, vec[ty.arg] inputs, @ty.t output) -> TypeRef { ret type_of_fn_full(cx, none[TypeRef], inputs, output); } +fn type_of_native_fn(@crate_ctxt cx, vec[ty.arg] inputs, + @ty.t output) -> TypeRef { + let vec[TypeRef] atys = type_of_explicit_args(cx, inputs); + ret T_fn(atys, llvm.LLVMVoidType()); +} + fn type_of_inner(@crate_ctxt cx, @ty.t t) -> TypeRef { alt (t.struct) { case (ty.ty_native) { ret T_ptr(T_i8()); } @@ -489,6 +501,9 @@ fn type_of_inner(@crate_ctxt cx, @ty.t t) -> TypeRef { case (ty.ty_fn(?args, ?out)) { ret T_fn_pair(type_of_fn(cx, args, out)); } + case (ty.ty_native_fn(?args, ?out)) { + ret T_fn_pair(type_of_native_fn(cx, args, out)); + } case (ty.ty_obj(?meths)) { auto th = mk_type_handle(); auto self_ty = llvm.LLVMResolveTypeHandle(th.llth); -- cgit v1.2.3 From 79d3ceaac0b4a6ca83f0ff7b8b533649fc5165a1 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 17 Feb 2011 12:20:55 -0800 Subject: Steps toward implementing iterators. --- src/comp/middle/trans.rs | 123 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 116 insertions(+), 7 deletions(-) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index e3e68d4b..62b5a415 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -88,6 +88,7 @@ state type fn_ctxt = rec(ValueRef llfn, ValueRef llenv, ValueRef llretptr, mutable option.t[ValueRef] llself, + mutable option.t[ValueRef] lliterbody, hashmap[ast.def_id, ValueRef] llargs, hashmap[ast.def_id, ValueRef] llobjfields, hashmap[ast.def_id, ValueRef] lllocals, @@ -399,6 +400,8 @@ fn type_of_explicit_args(@crate_ctxt cx, // - trans_args fn type_of_fn_full(@crate_ctxt cx, + // FIXME: change bool flag to tag + bool is_iter, option.t[TypeRef] obj_self, vec[ty.arg] inputs, @ty.t output) -> TypeRef { @@ -436,14 +439,26 @@ fn type_of_fn_full(@crate_ctxt cx, } } + if (is_iter) { + // If it's an iter, the 'output' type of the iter is actually the + // *input* type of the function we're given as our iter-block + // argument. + atys += T_fn_pair(type_of_fn_full(cx, false, none[TypeRef], + vec(rec(mode=ast.val, ty=output)), + plain_ty(ty.ty_nil))); + } + // ... then explicit args. atys += type_of_explicit_args(cx, inputs); ret T_fn(atys, llvm.LLVMVoidType()); } -fn type_of_fn(@crate_ctxt cx, vec[ty.arg] inputs, @ty.t output) -> TypeRef { - ret type_of_fn_full(cx, none[TypeRef], inputs, output); +fn type_of_fn(@crate_ctxt cx, + // FIXME: change bool flag to tag + bool is_iter, + vec[ty.arg] inputs, @ty.t output) -> TypeRef { + ret type_of_fn_full(cx, is_iter, none[TypeRef], inputs, output); } fn type_of_native_fn(@crate_ctxt cx, vec[ty.arg] inputs, @@ -499,7 +514,8 @@ fn type_of_inner(@crate_ctxt cx, @ty.t t) -> TypeRef { ret T_struct(tys); } case (ty.ty_fn(?args, ?out)) { - ret T_fn_pair(type_of_fn(cx, args, out)); + // FIXME: put iter in ty_fn. + ret T_fn_pair(type_of_fn(cx, false, args, out)); } case (ty.ty_native_fn(?args, ?out)) { ret T_fn_pair(type_of_native_fn(cx, args, out)); @@ -512,6 +528,8 @@ fn type_of_inner(@crate_ctxt cx, @ty.t t) -> TypeRef { for (ty.method m in meths) { let TypeRef mty = type_of_fn_full(cx, + // FIXME: support method iters + false, some[TypeRef](self_ty), m.inputs, m.output); mtys += T_ptr(mty); @@ -2141,7 +2159,83 @@ fn trans_for_each(@block_ctxt cx, @ast.decl decl, @ast.expr seq, &ast.block body) -> result { - cx.fcx.ccx.sess.unimpl("for each loop"); + + /* + * The translation is a little .. complex here. Code like: + * + * let ty1 p = ...; + * + * let ty1 q = ...; + * + * foreach (ty v in foo(a,b)) { body(p,q,v) } + * + * + * Turns into a something like so (C/Rust mishmash): + * + * type env = { *ty1 p, *ty2 q, ... }; + * + * let env e = { &p, &q, ... }; + * + * fn foreach123_body(env* e, ty v) { body(*(e->p),*(e->q),v) } + * + * foo([foreach123_body, env*], a, b); + * + */ + + // Step 1: walk body and figure out which references it makes + // escape. This could be determined upstream, and probably ought + // to be so, eventualy. For first cut, skip this. Null env. + + auto env_ty = T_struct(vec(T_ptr(T_i8()))); + + + // Step 2: Declare foreach body function. + + // FIXME: possibly support alias-mode here? + auto decl_ty = plain_ty(ty.ty_nil); + alt (decl.node) { + case (ast.decl_local(?local)) { + decl_ty = node_ann_type(cx.fcx.ccx, local.ann); + } + } + + let str s = + cx.fcx.ccx.names.next("_rust_foreach") + + sep() + cx.fcx.ccx.path; + + // The 'env' arg entering the body function is a fake env member (as in + // the env-part of the normal rust calling convention) that actually + // points to a stack allocated env in this frame. We bundle that env + // pointer along with the foreach-body-fn pointer into a 'normal' fn pair + // and pass it in as a first class fn-arg to the iterator. + + auto foreach_llty = type_of_fn_full(cx.fcx.ccx, false, none[TypeRef], + vec(rec(mode=ast.val, ty=decl_ty)), + plain_ty(ty.ty_nil)); + + let ValueRef llforeach = decl_fastcall_fn(cx.fcx.ccx.llmod, + s, foreach_llty); + + // FIXME: handle ty params properly. + let vec[ast.ty_param] ty_params = vec(); + + auto fcx = new_fn_ctxt(cx.fcx.ccx, s, llforeach); + auto bcx = new_top_block_ctxt(fcx); + + // FIXME: populate lllocals from llenv here. + auto res = trans_block(bcx, body); + res.bcx.build.RetVoid(); + + + // Step 3: Call iter passing [llforeach, llenv], plus other args. + + alt (seq.node) { + case (ast.expr_call(?f, ?args, ?ann)) { + // FIXME_ finish here by transferring to trans_call, + // suitably refactored. + cx.fcx.ccx.sess.unimpl("for each loop in trans"); + } + } fail; } @@ -3538,6 +3632,7 @@ fn new_fn_ctxt(@crate_ctxt cx, llenv=llenv, llretptr=llretptr, mutable llself=none[ValueRef], + mutable lliterbody=none[ValueRef], llargs=llargs, llobjfields=llobjfields, lllocals=lllocals, @@ -3553,6 +3648,8 @@ fn new_fn_ctxt(@crate_ctxt cx, // - trans_args fn create_llargs_for_fn_args(&@fn_ctxt cx, + // FIXME: change bool flag to tag + bool is_iter, option.t[TypeRef] ty_self, @ty.t ret_ty, &vec[ast.arg] args, @@ -3577,6 +3674,12 @@ fn create_llargs_for_fn_args(&@fn_ctxt cx, } } + if (is_iter) { + auto llarg = llvm.LLVMGetParam(cx.llfn, arg_n); + check (llarg as int != 0); + cx.lliterbody = some[ValueRef](llarg); + arg_n += 1u; + } for (ast.arg arg in args) { auto llarg = llvm.LLVMGetParam(cx.llfn, arg_n); @@ -3713,7 +3816,8 @@ fn trans_fn(@crate_ctxt cx, &ast._fn f, ast.def_id fid, cx.item_names.insert(cx.path, llfndecl); auto fcx = new_fn_ctxt(cx, cx.path, llfndecl); - create_llargs_for_fn_args(fcx, ty_self, ret_ty_of_fn(ann), + create_llargs_for_fn_args(fcx, f.is_iter, + ty_self, ret_ty_of_fn(ann), f.decl.inputs, ty_params); auto bcx = new_top_block_ctxt(fcx); @@ -3754,6 +3858,8 @@ fn trans_vtbl(@crate_ctxt cx, TypeRef self_ty, alt (node_ann_type(cx, m.node.ann).struct) { case (ty.ty_fn(?inputs, ?output)) { llfnty = type_of_fn_full(cx, + // FIXME: support method iters. + false, some[TypeRef](self_ty), inputs, output); } @@ -3797,7 +3903,8 @@ fn trans_obj(@crate_ctxt cx, &ast._obj ob, ast.def_id oid, } auto fcx = new_fn_ctxt(cx, cx.path, llctor_decl); - create_llargs_for_fn_args(fcx, none[TypeRef], ret_ty_of_fn(ann), + create_llargs_for_fn_args(fcx, false, + none[TypeRef], ret_ty_of_fn(ann), fn_args, ty_params); auto bcx = new_top_block_ctxt(fcx); @@ -3925,7 +4032,8 @@ fn trans_tag_variant(@crate_ctxt cx, ast.def_id tag_id, let ValueRef llfndecl = cx.item_ids.get(variant.id); auto fcx = new_fn_ctxt(cx, cx.path, llfndecl); - create_llargs_for_fn_args(fcx, none[TypeRef], ret_ty_of_fn(variant.ann), + create_llargs_for_fn_args(fcx, false, + none[TypeRef], ret_ty_of_fn(variant.ann), fn_args, ty_params); auto bcx = new_top_block_ctxt(fcx); @@ -4331,6 +4439,7 @@ fn trans_exit_task_glue(@crate_ctxt cx) { llenv=C_null(T_opaque_closure_ptr()), llretptr=C_null(T_ptr(T_nil())), mutable llself=none[ValueRef], + mutable lliterbody=none[ValueRef], llargs=new_def_hash[ValueRef](), llobjfields=new_def_hash[ValueRef](), lllocals=new_def_hash[ValueRef](), -- cgit v1.2.3 From 10befcd9a4d9f68e2dbec84c4a86450a021143fb Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Thu, 17 Feb 2011 16:23:31 -0800 Subject: Add type parameters to tag types --- src/comp/middle/trans.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 62b5a415..9d336f22 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -490,7 +490,7 @@ fn type_of_inner(@crate_ctxt cx, @ty.t t) -> TypeRef { } case (ty.ty_char) { ret T_char(); } case (ty.ty_str) { ret T_ptr(T_str()); } - case (ty.ty_tag(?tag_id)) { + case (ty.ty_tag(?tag_id, _)) { ret llvm.LLVMResolveTypeHandle(cx.tags.get(tag_id).th.llth); } case (ty.ty_box(?t)) { @@ -1445,7 +1445,9 @@ fn iter_structural_ty(@block_ctxt cx, i += 1; } } - case (ty.ty_tag(?tid)) { + case (ty.ty_tag(?tid, _)) { + // TODO: type params! + check (cx.fcx.ccx.tags.contains_key(tid)); auto info = cx.fcx.ccx.tags.get(tid); auto n_variants = _vec.len[tup(ast.def_id,arity)](info.variants); -- cgit v1.2.3 From 0ddb832a4e34dfd0edcd22529e16732d7cb15f88 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 17 Feb 2011 18:16:51 -0800 Subject: Teach trans and llvm to cooperate on producing tidier diagnostic names in trans.ty_str. --- src/comp/middle/trans.rs | 268 +++++++++++++++++++++++++++++------------------ 1 file changed, 164 insertions(+), 104 deletions(-) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 9d336f22..538dfdbe 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -28,9 +28,11 @@ import lib.llvm.llvm; import lib.llvm.builder; import lib.llvm.target_data; import lib.llvm.type_handle; +import lib.llvm.type_names; import lib.llvm.mk_pass_manager; import lib.llvm.mk_target_data; import lib.llvm.mk_type_handle; +import lib.llvm.mk_type_names; import lib.llvm.llvm.ModuleRef; import lib.llvm.llvm.ValueRef; import lib.llvm.llvm.TypeRef; @@ -64,6 +66,7 @@ type tag_info = rec(type_handle th, state type crate_ctxt = rec(session.session sess, ModuleRef llmod, target_data td, + type_names tn, ValueRef crate_ptr, hashmap[str, ValueRef] upcalls, hashmap[str, ValueRef] intrinsics, @@ -133,16 +136,16 @@ fn res(@block_ctxt bcx, ValueRef val) -> result { mutable val = val); } -fn ty_str(TypeRef t) -> str { - ret lib.llvm.type_to_str(t); +fn ty_str(type_names tn, TypeRef t) -> str { + ret lib.llvm.type_to_str(tn, t); } fn val_ty(ValueRef v) -> TypeRef { ret llvm.LLVMTypeOf(v); } -fn val_str(ValueRef v) -> str { - ret ty_str(val_ty(v)); +fn val_str(type_names tn, ValueRef v) -> str { + ret ty_str(tn, val_ty(v)); } @@ -215,9 +218,9 @@ fn T_fn(vec[TypeRef] inputs, TypeRef output) -> TypeRef { False); } -fn T_fn_pair(TypeRef tfn) -> TypeRef { +fn T_fn_pair(type_names tn, TypeRef tfn) -> TypeRef { ret T_struct(vec(T_ptr(tfn), - T_opaque_closure_ptr())); + T_opaque_closure_ptr(tn))); } fn T_ptr(TypeRef t) -> TypeRef { @@ -234,34 +237,55 @@ fn T_opaque() -> TypeRef { ret llvm.LLVMOpaqueType(); } -fn T_task() -> TypeRef { - ret T_struct(vec(T_int(), // Refcount - T_int(), // Delegate pointer - T_int(), // Stack segment pointer - T_int(), // Runtime SP - T_int(), // Rust SP - T_int(), // GC chain - T_int(), // Domain pointer - T_int() // Crate cache pointer - )); +fn T_task(type_names tn) -> TypeRef { + auto s = "task"; + if (tn.name_has_type(s)) { + ret tn.get_type(s); + } + + auto t = T_struct(vec(T_int(), // Refcount + T_int(), // Delegate pointer + T_int(), // Stack segment pointer + T_int(), // Runtime SP + T_int(), // Rust SP + T_int(), // GC chain + T_int(), // Domain pointer + T_int() // Crate cache pointer + )); + tn.associate(s, t); + ret t; } -fn T_glue_fn() -> TypeRef { +fn T_glue_fn(type_names tn) -> TypeRef { + auto s = "glue_fn"; + if (tn.name_has_type(s)) { + ret tn.get_type(s); + } + // Bit of a kludge: pick the fn typeref out of the tydesc.. let vec[TypeRef] tydesc_elts = _vec.init_elt[TypeRef](T_nil(), 10u); - llvm.LLVMGetStructElementTypes(T_tydesc(), + llvm.LLVMGetStructElementTypes(T_tydesc(tn), _vec.buf[TypeRef](tydesc_elts)); - ret llvm.LLVMGetElementType(tydesc_elts.(abi.tydesc_field_drop_glue_off)); + auto t = + llvm.LLVMGetElementType + (tydesc_elts.(abi.tydesc_field_drop_glue_off)); + tn.associate(s, t); + ret t; } -fn T_tydesc() -> TypeRef { +fn T_tydesc(type_names tn) -> TypeRef { + + auto s = "tydesc"; + if (tn.name_has_type(s)) { + ret tn.get_type(s); + } auto th = mk_type_handle(); auto abs_tydesc = llvm.LLVMResolveTypeHandle(th.llth); auto tydescpp = T_ptr(T_ptr(abs_tydesc)); auto pvoid = T_ptr(T_i8()); auto glue_fn_ty = T_ptr(T_fn(vec(T_ptr(T_nil()), - T_taskptr(), + T_taskptr(tn), T_ptr(T_nil()), tydescpp, pvoid), T_void())); @@ -277,7 +301,9 @@ fn T_tydesc() -> TypeRef { glue_fn_ty)); // is_stateful llvm.LLVMRefineType(abs_tydesc, tydesc); - ret llvm.LLVMResolveTypeHandle(th.llth); + auto t = llvm.LLVMResolveTypeHandle(th.llth); + tn.associate(s, t); + ret t; } fn T_array(TypeRef t, uint n) -> TypeRef { @@ -300,67 +326,90 @@ fn T_box(TypeRef t) -> TypeRef { ret T_struct(vec(T_int(), t)); } -fn T_crate() -> TypeRef { - ret T_struct(vec(T_int(), // ptrdiff_t image_base_off - T_int(), // uintptr_t self_addr - T_int(), // ptrdiff_t debug_abbrev_off - T_int(), // size_t debug_abbrev_sz - T_int(), // ptrdiff_t debug_info_off - T_int(), // size_t debug_info_sz - T_int(), // size_t activate_glue_off - T_int(), // size_t yield_glue_off - T_int(), // size_t unwind_glue_off - T_int(), // size_t gc_glue_off - T_int(), // size_t main_exit_task_glue_off - T_int(), // int n_rust_syms - T_int(), // int n_c_syms - T_int() // int n_libs - )); +fn T_crate(type_names tn) -> TypeRef { + auto s = "crate"; + if (tn.name_has_type(s)) { + ret tn.get_type(s); + } + + auto t = T_struct(vec(T_int(), // ptrdiff_t image_base_off + T_int(), // uintptr_t self_addr + T_int(), // ptrdiff_t debug_abbrev_off + T_int(), // size_t debug_abbrev_sz + T_int(), // ptrdiff_t debug_info_off + T_int(), // size_t debug_info_sz + T_int(), // size_t activate_glue_off + T_int(), // size_t yield_glue_off + T_int(), // size_t unwind_glue_off + T_int(), // size_t gc_glue_off + T_int(), // size_t main_exit_task_glue_off + T_int(), // int n_rust_syms + T_int(), // int n_c_syms + T_int() // int n_libs + )); + tn.associate(s, t); + ret t; } fn T_double() -> TypeRef { ret llvm.LLVMDoubleType(); } -fn T_taskptr() -> TypeRef { - ret T_ptr(T_task()); +fn T_taskptr(type_names tn) -> TypeRef { + ret T_ptr(T_task(tn)); } -fn T_typaram_ptr() -> TypeRef { - ret T_ptr(T_i8()); +fn T_typaram_ptr(type_names tn) -> TypeRef { + auto s = "typaram"; + if (tn.name_has_type(s)) { + ret tn.get_type(s); + } + + auto t = T_ptr(T_i8()); + tn.associate(s, t); + ret t; } -fn T_closure_ptr(TypeRef lltarget_ty, +fn T_closure_ptr(type_names tn, + TypeRef lltarget_ty, TypeRef llbindings_ty) -> TypeRef { - ret T_ptr(T_box(T_struct(vec(T_ptr(T_tydesc()), + ret T_ptr(T_box(T_struct(vec(T_ptr(T_tydesc(tn)), lltarget_ty, llbindings_ty) // FIXME: add captured typarams. ))); } -fn T_opaque_closure_ptr() -> TypeRef { - ret T_closure_ptr(T_struct(vec(T_ptr(T_nil()), - T_ptr(T_nil()))), - T_nil()); +fn T_opaque_closure_ptr(type_names tn) -> TypeRef { + auto s = "*closure"; + if (tn.name_has_type(s)) { + ret tn.get_type(s); + } + auto t = T_closure_ptr(tn, T_struct(vec(T_ptr(T_nil()), + T_ptr(T_nil()))), + T_nil()); + tn.associate(s, t); + ret t; } -fn T_captured_tydescs(uint n) -> TypeRef { - ret T_struct(_vec.init_elt[TypeRef](T_ptr(T_tydesc()), n)); +fn T_captured_tydescs(type_names tn, uint n) -> TypeRef { + ret T_struct(_vec.init_elt[TypeRef](T_ptr(T_tydesc(tn)), n)); } -fn T_obj(uint n_captured_tydescs, TypeRef llfields_ty) -> TypeRef { - ret T_struct(vec(T_ptr(T_tydesc()), - T_captured_tydescs(n_captured_tydescs), +fn T_obj(type_names tn, uint n_captured_tydescs, + TypeRef llfields_ty) -> TypeRef { + ret T_struct(vec(T_ptr(T_tydesc(tn)), + T_captured_tydescs(tn, n_captured_tydescs), llfields_ty)); } -fn T_obj_ptr(uint n_captured_tydescs, TypeRef llfields_ty) -> TypeRef { - ret T_ptr(T_box(T_obj(n_captured_tydescs, llfields_ty))); +fn T_obj_ptr(type_names tn, uint n_captured_tydescs, + TypeRef llfields_ty) -> TypeRef { + ret T_ptr(T_box(T_obj(tn, n_captured_tydescs, llfields_ty))); } -fn T_opaque_obj_ptr() -> TypeRef { - ret T_obj_ptr(0u, T_nil()); +fn T_opaque_obj_ptr(type_names tn) -> TypeRef { + ret T_obj_ptr(tn, 0u, T_nil()); } @@ -377,7 +426,7 @@ fn type_of_explicit_args(@crate_ctxt cx, for (ty.arg arg in inputs) { if (ty.type_has_dynamic_size(arg.ty)) { check (arg.mode == ast.alias); - atys += T_typaram_ptr(); + atys += T_typaram_ptr(cx.tn); } else { let TypeRef t = type_of(cx, arg.ty); alt (arg.mode) { @@ -409,13 +458,13 @@ fn type_of_fn_full(@crate_ctxt cx, // Arg 0: Output pointer. if (ty.type_has_dynamic_size(output)) { - atys += T_typaram_ptr(); + atys += T_typaram_ptr(cx.tn); } else { atys += T_ptr(type_of(cx, output)); } // Arg 1: Task pointer. - atys += T_taskptr(); + atys += T_taskptr(cx.tn); // Arg 2: Env (closure-bindings / self-obj) alt (obj_self) { @@ -424,7 +473,7 @@ fn type_of_fn_full(@crate_ctxt cx, atys += t; } case (_) { - atys += T_opaque_closure_ptr(); + atys += T_opaque_closure_ptr(cx.tn); } } @@ -434,7 +483,7 @@ fn type_of_fn_full(@crate_ctxt cx, ty.count_ty_params(plain_ty(ty.ty_fn(inputs, output))); auto i = 0u; while (i < ty_param_count) { - atys += T_ptr(T_tydesc()); + atys += T_ptr(T_tydesc(cx.tn)); i += 1u; } } @@ -443,7 +492,8 @@ fn type_of_fn_full(@crate_ctxt cx, // If it's an iter, the 'output' type of the iter is actually the // *input* type of the function we're given as our iter-block // argument. - atys += T_fn_pair(type_of_fn_full(cx, false, none[TypeRef], + atys += T_fn_pair(cx.tn, + type_of_fn_full(cx, false, none[TypeRef], vec(rec(mode=ast.val, ty=output)), plain_ty(ty.ty_nil))); } @@ -515,10 +565,10 @@ fn type_of_inner(@crate_ctxt cx, @ty.t t) -> TypeRef { } case (ty.ty_fn(?args, ?out)) { // FIXME: put iter in ty_fn. - ret T_fn_pair(type_of_fn(cx, false, args, out)); + ret T_fn_pair(cx.tn, type_of_fn(cx, false, args, out)); } case (ty.ty_native_fn(?args, ?out)) { - ret T_fn_pair(type_of_native_fn(cx, args, out)); + ret T_fn_pair(cx.tn, type_of_native_fn(cx, args, out)); } case (ty.ty_obj(?meths)) { auto th = mk_type_handle(); @@ -536,7 +586,7 @@ fn type_of_inner(@crate_ctxt cx, @ty.t t) -> TypeRef { } let TypeRef vtbl = T_struct(mtys); let TypeRef pair = T_struct(vec(T_ptr(vtbl), - T_opaque_obj_ptr())); + T_opaque_obj_ptr(cx.tn))); auto abs_pair = llvm.LLVMResolveTypeHandle(th.llth); llvm.LLVMRefineType(abs_pair, pair); @@ -548,9 +598,9 @@ fn type_of_inner(@crate_ctxt cx, @ty.t t) -> TypeRef { fail; } case (ty.ty_param(_)) { - ret T_typaram_ptr(); + ret T_typaram_ptr(cx.tn); } - case (ty.ty_type) { ret T_ptr(T_tydesc()); } + case (ty.ty_type) { ret T_ptr(T_tydesc(cx.tn)); } } fail; } @@ -686,11 +736,11 @@ fn decl_fastcall_fn(ModuleRef llmod, str name, TypeRef llty) -> ValueRef { ret decl_fn(llmod, name, lib.llvm.LLVMFastCallConv, llty); } -fn decl_glue(ModuleRef llmod, str s) -> ValueRef { - ret decl_cdecl_fn(llmod, s, T_fn(vec(T_taskptr()), T_void())); +fn decl_glue(ModuleRef llmod, type_names tn, str s) -> ValueRef { + ret decl_cdecl_fn(llmod, s, T_fn(vec(T_taskptr(tn)), T_void())); } -fn decl_upcall_glue(ModuleRef llmod, uint _n) -> ValueRef { +fn decl_upcall_glue(ModuleRef llmod, type_names tn, uint _n) -> ValueRef { // It doesn't actually matter what type we come up with here, at the // moment, as we cast the upcall function pointers to int before passing // them to the indirect upcall-invocation glue. But eventually we'd like @@ -698,7 +748,7 @@ fn decl_upcall_glue(ModuleRef llmod, uint _n) -> ValueRef { let int n = _n as int; let str s = abi.upcall_glue_name(n); let vec[TypeRef] args = - vec(T_taskptr(), // taskptr + vec(T_taskptr(tn), // taskptr T_int()) // callee + _vec.init_elt[TypeRef](T_int(), n as uint); @@ -709,7 +759,7 @@ fn get_upcall(@crate_ctxt cx, str name, int n_args) -> ValueRef { if (cx.upcalls.contains_key(name)) { ret cx.upcalls.get(name); } - auto inputs = vec(T_taskptr()); + auto inputs = vec(T_taskptr(cx.tn)); inputs += _vec.init_elt[TypeRef](T_int(), n_args as uint); auto output = T_int(); auto f = decl_cdecl_fn(cx.llmod, name, T_fn(inputs, output)); @@ -1064,7 +1114,8 @@ fn get_tydesc(&@block_ctxt cx, @ty.t t) -> result { auto root = cx.fcx.ccx.tydescs.get(t); - auto tydescs = cx.build.Alloca(T_array(T_ptr(T_tydesc()), n_params)); + auto tydescs = cx.build.Alloca(T_array(T_ptr(T_tydesc(cx.fcx.ccx.tn)), + n_params)); auto i = 0; auto tdp = cx.build.GEP(tydescs, vec(C_int(0), C_int(i))); @@ -1089,7 +1140,8 @@ fn get_tydesc(&@block_ctxt cx, @ty.t t) -> result { C_int((1u + n_params) as int), bcx.build.PtrToInt(tydescs, T_int()))); - ret res(v.bcx, v.bcx.build.IntToPtr(v.val, T_ptr(T_tydesc()))); + ret res(v.bcx, v.bcx.build.IntToPtr(v.val, + T_ptr(T_tydesc(cx.fcx.ccx.tn)))); } // Otherwise, generate a tydesc if necessary, and return it. @@ -1107,7 +1159,7 @@ fn make_tydesc(@crate_ctxt cx, @ty.t t, vec[ast.def_id] typaram_defs) { auto drop_glue = make_generic_glue(cx, t, "drop", dg, typaram_defs); auto llty = type_of(cx, t); - auto glue_fn_ty = T_ptr(T_glue_fn()); + auto glue_fn_ty = T_ptr(T_glue_fn(cx.tn)); // FIXME: this adjustment has to do with the ridiculous encoding of // glue-pointer-constants in the tydesc records: They are tydesc-relative @@ -1120,8 +1172,9 @@ fn make_tydesc(@crate_ctxt cx, @ty.t t, vec[ast.def_id] typaram_defs) { } auto name = sanitize(cx.names.next("tydesc_" + ty.ty_to_str(t))); - auto gvar = llvm.LLVMAddGlobal(cx.llmod, T_tydesc(), _str.buf(name)); - auto tydesc = C_struct(vec(C_null(T_ptr(T_ptr(T_tydesc()))), + auto gvar = llvm.LLVMAddGlobal(cx.llmod, T_tydesc(cx.tn), + _str.buf(name)); + auto tydesc = C_struct(vec(C_null(T_ptr(T_ptr(T_tydesc(cx.tn)))), llsize_of(llty), llalign_of(llty), off(gvar, take_glue), // take_glue_off @@ -1142,7 +1195,7 @@ fn make_tydesc(@crate_ctxt cx, @ty.t t, vec[ast.def_id] typaram_defs) { fn make_generic_glue(@crate_ctxt cx, @ty.t t, str name, val_and_ty_fn helper, vec[ast.def_id] typaram_defs) -> ValueRef { - auto llfnty = T_glue_fn(); + auto llfnty = T_glue_fn(cx.tn); auto fn_name = cx.names.next("_rust_" + name) + sep() + ty.ty_to_str(t); fn_name = sanitize(fn_name); @@ -2793,7 +2846,8 @@ fn trans_bind(@block_ctxt cx, @ast.expr f, let @ty.t bindings_ty = plain_ty(ty.ty_tup(bound_tys)); let TypeRef lltarget_ty = type_of(bcx.fcx.ccx, ty.expr_ty(f)); let TypeRef llbindings_ty = type_of(bcx.fcx.ccx, bindings_ty); - let TypeRef llclosure_ty = T_closure_ptr(lltarget_ty, + let TypeRef llclosure_ty = T_closure_ptr(cx.fcx.ccx.tn, + lltarget_ty, llbindings_ty); // Malloc a box for the body. @@ -2854,9 +2908,11 @@ fn trans_bind(@block_ctxt cx, @ast.expr f, auto pair_box = bcx.build.GEP(pair_v, vec(C_int(0), C_int(abi.fn_field_box))); - bcx.build.Store(bcx.build.PointerCast(box, - T_opaque_closure_ptr()), - pair_box); + bcx.build.Store + (bcx.build.PointerCast + (box, + T_opaque_closure_ptr(bcx.fcx.ccx.tn)), + pair_box); find_scope_cx(cx).cleanups += clean(bind drop_slot(_, pair_v, pair_ty)); @@ -2903,7 +2959,8 @@ fn trans_args(@block_ctxt cx, } } if (ty.type_has_dynamic_size(retty)) { - llargs += bcx.build.PointerCast(llretslot, T_typaram_ptr()); + llargs += bcx.build.PointerCast(llretslot, + T_typaram_ptr(cx.fcx.ccx.tn)); } else if (ty.count_ty_params(retty) != 0u) { // It's possible that the callee has some generic-ness somewhere in // its return value -- say a method signature within an obj or a fn @@ -2979,7 +3036,8 @@ fn trans_args(@block_ctxt cx, } if (ty.type_has_dynamic_size(args.(i).ty)) { - val = bcx.build.PointerCast(val, T_typaram_ptr()); + val = bcx.build.PointerCast(val, + T_typaram_ptr(cx.fcx.ccx.tn)); } llargs += val; @@ -2993,7 +3051,7 @@ fn trans_call(@block_ctxt cx, @ast.expr f, vec[@ast.expr] args, &ast.ann ann) -> result { auto f_res = trans_lval(cx, f); auto faddr = f_res.res.val; - auto llenv = C_null(T_opaque_closure_ptr()); + auto llenv = C_null(T_opaque_closure_ptr(cx.fcx.ccx.tn)); alt (f_res.llobj) { case (some[ValueRef](_)) { @@ -3036,7 +3094,6 @@ fn trans_call(@block_ctxt cx, @ast.expr f, find_scope_cx(cx).cleanups += clean(bind drop_ty(_, retval, ret_ty)); } - // log "call-result type: " + val_str(retval); ret res(bcx, retval); } @@ -3767,7 +3824,7 @@ fn populate_fn_ctxt_from_llself(@block_ctxt cx, ValueRef llself) { } auto n_typarams = _vec.len[ast.ty_param](cx.fcx.ccx.obj_typarams); - let TypeRef llobj_box_ty = T_obj_ptr(n_typarams, + let TypeRef llobj_box_ty = T_obj_ptr(cx.fcx.ccx.tn, n_typarams, T_struct(llfield_tys)); auto box_cell = @@ -3925,7 +3982,7 @@ fn trans_obj(@crate_ctxt cx, &ast._obj ob, ast.def_id oid, C_int(abi.obj_field_box))); bcx.build.Store(vtbl, pair_vtbl); - let TypeRef llbox_ty = T_opaque_obj_ptr(); + let TypeRef llbox_ty = T_opaque_obj_ptr(cx.tn); if (_vec.len[ast.ty_param](ty_params) == 0u && _vec.len[ty.arg](arg_tys) == 0u) { @@ -4175,7 +4232,7 @@ fn decl_fn_and_pair(@crate_ctxt cx, let ValueRef gvar = llvm.LLVMAddGlobal(cx.llmod, llpairty, _str.buf(ps)); auto pair = C_struct(vec(llfn, - C_null(T_opaque_closure_ptr()))); + C_null(T_opaque_closure_ptr(cx.tn)))); llvm.LLVMSetInitializer(gvar, pair); llvm.LLVMSetGlobalConstant(gvar, True); @@ -4438,7 +4495,7 @@ fn trans_exit_task_glue(@crate_ctxt cx) { let ValueRef lltaskptr = llvm.LLVMGetParam(llfn, 0u); auto fcx = @rec(llfn=llfn, lltaskptr=lltaskptr, - llenv=C_null(T_opaque_closure_ptr()), + llenv=C_null(T_opaque_closure_ptr(cx.tn)), llretptr=C_null(T_ptr(T_nil())), mutable llself=none[ValueRef], mutable lliterbody=none[ValueRef], @@ -4454,9 +4511,9 @@ fn trans_exit_task_glue(@crate_ctxt cx) { } fn create_typedefs(@crate_ctxt cx) { - llvm.LLVMAddTypeName(cx.llmod, _str.buf("rust_crate"), T_crate()); - llvm.LLVMAddTypeName(cx.llmod, _str.buf("rust_task"), T_task()); - llvm.LLVMAddTypeName(cx.llmod, _str.buf("rust_tydesc"), T_tydesc()); + llvm.LLVMAddTypeName(cx.llmod, _str.buf("crate"), T_crate(cx.tn)); + llvm.LLVMAddTypeName(cx.llmod, _str.buf("task"), T_task(cx.tn)); + llvm.LLVMAddTypeName(cx.llmod, _str.buf("tydesc"), T_tydesc(cx.tn)); } fn create_crate_constant(@crate_ctxt cx) { @@ -4568,8 +4625,8 @@ fn check_module(ModuleRef llmod) { // TODO: run the linter here also, once there are llvm-c bindings for it. } -fn make_no_op_type_glue(ModuleRef llmod) -> ValueRef { - auto ty = T_fn(vec(T_taskptr(), T_ptr(T_i8())), T_void()); +fn make_no_op_type_glue(ModuleRef llmod, type_names tn) -> ValueRef { + auto ty = T_fn(vec(T_taskptr(tn), T_ptr(T_i8())), T_void()); auto fun = decl_fastcall_fn(llmod, abi.no_op_type_glue_name(), ty); auto bb_name = _str.buf("_rust_no_op_type_glue_bb"); auto llbb = llvm.LLVMAppendBasicBlock(fun, bb_name); @@ -4663,9 +4720,9 @@ fn make_bzero_glue(ModuleRef llmod) -> ValueRef { ret fun; } -fn make_glues(ModuleRef llmod) -> @glue_fns { - ret @rec(activate_glue = decl_glue(llmod, abi.activate_glue_name()), - yield_glue = decl_glue(llmod, abi.yield_glue_name()), +fn make_glues(ModuleRef llmod, type_names tn) -> @glue_fns { + ret @rec(activate_glue = decl_glue(llmod, tn, abi.activate_glue_name()), + yield_glue = decl_glue(llmod, tn, abi.yield_glue_name()), /* * Note: the signature passed to decl_cdecl_fn here looks unusual * because it is. It corresponds neither to an upcall signature @@ -4677,12 +4734,13 @@ fn make_glues(ModuleRef llmod) -> @glue_fns { * this is the signature required to retrieve it. */ exit_task_glue = decl_cdecl_fn(llmod, abi.exit_task_glue_name(), - T_fn(vec(T_taskptr()), T_void())), + T_fn(vec(T_taskptr(tn)), + T_void())), upcall_glues = - _vec.init_fn[ValueRef](bind decl_upcall_glue(llmod, _), + _vec.init_fn[ValueRef](bind decl_upcall_glue(llmod, tn, _), abi.n_upcall_glues as uint), - no_op_type_glue = make_no_op_type_glue(llmod), + no_op_type_glue = make_no_op_type_glue(llmod, tn), memcpy_glue = make_memcpy_glue(llmod), bzero_glue = make_bzero_glue(llmod)); } @@ -4696,14 +4754,15 @@ fn trans_crate(session.session sess, @ast.crate crate, str output, llvm.LLVMSetDataLayout(llmod, _str.buf(x86.get_data_layout())); llvm.LLVMSetTarget(llmod, _str.buf(x86.get_target_triple())); auto td = mk_target_data(x86.get_data_layout()); + auto tn = mk_type_names(); let ValueRef crate_ptr = - llvm.LLVMAddGlobal(llmod, T_crate(), _str.buf("rust_crate")); + llvm.LLVMAddGlobal(llmod, T_crate(tn), _str.buf("rust_crate")); llvm.LLVMSetModuleInlineAsm(llmod, _str.buf(x86.get_module_asm())); auto intrinsics = declare_intrinsics(llmod); - auto glues = make_glues(llmod); + auto glues = make_glues(llmod, tn); auto hasher = ty.hash_ty; auto eqer = ty.eq_ty; auto tydescs = map.mk_hashmap[@ty.t,ValueRef](hasher, eqer); @@ -4713,6 +4772,7 @@ fn trans_crate(session.session sess, @ast.crate crate, str output, auto cx = @rec(sess = sess, llmod = llmod, td = td, + tn = tn, crate_ptr = crate_ptr, upcalls = new_str_hash[ValueRef](), intrinsics = intrinsics, -- cgit v1.2.3 From 34c60b6edb810d9f142d248b27d8e6e34c95d63c Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Fri, 18 Feb 2011 17:30:57 -0800 Subject: Make a tag for iterness / fnness, teach many places about it. --- src/comp/middle/trans.rs | 102 ++++++++++++++++++++++++++++------------------- 1 file changed, 60 insertions(+), 42 deletions(-) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 538dfdbe..03d1fad9 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -449,8 +449,7 @@ fn type_of_explicit_args(@crate_ctxt cx, // - trans_args fn type_of_fn_full(@crate_ctxt cx, - // FIXME: change bool flag to tag - bool is_iter, + ast.proto proto, option.t[TypeRef] obj_self, vec[ty.arg] inputs, @ty.t output) -> TypeRef { @@ -480,7 +479,9 @@ fn type_of_fn_full(@crate_ctxt cx, // Args >3: ty params, if not acquired via capture... if (obj_self == none[TypeRef]) { auto ty_param_count = - ty.count_ty_params(plain_ty(ty.ty_fn(inputs, output))); + ty.count_ty_params(plain_ty(ty.ty_fn(proto, + inputs, + output))); auto i = 0u; while (i < ty_param_count) { atys += T_ptr(T_tydesc(cx.tn)); @@ -488,12 +489,12 @@ fn type_of_fn_full(@crate_ctxt cx, } } - if (is_iter) { + if (proto == ast.proto_iter) { // If it's an iter, the 'output' type of the iter is actually the // *input* type of the function we're given as our iter-block // argument. atys += T_fn_pair(cx.tn, - type_of_fn_full(cx, false, none[TypeRef], + type_of_fn_full(cx, ast.proto_fn, none[TypeRef], vec(rec(mode=ast.val, ty=output)), plain_ty(ty.ty_nil))); } @@ -505,10 +506,9 @@ fn type_of_fn_full(@crate_ctxt cx, } fn type_of_fn(@crate_ctxt cx, - // FIXME: change bool flag to tag - bool is_iter, + ast.proto proto, vec[ty.arg] inputs, @ty.t output) -> TypeRef { - ret type_of_fn_full(cx, is_iter, none[TypeRef], inputs, output); + ret type_of_fn_full(cx, proto, none[TypeRef], inputs, output); } fn type_of_native_fn(@crate_ctxt cx, vec[ty.arg] inputs, @@ -563,9 +563,8 @@ fn type_of_inner(@crate_ctxt cx, @ty.t t) -> TypeRef { } ret T_struct(tys); } - case (ty.ty_fn(?args, ?out)) { - // FIXME: put iter in ty_fn. - ret T_fn_pair(cx.tn, type_of_fn(cx, false, args, out)); + case (ty.ty_fn(?proto, ?args, ?out)) { + ret T_fn_pair(cx.tn, type_of_fn(cx, proto, args, out)); } case (ty.ty_native_fn(?args, ?out)) { ret T_fn_pair(cx.tn, type_of_native_fn(cx, args, out)); @@ -577,9 +576,7 @@ fn type_of_inner(@crate_ctxt cx, @ty.t t) -> TypeRef { let vec[TypeRef] mtys = vec(); for (ty.method m in meths) { let TypeRef mty = - type_of_fn_full(cx, - // FIXME: support method iters - false, + type_of_fn_full(cx, m.proto, some[TypeRef](self_ty), m.inputs, m.output); mtys += T_ptr(mty); @@ -1339,7 +1336,7 @@ fn make_drop_glue(@block_ctxt cx, ValueRef v, @ty.t t) -> result { T_int(), C_int(0)); } - case (ty.ty_fn(_,_)) { + case (ty.ty_fn(_,_,_)) { fn hit_zero(@block_ctxt cx, ValueRef v) -> result { // Call through the closure's own fields-drop glue first. @@ -1440,7 +1437,7 @@ fn decr_refcnt_and_if_zero(@block_ctxt cx, fn type_of_variant(@crate_ctxt cx, &ast.variant v) -> TypeRef { let vec[TypeRef] lltys = vec(); alt (ty.ann_to_type(v.ann).struct) { - case (ty.ty_fn(?args, _)) { + case (ty.ty_fn(_, ?args, _)) { for (ty.arg arg in args) { lltys += vec(type_of(cx, arg.ty)); } @@ -1547,7 +1544,7 @@ fn iter_structural_ty(@block_ctxt cx, auto fn_ty = ty.ann_to_type(variants.(i).ann); alt (fn_ty.struct) { - case (ty.ty_fn(?args, _)) { + case (ty.ty_fn(_, ?args, _)) { auto llvarp = variant_cx.build. TruncOrBitCast(llunion_ptr, T_ptr(llvarty)); @@ -1584,7 +1581,7 @@ fn iter_structural_ty(@block_ctxt cx, ret res(next_cx, C_nil()); } - case (ty.ty_fn(_,_)) { + case (ty.ty_fn(_,_,_)) { auto box_cell = cx.build.GEP(v, vec(C_int(0), @@ -2264,17 +2261,18 @@ fn trans_for_each(@block_ctxt cx, // pointer along with the foreach-body-fn pointer into a 'normal' fn pair // and pass it in as a first class fn-arg to the iterator. - auto foreach_llty = type_of_fn_full(cx.fcx.ccx, false, none[TypeRef], - vec(rec(mode=ast.val, ty=decl_ty)), - plain_ty(ty.ty_nil)); + auto iter_body_llty = type_of_fn_full(cx.fcx.ccx, ast.proto_fn, + none[TypeRef], + vec(rec(mode=ast.val, ty=decl_ty)), + plain_ty(ty.ty_nil)); - let ValueRef llforeach = decl_fastcall_fn(cx.fcx.ccx.llmod, - s, foreach_llty); + let ValueRef lliterbody = decl_fastcall_fn(cx.fcx.ccx.llmod, + s, iter_body_llty); // FIXME: handle ty params properly. let vec[ast.ty_param] ty_params = vec(); - auto fcx = new_fn_ctxt(cx.fcx.ccx, s, llforeach); + auto fcx = new_fn_ctxt(cx.fcx.ccx, s, lliterbody); auto bcx = new_top_block_ctxt(fcx); // FIXME: populate lllocals from llenv here. @@ -2282,13 +2280,16 @@ fn trans_for_each(@block_ctxt cx, res.bcx.build.RetVoid(); - // Step 3: Call iter passing [llforeach, llenv], plus other args. + // Step 3: Call iter passing [lliterbody, llenv], plus other args. alt (seq.node) { case (ast.expr_call(?f, ?args, ?ann)) { - // FIXME_ finish here by transferring to trans_call, - // suitably refactored. - cx.fcx.ccx.sess.unimpl("for each loop in trans"); + + // log "lliterbody: " + val_str(cx.fcx.ccx.tn, lliterbody); + ret trans_call(cx, f, + some[ValueRef](lliterbody), + args, + ann); } } fail; @@ -2933,6 +2934,7 @@ fn trans_args(@block_ctxt cx, ValueRef llenv, option.t[ValueRef] llobj, option.t[generic_info] gen, + option.t[ValueRef] lliterbody, &vec[@ast.expr] es, @ty.t fn_ty) -> tup(@block_ctxt, vec[ValueRef], ValueRef) { @@ -2993,6 +2995,14 @@ fn trans_args(@block_ctxt cx, // Args >3: ty_params ... llargs += lltydescs; + // ... then possibly an lliterbody argument. + alt (lliterbody) { + case (none[ValueRef]) {} + case (some[ValueRef](?lli)) { + llargs += lli; + } + } + // ... then explicit args. auto i = 0u; for (@ast.expr e in es) { @@ -3048,7 +3058,9 @@ fn trans_args(@block_ctxt cx, } fn trans_call(@block_ctxt cx, @ast.expr f, - vec[@ast.expr] args, &ast.ann ann) -> result { + option.t[ValueRef] lliterbody, + vec[@ast.expr] args, + &ast.ann ann) -> result { auto f_res = trans_lval(cx, f); auto faddr = f_res.res.val; auto llenv = C_null(T_opaque_closure_ptr(cx.fcx.ccx.tn)); @@ -3077,12 +3089,21 @@ fn trans_call(@block_ctxt cx, @ast.expr f, auto args_res = trans_args(f_res.res.bcx, llenv, f_res.llobj, f_res.generic, + lliterbody, args, fn_ty); auto bcx = args_res._0; auto llargs = args_res._1; auto llretslot = args_res._2; + /* + log "calling: " + val_str(cx.fcx.ccx.tn, faddr); + + for (ValueRef arg in llargs) { + log "arg: " + val_str(cx.fcx.ccx.tn, arg); + } + */ + bcx.build.FastCall(faddr, llargs); auto retval = C_nil(); @@ -3308,7 +3329,7 @@ fn trans_expr(@block_ctxt cx, @ast.expr e) -> result { } case (ast.expr_call(?f, ?args, ?ann)) { - ret trans_call(cx, f, args, ann); + ret trans_call(cx, f, none[ValueRef], args, ann); } case (ast.expr_cast(?e, _, ?ann)) { @@ -3707,8 +3728,7 @@ fn new_fn_ctxt(@crate_ctxt cx, // - trans_args fn create_llargs_for_fn_args(&@fn_ctxt cx, - // FIXME: change bool flag to tag - bool is_iter, + ast.proto proto, option.t[TypeRef] ty_self, @ty.t ret_ty, &vec[ast.arg] args, @@ -3733,7 +3753,7 @@ fn create_llargs_for_fn_args(&@fn_ctxt cx, } } - if (is_iter) { + if (proto == ast.proto_iter) { auto llarg = llvm.LLVMGetParam(cx.llfn, arg_n); check (llarg as int != 0); cx.lliterbody = some[ValueRef](llarg); @@ -3794,7 +3814,7 @@ fn is_terminated(@block_ctxt cx) -> bool { fn arg_tys_of_fn(ast.ann ann) -> vec[ty.arg] { alt (ty.ann_to_type(ann).struct) { - case (ty.ty_fn(?arg_tys, _)) { + case (ty.ty_fn(_, ?arg_tys, _)) { ret arg_tys; } } @@ -3803,7 +3823,7 @@ fn arg_tys_of_fn(ast.ann ann) -> vec[ty.arg] { fn ret_ty_of_fn_ty(@ty.t t) -> @ty.t { alt (t.struct) { - case (ty.ty_fn(_, ?ret_ty)) { + case (ty.ty_fn(_, _, ?ret_ty)) { ret ret_ty; } } @@ -3875,7 +3895,7 @@ fn trans_fn(@crate_ctxt cx, &ast._fn f, ast.def_id fid, cx.item_names.insert(cx.path, llfndecl); auto fcx = new_fn_ctxt(cx, cx.path, llfndecl); - create_llargs_for_fn_args(fcx, f.is_iter, + create_llargs_for_fn_args(fcx, f.decl.proto, ty_self, ret_ty_of_fn(ann), f.decl.inputs, ty_params); auto bcx = new_top_block_ctxt(fcx); @@ -3915,10 +3935,8 @@ fn trans_vtbl(@crate_ctxt cx, TypeRef self_ty, auto llfnty = T_nil(); alt (node_ann_type(cx, m.node.ann).struct) { - case (ty.ty_fn(?inputs, ?output)) { - llfnty = type_of_fn_full(cx, - // FIXME: support method iters. - false, + case (ty.ty_fn(?proto, ?inputs, ?output)) { + llfnty = type_of_fn_full(cx, proto, some[TypeRef](self_ty), inputs, output); } @@ -3962,7 +3980,7 @@ fn trans_obj(@crate_ctxt cx, &ast._obj ob, ast.def_id oid, } auto fcx = new_fn_ctxt(cx, cx.path, llctor_decl); - create_llargs_for_fn_args(fcx, false, + create_llargs_for_fn_args(fcx, ast.proto_fn, none[TypeRef], ret_ty_of_fn(ann), fn_args, ty_params); @@ -4091,7 +4109,7 @@ fn trans_tag_variant(@crate_ctxt cx, ast.def_id tag_id, let ValueRef llfndecl = cx.item_ids.get(variant.id); auto fcx = new_fn_ctxt(cx, cx.path, llfndecl); - create_llargs_for_fn_args(fcx, false, + create_llargs_for_fn_args(fcx, ast.proto_fn, none[TypeRef], ret_ty_of_fn(variant.ann), fn_args, ty_params); -- cgit v1.2.3 From 80c67268fc007d55fa0ff193ac0be6ab83640aa6 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Fri, 18 Feb 2011 18:04:37 -0800 Subject: Pass correct lliterbody; can compile and run no-put iters. --- src/comp/middle/trans.rs | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 03d1fad9..59d6ad7f 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -2238,7 +2238,7 @@ fn trans_for_each(@block_ctxt cx, // escape. This could be determined upstream, and probably ought // to be so, eventualy. For first cut, skip this. Null env. - auto env_ty = T_struct(vec(T_ptr(T_i8()))); + auto env_ty = T_opaque_closure_ptr(cx.fcx.ccx.tn); // Step 2: Declare foreach body function. @@ -2283,11 +2283,19 @@ fn trans_for_each(@block_ctxt cx, // Step 3: Call iter passing [lliterbody, llenv], plus other args. alt (seq.node) { + case (ast.expr_call(?f, ?args, ?ann)) { + auto pair = cx.build.Alloca(T_fn_pair(cx.fcx.ccx.tn, + iter_body_llty)); + auto code_cell = cx.build.GEP(pair, + vec(C_int(0), + C_int(abi.fn_field_code))); + cx.build.Store(lliterbody, code_cell); + // log "lliterbody: " + val_str(cx.fcx.ccx.tn, lliterbody); ret trans_call(cx, f, - some[ValueRef](lliterbody), + some[ValueRef](cx.build.Load(pair)), args, ann); } @@ -3364,7 +3372,7 @@ fn trans_expr(@block_ctxt cx, @ast.expr e) -> result { ret trans_ret(cx, e); } - case (ast.expr_ret(?e)) { + case (ast.expr_put(?e)) { ret trans_put(cx, e); } -- cgit v1.2.3 From b0c7439d777bbb967be7a67fa11096aaf540fe9f Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Fri, 18 Feb 2011 18:52:16 -0800 Subject: Implement expr_put. Un-XFAIL foreach-simple.rs; iters w/o env access work. --- src/comp/middle/trans.rs | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 59d6ad7f..efa3a41d 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -3454,8 +3454,35 @@ fn trans_fail(@block_ctxt cx, common.span sp, str fail_str) -> result { } fn trans_put(@block_ctxt cx, &option.t[@ast.expr] e) -> result { - cx.fcx.ccx.sess.unimpl("put expr"); - fail; + auto llcallee = C_nil(); + auto llenv = C_nil(); + + alt (cx.fcx.lliterbody) { + case (some[ValueRef](?lli)) { + auto slot = cx.build.Alloca(val_ty(lli)); + cx.build.Store(lli, slot); + + llcallee = cx.build.GEP(slot, vec(C_int(0), + C_int(abi.fn_field_code))); + llcallee = cx.build.Load(llcallee); + + llenv = cx.build.GEP(slot, vec(C_int(0), + C_int(abi.fn_field_box))); + llenv = cx.build.Load(llenv); + } + } + auto bcx = cx; + auto dummy_retslot = bcx.build.Alloca(T_nil()); + let vec[ValueRef] llargs = vec(dummy_retslot, cx.fcx.lltaskptr, llenv); + alt (e) { + case (none[@ast.expr]) { } + case (some[@ast.expr](?x)) { + auto r = trans_expr(bcx, x); + llargs += r.val; + bcx = r.bcx; + } + } + ret res(bcx, bcx.build.FastCall(llcallee, llargs)); } fn trans_ret(@block_ctxt cx, &option.t[@ast.expr] e) -> result { -- cgit v1.2.3 From 60f97aa9cc73ee4e0b57abc07dc543c8fa823ee2 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Mon, 21 Feb 2011 17:42:23 -0800 Subject: Find main functions buried within modules. Un-XFAIL import.rs. --- src/comp/middle/trans.rs | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index efa3a41d..35fefc10 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -4602,6 +4602,30 @@ fn create_crate_constant(@crate_ctxt cx) { llvm.LLVMSetInitializer(cx.crate_ptr, crate_val); } +fn find_main_fn(@crate_ctxt cx) -> ValueRef { + auto e = sep() + "main"; + let ValueRef v = C_nil(); + let uint n = 0u; + for each (tup(str,ValueRef) i in cx.item_names.items()) { + if (_str.ends_with(i._0, e)) { + n += 1u; + v = i._1; + } + } + alt (n) { + case (0u) { + cx.sess.err("main fn not found"); + } + case (1u) { + ret v; + } + case (_) { + cx.sess.err("multiple main fns found"); + } + } + fail; +} + fn trans_main_fn(@crate_ctxt cx, ValueRef llcrate) { auto T_main_args = vec(T_int(), T_int()); auto T_rust_start_args = vec(T_int(), T_int(), T_int(), T_int()); @@ -4621,8 +4645,7 @@ fn trans_main_fn(@crate_ctxt cx, ValueRef llcrate) { auto llargc = llvm.LLVMGetParam(llmain, 0u); auto llargv = llvm.LLVMGetParam(llmain, 1u); - check (cx.item_names.contains_key("_rust" + sep() + "main")); - auto llrust_main = cx.item_names.get("_rust" + sep() + "main"); + auto llrust_main = find_main_fn(cx); // // Emit the moral equivalent of: -- cgit v1.2.3 From b389611ce772d65ed135d6e52fecb9ca2238e902 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20=C3=81vila=20de=20Esp=C3=ADndola?= Date: Tue, 22 Feb 2011 17:37:11 -0500 Subject: Finish the type of native functions. We now get declare i32 @write(i32, i8*, i32) --- src/comp/middle/trans.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 35fefc10..9da7e009 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -514,7 +514,7 @@ fn type_of_fn(@crate_ctxt cx, fn type_of_native_fn(@crate_ctxt cx, vec[ty.arg] inputs, @ty.t output) -> TypeRef { let vec[TypeRef] atys = type_of_explicit_args(cx, inputs); - ret T_fn(atys, llvm.LLVMVoidType()); + ret T_fn(atys, type_of(cx, output)); } fn type_of_inner(@crate_ctxt cx, @ty.t t) -> TypeRef { @@ -4305,7 +4305,7 @@ fn decl_native_fn_and_pair(@crate_ctxt cx, auto llpairty = node_type(cx, ann); auto llfty = get_pair_fn_ty(llpairty); - let ValueRef llfn = decl_fastcall_fn(cx.llmod, name, llfty); + let ValueRef llfn = decl_cdecl_fn(cx.llmod, name, llfty); cx.item_ids.insert(id, llfn); } -- cgit v1.2.3 From af4d6ae76b05d4edb9d7074b971600a447c9c9a4 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Tue, 22 Feb 2011 16:37:01 -0800 Subject: Add ABI tagging to crates, adjust rustc output and runtime stack-frame setup so access to argv works. --- src/comp/middle/trans.rs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 9da7e009..4a672f49 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -345,7 +345,8 @@ fn T_crate(type_names tn) -> TypeRef { T_int(), // size_t main_exit_task_glue_off T_int(), // int n_rust_syms T_int(), // int n_c_syms - T_int() // int n_libs + T_int(), // int n_libs + T_int() // uintptr_t abi_tag )); tn.associate(s, t); ret t; @@ -4545,7 +4546,7 @@ fn trans_exit_task_glue(@crate_ctxt cx) { let vec[ValueRef] V_args = vec(); auto llfn = cx.glues.exit_task_glue; - let ValueRef lltaskptr = llvm.LLVMGetParam(llfn, 0u); + let ValueRef lltaskptr = llvm.LLVMGetParam(llfn, 3u); auto fcx = @rec(llfn=llfn, lltaskptr=lltaskptr, llenv=C_null(T_opaque_closure_ptr(cx.tn)), @@ -4596,7 +4597,8 @@ fn create_crate_constant(@crate_ctxt cx) { exit_task_glue_off, // size_t main_exit_task_glue_off C_null(T_int()), // int n_rust_syms C_null(T_int()), // int n_c_syms - C_null(T_int()) // int n_libs + C_null(T_int()), // int n_libs + C_int(abi.abi_x86_rustc_fastcall) // uintptr_t abi_tag )); llvm.LLVMSetInitializer(cx.crate_ptr, crate_val); @@ -4810,7 +4812,10 @@ fn make_glues(ModuleRef llmod, type_names tn) -> @glue_fns { * this is the signature required to retrieve it. */ exit_task_glue = decl_cdecl_fn(llmod, abi.exit_task_glue_name(), - T_fn(vec(T_taskptr(tn)), + T_fn(vec(T_int(), + T_int(), + T_int(), + T_taskptr(tn)), T_void())), upcall_glues = -- cgit v1.2.3 From d7f7634c955deaf55cf11071d5e92300a059be61 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Tue, 22 Feb 2011 18:07:47 -0800 Subject: Drop for-loop temporary at end of scope, fixes memory leak. --- src/comp/middle/trans.rs | 1 + 1 file changed, 1 insertion(+) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 4a672f49..6a19a6e5 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -2189,6 +2189,7 @@ fn trans_for(@block_ctxt cx, cx.build.Br(scope_cx.llbb); auto local_res = alloc_local(scope_cx, local); auto bcx = copy_ty(local_res.bcx, INIT, local_res.val, curr, t).bcx; + scope_cx.cleanups += clean(bind drop_slot(_, local_res.val, t)); bcx = trans_block(bcx, body).bcx; bcx.build.Br(next_cx.llbb); ret res(next_cx, C_nil()); -- cgit v1.2.3 From b4d6589e7387a7c7df0841f51f0fa5ef831883d9 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Wed, 23 Feb 2011 10:58:43 -0800 Subject: Implement type descriptor binding. Un-XFAIL test/run-pass/generic-bind.rs. --- src/comp/middle/trans.rs | 115 +++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 96 insertions(+), 19 deletions(-) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 6a19a6e5..30f3cdc4 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -373,11 +373,12 @@ fn T_typaram_ptr(type_names tn) -> TypeRef { fn T_closure_ptr(type_names tn, TypeRef lltarget_ty, - TypeRef llbindings_ty) -> TypeRef { + TypeRef llbindings_ty, + uint n_ty_params) -> TypeRef { ret T_ptr(T_box(T_struct(vec(T_ptr(T_tydesc(tn)), lltarget_ty, - llbindings_ty) - // FIXME: add captured typarams. + llbindings_ty, + T_captured_tydescs(tn, n_ty_params)) ))); } @@ -388,7 +389,8 @@ fn T_opaque_closure_ptr(type_names tn) -> TypeRef { } auto t = T_closure_ptr(tn, T_struct(vec(T_ptr(T_nil()), T_ptr(T_nil()))), - T_nil()); + T_nil(), + 0u); tn.associate(s, t); ret t; } @@ -2747,7 +2749,8 @@ fn trans_bind_thunk(@crate_ctxt cx, @ty.t outgoing_fty, vec[option.t[@ast.expr]] args, TypeRef llclosure_ty, - vec[@ty.t] bound_tys) -> ValueRef { + vec[@ty.t] bound_tys, + uint ty_param_count) -> ValueRef { // Construct a thunk-call with signature incoming_fty, and that copies // args forward into a call to outgoing_fty. @@ -2755,9 +2758,6 @@ fn trans_bind_thunk(@crate_ctxt cx, let TypeRef llthunk_ty = get_pair_fn_ty(type_of(cx, incoming_fty)); let ValueRef llthunk = decl_fastcall_fn(cx.llmod, s, llthunk_ty); - // FIXME: handle ty params properly. - let vec[ast.ty_param] ty_params = vec(); - auto fcx = new_fn_ctxt(cx, s, llthunk); auto bcx = new_top_block_ctxt(fcx); @@ -2779,11 +2779,33 @@ fn trans_bind_thunk(@crate_ctxt cx, vec(C_int(0), C_int(abi.fn_field_box))); lltargetclosure = bcx.build.Load(lltargetclosure); - let vec[ValueRef] llargs = vec(fcx.llretptr, + + auto outgoing_ret_ty = ty.ty_fn_ret(outgoing_fty); + auto outgoing_arg_tys = ty.ty_fn_args(outgoing_fty); + + auto llretptr = fcx.llretptr; + if (ty.type_has_dynamic_size(outgoing_ret_ty)) { + llretptr = bcx.build.PointerCast(llretptr, T_typaram_ptr(cx.tn)); + } + + let vec[ValueRef] llargs = vec(llretptr, fcx.lltaskptr, lltargetclosure); - let uint a = 0u; + + // Copy in the type parameters. + let uint i = 0u; + while (i < ty_param_count) { + auto lltyparam_ptr = + bcx.build.GEP(llbody, vec(C_int(0), + C_int(abi.closure_elt_ty_params), + C_int(i as int))); + llargs += vec(bcx.build.Load(lltyparam_ptr)); + i += 1u; + } + + let uint a = 2u + i; // retptr, task ptr, env come first let int b = 0; + let uint outgoing_arg_index = 0u; for (option.t[@ast.expr] arg in args) { alt (arg) { @@ -2800,10 +2822,19 @@ fn trans_bind_thunk(@crate_ctxt cx, // Arg will be provided when the thunk is invoked. case (none[@ast.expr]) { let ValueRef passed_arg = llvm.LLVMGetParam(llthunk, a); + if (ty.type_has_dynamic_size(outgoing_arg_tys. + (outgoing_arg_index).ty)) { + // Cast to a generic typaram pointer in order to make a + // type-compatible call. + passed_arg = bcx.build.PointerCast(passed_arg, + T_typaram_ptr(cx.tn)); + } llargs += passed_arg; a += 1u; } } + + outgoing_arg_index += 0u; } // FIXME: turn this call + ret into a tail call. @@ -2811,6 +2842,7 @@ fn trans_bind_thunk(@crate_ctxt cx, vec(C_int(0), C_int(abi.fn_field_code))); lltargetfn = bcx.build.Load(lltargetfn); + auto r = bcx.build.FastCall(lltargetfn, llargs); bcx.build.RetVoid(); @@ -2835,7 +2867,23 @@ fn trans_bind(@block_ctxt cx, @ast.expr f, } } } - if (_vec.len[@ast.expr](bound) == 0u) { + + // Figure out which tydescs we need to pass, if any. + // FIXME: typestate botch + let @ty.t outgoing_fty = ty.plain_ty(ty.ty_nil); + let vec[ValueRef] lltydescs = vec(); + alt (f_res.generic) { + case (none[generic_info]) { + outgoing_fty = ty.expr_ty(f); + } + case (some[generic_info](?ginfo)) { + outgoing_fty = ginfo.item_type; + lltydescs = ginfo.tydescs; + } + } + auto ty_param_count = _vec.len[ValueRef](lltydescs); + + if (_vec.len[@ast.expr](bound) == 0u && ty_param_count == 0u) { // Trivial 'binding': just return the static pair-ptr. ret f_res.res; } else { @@ -2846,20 +2894,27 @@ fn trans_bind(@block_ctxt cx, @ast.expr f, // Translate the bound expressions. let vec[@ty.t] bound_tys = vec(); let vec[ValueRef] bound_vals = vec(); + auto i = 0u; for (@ast.expr e in bound) { auto arg = trans_expr(bcx, e); bcx = arg.bcx; + append[ValueRef](bound_vals, arg.val); append[@ty.t](bound_tys, ty.expr_ty(e)); + + i += 1u; } + // Get the type of the bound function. + let TypeRef lltarget_ty = type_of(bcx.fcx.ccx, outgoing_fty); + // Synthesize a closure type. let @ty.t bindings_ty = plain_ty(ty.ty_tup(bound_tys)); - let TypeRef lltarget_ty = type_of(bcx.fcx.ccx, ty.expr_ty(f)); let TypeRef llbindings_ty = type_of(bcx.fcx.ccx, bindings_ty); let TypeRef llclosure_ty = T_closure_ptr(cx.fcx.ccx.tn, lltarget_ty, - llbindings_ty); + llbindings_ty, + ty_param_count); // Malloc a box for the body. auto r = trans_malloc_inner(bcx, llclosure_ty); @@ -2888,19 +2943,40 @@ fn trans_bind(@block_ctxt cx, @ast.expr f, bcx.build.GEP(closure, vec(C_int(0), C_int(abi.closure_elt_target))); - bcx.build.Store(bcx.build.Load(f_res.res.val), bound_target); + auto src = bcx.build.Load(f_res.res.val); + bcx.build.Store(src, bound_target); // Copy expr values into boxed bindings. - let int i = 0; + i = 0u; auto bindings = bcx.build.GEP(closure, vec(C_int(0), C_int(abi.closure_elt_bindings))); for (ValueRef v in bound_vals) { auto bound = bcx.build.GEP(bindings, - vec(C_int(0),C_int(i))); + vec(C_int(0), C_int(i as int))); bcx = copy_ty(r.bcx, INIT, bound, v, bound_tys.(i)).bcx; - i += 1; + i += 1u; + } + + // If necessary, copy tydescs describing type parameters into the + // appropriate slot in the closure. + alt (f_res.generic) { + case (none[generic_info]) { /* nothing to do */ } + case (some[generic_info](?ginfo)) { + auto ty_params_slot = + bcx.build.GEP(closure, + vec(C_int(0), + C_int(abi.closure_elt_ty_params))); + auto i = 0; + for (ValueRef td in ginfo.tydescs) { + auto ty_param_slot = bcx.build.GEP(ty_params_slot, + vec(C_int(0), + C_int(i))); + bcx.build.Store(td, ty_param_slot); + i += 1; + } + } } // Make thunk and store thunk-ptr in outer pair's code slot. @@ -2910,8 +2986,9 @@ fn trans_bind(@block_ctxt cx, @ast.expr f, let @ty.t pair_ty = node_ann_type(cx.fcx.ccx, ann); let ValueRef llthunk = - trans_bind_thunk(cx.fcx.ccx, pair_ty, ty.expr_ty(f), - args, llclosure_ty, bound_tys); + trans_bind_thunk(cx.fcx.ccx, pair_ty, outgoing_fty, + args, llclosure_ty, bound_tys, + ty_param_count); bcx.build.Store(llthunk, pair_code); -- cgit v1.2.3 From 0a65283c5eeae0b98fff7d213dbaad59889e677e Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Wed, 23 Feb 2011 18:39:27 -0800 Subject: Cast more aggressively to the callee type when calling generic functions. Add a test-case for this, and XFAIL it in rustboot. --- src/comp/middle/trans.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 30f3cdc4..72f1106b 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -3132,9 +3132,9 @@ fn trans_args(@block_ctxt cx, bcx = re.bcx; } - if (ty.type_has_dynamic_size(args.(i).ty)) { - val = bcx.build.PointerCast(val, - T_typaram_ptr(cx.fcx.ccx.tn)); + if (ty.count_ty_params(args.(i).ty) > 0u) { + auto lldestty = type_of(cx.fcx.ccx, args.(i).ty); + val = bcx.build.PointerCast(val, lldestty); } llargs += val; -- cgit v1.2.3 From 5332250d3bddf509994832965f3c5d7b68662ce4 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Thu, 24 Feb 2011 13:51:18 -0800 Subject: Revert "Cast more aggressively to the callee type when calling generic functions. Add a test-case for this, and XFAIL it in rustboot." due to test failures This reverts commit 0a65283c5eeae0b98fff7d213dbaad59889e677e. --- src/comp/middle/trans.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 72f1106b..30f3cdc4 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -3132,9 +3132,9 @@ fn trans_args(@block_ctxt cx, bcx = re.bcx; } - if (ty.count_ty_params(args.(i).ty) > 0u) { - auto lldestty = type_of(cx.fcx.ccx, args.(i).ty); - val = bcx.build.PointerCast(val, lldestty); + if (ty.type_has_dynamic_size(args.(i).ty)) { + val = bcx.build.PointerCast(val, + T_typaram_ptr(cx.fcx.ccx.tn)); } llargs += val; -- cgit v1.2.3 From dcd65fac199d3caac4b1019304ef5e1b480f31ff Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Thu, 24 Feb 2011 13:51:53 -0800 Subject: Cast more aggressively to the callee type when calling generic functions. Add a test-case for this, and XFAIL it in rustboot. --- src/comp/middle/trans.rs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 30f3cdc4..a3a1d83f 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -3091,6 +3091,12 @@ fn trans_args(@block_ctxt cx, } // ... then explicit args. + + // First we figure out the caller's view of the types of the arguments. + // This will be needed if this is a generic call, because the callee has + // to cast her view of the arguments to the caller's view. + auto arg_tys = type_of_explicit_args(cx.fcx.ccx, args); + auto i = 0u; for (@ast.expr e in es) { auto mode = args.(i).mode; @@ -3132,9 +3138,9 @@ fn trans_args(@block_ctxt cx, bcx = re.bcx; } - if (ty.type_has_dynamic_size(args.(i).ty)) { - val = bcx.build.PointerCast(val, - T_typaram_ptr(cx.fcx.ccx.tn)); + if (ty.count_ty_params(args.(i).ty) > 0u) { + auto lldestty = arg_tys.(i); + val = bcx.build.PointerCast(val, lldestty); } llargs += val; -- cgit v1.2.3 From 19b2850388f634b500e612d8f24bbcb8c0fa2f3c Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Thu, 24 Feb 2011 19:24:12 -0800 Subject: rustc: Perform type parameter substitutions when emitting glue for generic tags. Un-XFAIL generic-tag.rs. --- src/comp/middle/trans.rs | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index a3a1d83f..467aaa0d 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -1,3 +1,4 @@ +import std._int; import std._str; import std._uint; import std._vec; @@ -61,7 +62,8 @@ type glue_fns = rec(ValueRef activate_glue, tag arity { nullary; n_ary; } type tag_info = rec(type_handle th, mutable vec[tup(ast.def_id,arity)] variants, - mutable uint size); + mutable uint size, + vec[ast.ty_param] ty_params); state type crate_ctxt = rec(session.session sess, ModuleRef llmod, @@ -1498,9 +1500,7 @@ fn iter_structural_ty(@block_ctxt cx, i += 1; } } - case (ty.ty_tag(?tid, _)) { - // TODO: type params! - + case (ty.ty_tag(?tid, ?tps)) { check (cx.fcx.ccx.tags.contains_key(tid)); auto info = cx.fcx.ccx.tags.get(tid); auto n_variants = _vec.len[tup(ast.def_id,arity)](info.variants); @@ -1559,11 +1559,15 @@ fn iter_structural_ty(@block_ctxt cx, auto llfldp = variant_cx.build.GEP(llvarp, v); + auto ty_subst = ty.substitute_ty_params( + info.ty_params, tps, a.ty); + auto llfld = load_scalar_or_boxed(variant_cx, - llfldp, a.ty); + llfldp, + ty_subst); - auto res = f(variant_cx, llfld, a.ty); + auto res = f(variant_cx, llfld, ty_subst); variant_cx = res.bcx; j += 1u; } @@ -4433,13 +4437,14 @@ fn collect_item(&@crate_ctxt cx, @ast.item i) -> @crate_ctxt { cx.items.insert(mid, i); } - case (ast.item_tag(_, ?variants, _, ?tag_id)) { + case (ast.item_tag(_, ?variants, ?tps, ?tag_id)) { auto vi = new_def_hash[uint](); auto navi = new_def_hash[uint](); let vec[tup(ast.def_id,arity)] variant_info = vec(); cx.tags.insert(tag_id, @rec(th=mk_type_handle(), mutable variants=variant_info, - mutable size=0u)); + mutable size=0u, + ty_params=tps)); cx.items.insert(tag_id, i); } -- cgit v1.2.3 From f8f6f078c505dd0f20526e3ad86c360605fce109 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20=C3=81vila=20de=20Esp=C3=ADndola?= Date: Fri, 25 Feb 2011 12:08:21 -0500 Subject: There are no native iterators (or at least they are not going to be supported soon.). --- src/comp/middle/trans.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 467aaa0d..33693835 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -4019,7 +4019,7 @@ fn trans_fn(@crate_ctxt cx, &ast._fn f, ast.def_id fid, cx.item_names.insert(cx.path, llfndecl); auto fcx = new_fn_ctxt(cx, cx.path, llfndecl); - create_llargs_for_fn_args(fcx, f.decl.proto, + create_llargs_for_fn_args(fcx, f.proto, ty_self, ret_ty_of_fn(ann), f.decl.inputs, ty_params); auto bcx = new_top_block_ctxt(fcx); -- cgit v1.2.3 From 081c3aa76dd0805767e0233c0cc6ccf313cf44ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20=C3=81vila=20de=20Esp=C3=ADndola?= Date: Fri, 25 Feb 2011 15:58:08 -0500 Subject: Pass the abi of native functions all the way to codegen. --- src/comp/middle/trans.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 33693835..d175432d 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -516,7 +516,8 @@ fn type_of_fn(@crate_ctxt cx, ret type_of_fn_full(cx, proto, none[TypeRef], inputs, output); } -fn type_of_native_fn(@crate_ctxt cx, vec[ty.arg] inputs, +fn type_of_native_fn(@crate_ctxt cx, ast.native_abi abi, + vec[ty.arg] inputs, @ty.t output) -> TypeRef { let vec[TypeRef] atys = type_of_explicit_args(cx, inputs); ret T_fn(atys, type_of(cx, output)); @@ -571,8 +572,8 @@ fn type_of_inner(@crate_ctxt cx, @ty.t t) -> TypeRef { case (ty.ty_fn(?proto, ?args, ?out)) { ret T_fn_pair(cx.tn, type_of_fn(cx, proto, args, out)); } - case (ty.ty_native_fn(?args, ?out)) { - ret T_fn_pair(cx.tn, type_of_native_fn(cx, args, out)); + case (ty.ty_native_fn(?abi, ?args, ?out)) { + ret T_fn_pair(cx.tn, type_of_native_fn(cx, abi, args, out)); } case (ty.ty_obj(?meths)) { auto th = mk_type_handle(); -- cgit v1.2.3 From 2cd7fbbdf1edf84d962c62e9990acc0906998413 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Fri, 25 Feb 2011 16:24:19 -0800 Subject: rustc: Move all of the logic in type_of() to type_of_inner() --- src/comp/middle/trans.rs | 78 +++++++++++++++++++++++++----------------------- 1 file changed, 40 insertions(+), 38 deletions(-) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index d175432d..29ff9d6e 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -419,10 +419,7 @@ fn T_opaque_obj_ptr(type_names tn) -> TypeRef { fn type_of(@crate_ctxt cx, @ty.t t) -> TypeRef { - let TypeRef llty = type_of_inner(cx, t); - check (llty as int != 0); - llvm.LLVMAddTypeName(cx.llmod, _str.buf(ty.ty_to_str(t)), llty); - ret llty; + ret type_of_inner(cx, t); } fn type_of_explicit_args(@crate_ctxt cx, @@ -433,7 +430,7 @@ fn type_of_explicit_args(@crate_ctxt cx, check (arg.mode == ast.alias); atys += T_typaram_ptr(cx.tn); } else { - let TypeRef t = type_of(cx, arg.ty); + let TypeRef t = type_of_inner(cx, arg.ty); alt (arg.mode) { case (ast.alias) { t = T_ptr(t); @@ -464,7 +461,7 @@ fn type_of_fn_full(@crate_ctxt cx, if (ty.type_has_dynamic_size(output)) { atys += T_typaram_ptr(cx.tn); } else { - atys += T_ptr(type_of(cx, output)); + atys += T_ptr(type_of_inner(cx, output)); } // Arg 1: Task pointer. @@ -520,60 +517,62 @@ fn type_of_native_fn(@crate_ctxt cx, ast.native_abi abi, vec[ty.arg] inputs, @ty.t output) -> TypeRef { let vec[TypeRef] atys = type_of_explicit_args(cx, inputs); - ret T_fn(atys, type_of(cx, output)); + ret T_fn(atys, type_of_inner(cx, output)); } fn type_of_inner(@crate_ctxt cx, @ty.t t) -> TypeRef { + let TypeRef llty = 0 as TypeRef; + alt (t.struct) { - case (ty.ty_native) { ret T_ptr(T_i8()); } - case (ty.ty_nil) { ret T_nil(); } - case (ty.ty_bool) { ret T_bool(); } - case (ty.ty_int) { ret T_int(); } - case (ty.ty_uint) { ret T_int(); } + case (ty.ty_native) { llty = T_ptr(T_i8()); } + case (ty.ty_nil) { llty = T_nil(); } + case (ty.ty_bool) { llty = T_bool(); } + case (ty.ty_int) { llty = T_int(); } + case (ty.ty_uint) { llty = T_int(); } case (ty.ty_machine(?tm)) { alt (tm) { - case (common.ty_i8) { ret T_i8(); } - case (common.ty_u8) { ret T_i8(); } - case (common.ty_i16) { ret T_i16(); } - case (common.ty_u16) { ret T_i16(); } - case (common.ty_i32) { ret T_i32(); } - case (common.ty_u32) { ret T_i32(); } - case (common.ty_i64) { ret T_i64(); } - case (common.ty_u64) { ret T_i64(); } - case (common.ty_f32) { ret T_f32(); } - case (common.ty_f64) { ret T_f64(); } + case (common.ty_i8) { llty = T_i8(); } + case (common.ty_u8) { llty = T_i8(); } + case (common.ty_i16) { llty = T_i16(); } + case (common.ty_u16) { llty = T_i16(); } + case (common.ty_i32) { llty = T_i32(); } + case (common.ty_u32) { llty = T_i32(); } + case (common.ty_i64) { llty = T_i64(); } + case (common.ty_u64) { llty = T_i64(); } + case (common.ty_f32) { llty = T_f32(); } + case (common.ty_f64) { llty = T_f64(); } } } - case (ty.ty_char) { ret T_char(); } - case (ty.ty_str) { ret T_ptr(T_str()); } + case (ty.ty_char) { llty = T_char(); } + case (ty.ty_str) { llty = T_ptr(T_str()); } case (ty.ty_tag(?tag_id, _)) { - ret llvm.LLVMResolveTypeHandle(cx.tags.get(tag_id).th.llth); + llty = llvm.LLVMResolveTypeHandle(cx.tags.get(tag_id).th.llth); } case (ty.ty_box(?t)) { - ret T_ptr(T_box(type_of(cx, t))); + llty = T_ptr(T_box(type_of_inner(cx, t))); } case (ty.ty_vec(?t)) { - ret T_ptr(T_vec(type_of(cx, t))); + llty = T_ptr(T_vec(type_of_inner(cx, t))); } case (ty.ty_tup(?elts)) { let vec[TypeRef] tys = vec(); for (@ty.t elt in elts) { - tys += type_of(cx, elt); + tys += type_of_inner(cx, elt); } - ret T_struct(tys); + llty = T_struct(tys); } case (ty.ty_rec(?fields)) { let vec[TypeRef] tys = vec(); for (ty.field f in fields) { - tys += type_of(cx, f.ty); + tys += type_of_inner(cx, f.ty); } - ret T_struct(tys); + llty = T_struct(tys); } case (ty.ty_fn(?proto, ?args, ?out)) { - ret T_fn_pair(cx.tn, type_of_fn(cx, proto, args, out)); + llty = T_fn_pair(cx.tn, type_of_fn(cx, proto, args, out)); } case (ty.ty_native_fn(?abi, ?args, ?out)) { - ret T_fn_pair(cx.tn, type_of_native_fn(cx, abi, args, out)); + llty = T_fn_pair(cx.tn, type_of_native_fn(cx, abi, args, out)); } case (ty.ty_obj(?meths)) { auto th = mk_type_handle(); @@ -594,22 +593,25 @@ fn type_of_inner(@crate_ctxt cx, @ty.t t) -> TypeRef { auto abs_pair = llvm.LLVMResolveTypeHandle(th.llth); llvm.LLVMRefineType(abs_pair, pair); abs_pair = llvm.LLVMResolveTypeHandle(th.llth); - ret abs_pair; + llty = abs_pair; } case (ty.ty_var(_)) { log "ty_var in trans.type_of"; fail; } case (ty.ty_param(_)) { - ret T_typaram_ptr(cx.tn); + llty = T_typaram_ptr(cx.tn); } - case (ty.ty_type) { ret T_ptr(T_tydesc(cx.tn)); } + case (ty.ty_type) { llty = T_ptr(T_tydesc(cx.tn)); } } - fail; + + check (llty as int != 0); + llvm.LLVMAddTypeName(cx.llmod, _str.buf(ty.ty_to_str(t)), llty); + ret llty; } fn type_of_arg(@crate_ctxt cx, &ty.arg arg) -> TypeRef { - auto ty = type_of(cx, arg.ty); + auto ty = type_of_inner(cx, arg.ty); if (arg.mode == ast.alias) { ty = T_ptr(ty); } -- cgit v1.2.3 From b5081a6a825f23b45920cf72896076039f30386d Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Fri, 25 Feb 2011 16:45:43 -0800 Subject: Add a tag_variant_count() function to trans that doesn't go through the soon-to-be-deprecated tag info table --- src/comp/middle/trans.rs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 29ff9d6e..cfe07caa 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -1442,6 +1442,8 @@ fn decr_refcnt_and_if_zero(@block_ctxt cx, ret res(next_cx, phi); } +// Tag information + fn type_of_variant(@crate_ctxt cx, &ast.variant v) -> TypeRef { let vec[TypeRef] lltys = vec(); alt (ty.ann_to_type(v.ann).struct) { @@ -1455,6 +1457,17 @@ fn type_of_variant(@crate_ctxt cx, &ast.variant v) -> TypeRef { ret T_struct(lltys); } +// Returns the number of variants in a tag. +fn tag_variant_count(@crate_ctxt cx, ast.def_id id) -> uint { + check (cx.items.contains_key(id)); + alt (cx.items.get(id).node) { + case (ast.item_tag(_, ?variants, _, _)) { + ret _vec.len[ast.variant](variants); + } + } + fail; // not reached +} + type val_and_ty_fn = fn(@block_ctxt cx, ValueRef v, @ty.t t) -> result; // Iterates through the elements of a structural type. @@ -1506,7 +1519,7 @@ fn iter_structural_ty(@block_ctxt cx, case (ty.ty_tag(?tid, ?tps)) { check (cx.fcx.ccx.tags.contains_key(tid)); auto info = cx.fcx.ccx.tags.get(tid); - auto n_variants = _vec.len[tup(ast.def_id,arity)](info.variants); + auto n_variants = tag_variant_count(cx.fcx.ccx, tid); // Look up the tag in the typechecked AST. check (cx.fcx.ccx.items.contains_key(tid)); -- cgit v1.2.3 From 9c928fcf8c584659274bdb9095e47f2fa963d05c Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Fri, 25 Feb 2011 17:14:48 -0800 Subject: rustc: Make iter_structural_ty() not use the "variants" field in the tag info --- src/comp/middle/trans.rs | 104 +++++++++++++++++++---------------------------- 1 file changed, 42 insertions(+), 62 deletions(-) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index cfe07caa..a56421ba 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -1457,13 +1457,11 @@ fn type_of_variant(@crate_ctxt cx, &ast.variant v) -> TypeRef { ret T_struct(lltys); } -// Returns the number of variants in a tag. -fn tag_variant_count(@crate_ctxt cx, ast.def_id id) -> uint { +// Returns the variants in a tag. +fn tag_variants(@crate_ctxt cx, ast.def_id id) -> vec[ast.variant] { check (cx.items.contains_key(id)); alt (cx.items.get(id).node) { - case (ast.item_tag(_, ?variants, _, _)) { - ret _vec.len[ast.variant](variants); - } + case (ast.item_tag(_, ?variants, _, _)) { ret variants; } } fail; // not reached } @@ -1519,21 +1517,9 @@ fn iter_structural_ty(@block_ctxt cx, case (ty.ty_tag(?tid, ?tps)) { check (cx.fcx.ccx.tags.contains_key(tid)); auto info = cx.fcx.ccx.tags.get(tid); - auto n_variants = tag_variant_count(cx.fcx.ccx, tid); - - // Look up the tag in the typechecked AST. - check (cx.fcx.ccx.items.contains_key(tid)); - auto tag_item = cx.fcx.ccx.items.get(tid); - let vec[ast.variant] variants = vec(); // FIXME: typestate bug - alt (tag_item.node) { - case (ast.item_tag(_, ?vs, _, _)) { - variants = vs; - } - case (_) { - log "trans: ty_tag doesn't actually refer to a tag"; - fail; - } - } + + auto variants = tag_variants(cx.fcx.ccx, tid); + auto n_variants = _vec.len[ast.variant](variants); auto lldiscrim_ptr = cx.build.GEP(v, vec(C_int(0), C_int(0))); auto llunion_ptr = cx.build.GEP(v, vec(C_int(0), C_int(1))); @@ -1548,55 +1534,49 @@ fn iter_structural_ty(@block_ctxt cx, auto next_cx = new_sub_block_ctxt(cx, "tag-iter-next"); auto i = 0u; - for (tup(ast.def_id,arity) variant in info.variants) { + for (ast.variant variant in variants) { auto variant_cx = new_sub_block_ctxt(cx, "tag-iter-variant-" + _uint.to_str(i, 10u)); llvm.LLVMAddCase(llswitch, C_int(i as int), variant_cx.llbb); - alt (variant._1) { - case (n_ary) { - let vec[ValueRef] vals = vec(C_int(0), C_int(1), - C_int(i as int)); - auto llvar = variant_cx.build.GEP(v, vals); - auto llvarty = type_of_variant(cx.fcx.ccx, - variants.(i)); - - auto fn_ty = ty.ann_to_type(variants.(i).ann); - alt (fn_ty.struct) { - case (ty.ty_fn(_, ?args, _)) { - auto llvarp = variant_cx.build. - TruncOrBitCast(llunion_ptr, - T_ptr(llvarty)); - - auto j = 0u; - for (ty.arg a in args) { - auto v = vec(C_int(0), - C_int(j as int)); - auto llfldp = - variant_cx.build.GEP(llvarp, v); - - auto ty_subst = ty.substitute_ty_params( - info.ty_params, tps, a.ty); - - auto llfld = - load_scalar_or_boxed(variant_cx, - llfldp, - ty_subst); - - auto res = f(variant_cx, llfld, ty_subst); - variant_cx = res.bcx; - j += 1u; - } + if (_vec.len[ast.variant_arg](variant.args) > 0u) { + // N-ary variant. + let vec[ValueRef] vals = vec(C_int(0), C_int(1), + C_int(i as int)); + auto llvar = variant_cx.build.GEP(v, vals); + auto llvarty = type_of_variant(cx.fcx.ccx, variants.(i)); + + auto fn_ty = ty.ann_to_type(variants.(i).ann); + alt (fn_ty.struct) { + case (ty.ty_fn(_, ?args, _)) { + auto llvarp = variant_cx.build. + TruncOrBitCast(llunion_ptr, T_ptr(llvarty)); + + auto j = 0u; + for (ty.arg a in args) { + auto v = vec(C_int(0), C_int(j as int)); + auto llfldp = variant_cx.build.GEP(llvarp, v); + + auto ty_subst = ty.substitute_ty_params( + info.ty_params, tps, a.ty); + + auto llfld = + load_scalar_or_boxed(variant_cx, + llfldp, + ty_subst); + + auto res = f(variant_cx, llfld, ty_subst); + variant_cx = res.bcx; + j += 1u; } - case (_) { fail; } } - - variant_cx.build.Br(next_cx.llbb); - } - case (nullary) { - // Nothing to do. - variant_cx.build.Br(next_cx.llbb); + case (_) { fail; } } + + variant_cx.build.Br(next_cx.llbb); + } else { + // Nullary variant; nothing to do. + variant_cx.build.Br(next_cx.llbb); } i += 1u; -- cgit v1.2.3 From 699eb69cc85f663d62200ee64ec9f2a606fcf440 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Fri, 25 Feb 2011 18:16:50 -0800 Subject: rustc: Eliminate the "variants" field from the tag info --- src/comp/middle/trans.rs | 59 ++++++++++++++++++------------------------------ 1 file changed, 22 insertions(+), 37 deletions(-) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index a56421ba..3f9c770e 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -61,7 +61,6 @@ type glue_fns = rec(ValueRef activate_glue, tag arity { nullary; n_ary; } type tag_info = rec(type_handle th, - mutable vec[tup(ast.def_id,arity)] variants, mutable uint size, vec[ast.ty_param] ty_params); @@ -2384,11 +2383,12 @@ fn trans_pat_match(@block_ctxt cx, @ast.pat pat, ValueRef llval, auto vdef = option.get[ast.variant_def](vdef_opt); auto variant_id = vdef._1; - auto tinfo = cx.fcx.ccx.tags.get(vdef._0); auto variant_tag = 0; + + auto variants = tag_variants(cx.fcx.ccx, vdef._0); auto i = 0; - for (tup(ast.def_id,arity) vinfo in tinfo.variants) { - auto this_variant_id = vinfo._0; + for (ast.variant v in variants) { + auto this_variant_id = v.id; if (variant_id._0 == this_variant_id._0 && variant_id._1 == this_variant_id._1) { variant_tag = i; @@ -4436,9 +4436,7 @@ fn collect_item(&@crate_ctxt cx, @ast.item i) -> @crate_ctxt { case (ast.item_tag(_, ?variants, ?tps, ?tag_id)) { auto vi = new_def_hash[uint](); auto navi = new_def_hash[uint](); - let vec[tup(ast.def_id,arity)] variant_info = vec(); cx.tags.insert(tag_id, @rec(th=mk_type_handle(), - mutable variants=variant_info, mutable size=0u, ty_params=tps)); cx.items.insert(tag_id, i); @@ -4502,10 +4500,8 @@ fn resolve_tag_types_for_item(&@crate_ctxt cx, @ast.item i) -> @crate_ctxt { auto max_size = 0u; auto info = cx.tags.get(tag_id); - let vec[tup(ast.def_id,arity)] variant_info = vec(); for (ast.variant variant in variants) { - auto arity_info; if (_vec.len[ast.variant_arg](variant.args) > 0u) { auto llvariantty = type_of_variant(cx, variant); auto align = @@ -4516,16 +4512,9 @@ fn resolve_tag_types_for_item(&@crate_ctxt cx, @ast.item i) -> @crate_ctxt { llvariantty) as uint; if (max_align < align) { max_align = align; } if (max_size < size) { max_size = size; } - - arity_info = n_ary; - } else { - arity_info = nullary; } - - variant_info += vec(tup(variant.id, arity_info)); } - info.variants = variant_info; info.size = max_size; // FIXME: alignment is wrong here, manually insert padding I @@ -4566,28 +4555,24 @@ fn trans_constant(&@crate_ctxt cx, @ast.item it) -> @crate_ctxt { auto union_ty = elts.(1); auto i = 0u; - while (i < _vec.len[tup(ast.def_id,arity)](info.variants)) { - auto variant_info = info.variants.(i); - alt (variant_info._1) { - case (nullary) { - // Nullary tags become constants. - auto union_val = C_zero_byte_arr(info.size as uint); - auto val = C_struct(vec(C_int(i as int), union_val)); - - // FIXME: better name - auto gvar = llvm.LLVMAddGlobal(cx.llmod, val_ty(val), - _str.buf("tag")); - llvm.LLVMSetInitializer(gvar, val); - llvm.LLVMSetGlobalConstant(gvar, True); - llvm.LLVMSetLinkage(gvar, - lib.llvm.LLVMPrivateLinkage - as llvm.Linkage); - cx.item_ids.insert(variant_info._0, gvar); - } - case (n_ary) { - // N-ary tags are treated as functions and generated - // later. - } + auto n_variants = _vec.len[ast.variant](variants); + while (i < n_variants) { + auto variant = variants.(i); + if (_vec.len[ast.variant_arg](variant.args) == 0u) { + // Nullary tags become constants. (N-ary tags are treated + // as functions and generated later.) + + auto union_val = C_zero_byte_arr(info.size as uint); + auto val = C_struct(vec(C_int(i as int), union_val)); + + // FIXME: better name + auto gvar = llvm.LLVMAddGlobal(cx.llmod, val_ty(val), + _str.buf("tag")); + llvm.LLVMSetInitializer(gvar, val); + llvm.LLVMSetGlobalConstant(gvar, True); + llvm.LLVMSetLinkage(gvar, lib.llvm.LLVMPrivateLinkage + as llvm.Linkage); + cx.item_ids.insert(variant.id, gvar); } i += 1u; -- cgit v1.2.3 From e37db13b02557b887de295a63b4b96021042ccde Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Fri, 25 Feb 2011 18:24:58 -0800 Subject: rustc: Eliminate the "ty_params" field from the tag info --- src/comp/middle/trans.rs | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 3f9c770e..b70568b4 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -60,9 +60,7 @@ type glue_fns = rec(ValueRef activate_glue, ValueRef bzero_glue); tag arity { nullary; n_ary; } -type tag_info = rec(type_handle th, - mutable uint size, - vec[ast.ty_param] ty_params); +type tag_info = rec(type_handle th, mutable uint size); state type crate_ctxt = rec(session.session sess, ModuleRef llmod, @@ -1456,6 +1454,15 @@ fn type_of_variant(@crate_ctxt cx, &ast.variant v) -> TypeRef { ret T_struct(lltys); } +// Returns the type parameters of a tag. +fn tag_ty_params(@crate_ctxt cx, ast.def_id id) -> vec[ast.ty_param] { + check (cx.items.contains_key(id)); + alt (cx.items.get(id).node) { + case (ast.item_tag(_, _, ?tps, _)) { ret tps; } + } + fail; // not reached +} + // Returns the variants in a tag. fn tag_variants(@crate_ctxt cx, ast.def_id id) -> vec[ast.variant] { check (cx.items.contains_key(id)); @@ -1551,13 +1558,15 @@ fn iter_structural_ty(@block_ctxt cx, auto llvarp = variant_cx.build. TruncOrBitCast(llunion_ptr, T_ptr(llvarty)); + auto ty_params = tag_ty_params(cx.fcx.ccx, tid); + auto j = 0u; for (ty.arg a in args) { auto v = vec(C_int(0), C_int(j as int)); auto llfldp = variant_cx.build.GEP(llvarp, v); auto ty_subst = ty.substitute_ty_params( - info.ty_params, tps, a.ty); + ty_params, tps, a.ty); auto llfld = load_scalar_or_boxed(variant_cx, @@ -4437,8 +4446,7 @@ fn collect_item(&@crate_ctxt cx, @ast.item i) -> @crate_ctxt { auto vi = new_def_hash[uint](); auto navi = new_def_hash[uint](); cx.tags.insert(tag_id, @rec(th=mk_type_handle(), - mutable size=0u, - ty_params=tps)); + mutable size=0u)); cx.items.insert(tag_id, i); } -- cgit v1.2.3 From 0120571e90a68befb03892c63c470d0923d425c4 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Fri, 25 Feb 2011 19:42:26 -0800 Subject: rustc: Make the tag info table keyed by both tag ID and type parameter. Also fix a bug that was causing all tags to compare equal. --- src/comp/middle/trans.rs | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index b70568b4..fb916f00 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -74,7 +74,7 @@ state type crate_ctxt = rec(session.session sess, hashmap[ast.def_id, @ast.item] items, hashmap[ast.def_id, @ast.native_item] native_items, - hashmap[ast.def_id, @tag_info] tags, + hashmap[@ty.t, @tag_info] tags, hashmap[ast.def_id, ValueRef] fn_pairs, hashmap[ast.def_id, ValueRef] consts, hashmap[ast.def_id,()] obj_methods, @@ -543,7 +543,7 @@ fn type_of_inner(@crate_ctxt cx, @ty.t t) -> TypeRef { case (ty.ty_char) { llty = T_char(); } case (ty.ty_str) { llty = T_ptr(T_str()); } case (ty.ty_tag(?tag_id, _)) { - llty = llvm.LLVMResolveTypeHandle(cx.tags.get(tag_id).th.llth); + llty = llvm.LLVMResolveTypeHandle(cx.tags.get(t).th.llth); } case (ty.ty_box(?t)) { llty = T_ptr(T_box(type_of_inner(cx, t))); @@ -1472,6 +1472,14 @@ fn tag_variants(@crate_ctxt cx, ast.def_id id) -> vec[ast.variant] { fail; // not reached } +// Returns a new plain tag type of the given ID with no type parameters. Don't +// use this function in new code; it's a hack to keep things working for now. +fn mk_plain_tag(ast.def_id tid) -> @ty.t { + let vec[@ty.t] tps = vec(); + ret ty.plain_ty(ty.ty_tag(tid, tps)); +} + + type val_and_ty_fn = fn(@block_ctxt cx, ValueRef v, @ty.t t) -> result; // Iterates through the elements of a structural type. @@ -1521,8 +1529,7 @@ fn iter_structural_ty(@block_ctxt cx, } } case (ty.ty_tag(?tid, ?tps)) { - check (cx.fcx.ccx.tags.contains_key(tid)); - auto info = cx.fcx.ccx.tags.get(tid); + auto info = cx.fcx.ccx.tags.get(mk_plain_tag(tid)); auto variants = tag_variants(cx.fcx.ccx, tid); auto n_variants = _vec.len[ast.variant](variants); @@ -2591,7 +2598,6 @@ fn trans_path(@block_ctxt cx, &ast.path p, &option.t[ast.def] dopt, ret lval_generic_fn(cx, ty.item_ty(fn_item), did, ann); } case (ast.def_variant(?tid, ?vid)) { - check (cx.fcx.ccx.tags.contains_key(tid)); if (cx.fcx.ccx.fn_pairs.contains_key(vid)) { check (cx.fcx.ccx.items.contains_key(tid)); auto tag_item = cx.fcx.ccx.items.get(tid); @@ -4247,7 +4253,9 @@ fn trans_tag_variant(@crate_ctxt cx, ast.def_id tag_id, auto arg_tys = arg_tys_of_fn(variant.ann); copy_args_to_allocas(bcx, none[TypeRef], fn_args, arg_tys); - auto info = cx.tags.get(tag_id); + // FIXME: This is wrong for generic tags. We should be dynamically + // computing "size" below based on the tydescs passed in. + auto info = cx.tags.get(mk_plain_tag(tag_id)); auto lltagty = T_struct(vec(T_int(), T_array(T_i8(), info.size))); @@ -4445,8 +4453,8 @@ fn collect_item(&@crate_ctxt cx, @ast.item i) -> @crate_ctxt { case (ast.item_tag(_, ?variants, ?tps, ?tag_id)) { auto vi = new_def_hash[uint](); auto navi = new_def_hash[uint](); - cx.tags.insert(tag_id, @rec(th=mk_type_handle(), - mutable size=0u)); + cx.tags.insert(mk_plain_tag(tag_id), @rec(th=mk_type_handle(), + mutable size=0u)); cx.items.insert(tag_id, i); } @@ -4507,7 +4515,7 @@ fn resolve_tag_types_for_item(&@crate_ctxt cx, @ast.item i) -> @crate_ctxt { auto max_align = 0u; auto max_size = 0u; - auto info = cx.tags.get(tag_id); + auto info = cx.tags.get(mk_plain_tag(tag_id)); for (ast.variant variant in variants) { if (_vec.len[ast.variant_arg](variant.args) > 0u) { @@ -4528,7 +4536,7 @@ fn resolve_tag_types_for_item(&@crate_ctxt cx, @ast.item i) -> @crate_ctxt { // FIXME: alignment is wrong here, manually insert padding I // guess :( auto tag_ty = T_struct(vec(T_int(), T_array(T_i8(), max_size))); - auto th = cx.tags.get(tag_id).th.llth; + auto th = info.th.llth; llvm.LLVMRefineType(llvm.LLVMResolveTypeHandle(th), tag_ty); } case (_) { @@ -4554,7 +4562,7 @@ fn resolve_tag_types(@crate_ctxt cx, @ast.crate crate) { fn trans_constant(&@crate_ctxt cx, @ast.item it) -> @crate_ctxt { alt (it.node) { case (ast.item_tag(_, ?variants, _, ?tag_id)) { - auto info = cx.tags.get(tag_id); + auto info = cx.tags.get(mk_plain_tag(tag_id)); auto tag_ty = llvm.LLVMResolveTypeHandle(info.th.llth); check (llvm.LLVMCountStructElementTypes(tag_ty) == 2u); @@ -4924,6 +4932,7 @@ fn trans_crate(session.session sess, @ast.crate crate, str output, auto glues = make_glues(llmod, tn); auto hasher = ty.hash_ty; auto eqer = ty.eq_ty; + auto tags = map.mk_hashmap[@ty.t,@tag_info](hasher, eqer); auto tydescs = map.mk_hashmap[@ty.t,ValueRef](hasher, eqer); let vec[ast.ty_param] obj_typarams = vec(); let vec[ast.obj_field] obj_fields = vec(); @@ -4939,7 +4948,7 @@ fn trans_crate(session.session sess, @ast.crate crate, str output, item_ids = new_def_hash[ValueRef](), items = new_def_hash[@ast.item](), native_items = new_def_hash[@ast.native_item](), - tags = new_def_hash[@tag_info](), + tags = tags, fn_pairs = new_def_hash[ValueRef](), consts = new_def_hash[ValueRef](), obj_methods = new_def_hash[()](), -- cgit v1.2.3 From 4ac4d03f0cac829650f7a297162d070de53c6455 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20=C3=81vila=20de=20Esp=C3=ADndola?= Date: Mon, 28 Feb 2011 10:37:49 -0500 Subject: Update the function declarations with rust abi. A cdecl fn write(int fd, rustrt.vbuf buf, uint count) -> int; compiles to declare i32 @write(i32, i8*, i32) and a rust fn vec_buf[T](vec[T] v, uint offset) -> vbuf; compiles to declare i8* @vec_buf(%task*, %tydesc*, %"vec[]", i32) which I think is the correct declaration for both :-) --- src/comp/middle/trans.rs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index fb916f00..3564b1b3 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -513,7 +513,18 @@ fn type_of_fn(@crate_ctxt cx, fn type_of_native_fn(@crate_ctxt cx, ast.native_abi abi, vec[ty.arg] inputs, @ty.t output) -> TypeRef { - let vec[TypeRef] atys = type_of_explicit_args(cx, inputs); + let vec[TypeRef] atys = vec(); + if (abi == ast.native_abi_rust) { + atys += T_taskptr(cx.tn); + auto t = ty.ty_native_fn(abi, inputs, output); + auto ty_param_count = ty.count_ty_params(plain_ty(t)); + auto i = 0u; + while (i < ty_param_count) { + atys += T_ptr(T_tydesc(cx.tn)); + i += 1u; + } + } + atys += type_of_explicit_args(cx, inputs); ret T_fn(atys, type_of_inner(cx, output)); } -- cgit v1.2.3 From a172f5aef5f7d26fba9dbf94a1ade60d6d62ba74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20=C3=81vila=20de=20Esp=C3=ADndola?= Date: Mon, 28 Feb 2011 17:33:46 -0500 Subject: Declare wrappers to the native functions and use those to create the fn/closure pairs. Disable native2.rs for now as we are not yet defining the wrappers and it fails to link. --- src/comp/middle/trans.rs | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 3564b1b3..189c742c 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -4395,6 +4395,12 @@ fn decl_fn_and_pair(@crate_ctxt cx, // Declare the global constant pair that points to it. let str ps = cx.names.next("_rust_" + kind + "_pair") + sep() + name; + + register_fn_pair(cx, ps, llpairty, llfn, id); +} + +fn register_fn_pair(@crate_ctxt cx, str ps, TypeRef llpairty, ValueRef llfn, + ast.def_id id) { let ValueRef gvar = llvm.LLVMAddGlobal(cx.llmod, llpairty, _str.buf(ps)); auto pair = C_struct(vec(llfn, @@ -4410,16 +4416,34 @@ fn decl_fn_and_pair(@crate_ctxt cx, cx.fn_pairs.insert(id, gvar); } +fn native_fn_wrapper_type(@crate_ctxt cx, &ast.ann ann) -> TypeRef { + auto x = node_ann_type(cx, ann); + alt (x.struct) { + case (ty.ty_native_fn(?abi, ?args, ?out)) { + ret type_of_fn(cx, ast.proto_fn, args, out); + } + } + fail; +} + fn decl_native_fn_and_pair(@crate_ctxt cx, str name, &ast.ann ann, ast.def_id id) { + // Declare the wrapper. + auto wrapper_type = native_fn_wrapper_type(cx, ann); + let str s = cx.names.next("_rust_wrapper") + sep() + name; + let ValueRef wrapper_fn = decl_fastcall_fn(cx.llmod, s, wrapper_type); - auto llpairty = node_type(cx, ann); - auto llfty = get_pair_fn_ty(llpairty); + // Declare the global constant pair that points to it. + auto wrapper_pair_type = T_fn_pair(cx.tn, wrapper_type); + let str ps = cx.names.next("_rust_wrapper_pair") + sep() + name; - let ValueRef llfn = decl_cdecl_fn(cx.llmod, name, llfty); - cx.item_ids.insert(id, llfn); + register_fn_pair(cx, ps, wrapper_pair_type, wrapper_fn, id); + + // Declare the function itself. + auto llfty = get_pair_fn_ty(node_type(cx, ann)); + decl_cdecl_fn(cx.llmod, name, llfty); } fn collect_native_item(&@crate_ctxt cx, @ast.native_item i) -> @crate_ctxt { -- cgit v1.2.3 From 86309ed3ea896473641c9cdeadf16b02931b8ac8 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Mon, 28 Feb 2011 16:08:05 -0800 Subject: rustc: Write tag variant discriminants into the crate as integer constants --- src/comp/middle/trans.rs | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 189c742c..b2ef0f16 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -4609,12 +4609,26 @@ fn trans_constant(&@crate_ctxt cx, @ast.item it) -> @crate_ctxt { auto n_variants = _vec.len[ast.variant](variants); while (i < n_variants) { auto variant = variants.(i); + + auto discrim_val = C_int(i as int); + + // FIXME: better name. + auto discrim_gvar = llvm.LLVMAddGlobal(cx.llmod, T_int(), + _str.buf("tag_discrim")); + + // FIXME: Eventually we do want to export these, but we need + // to figure out what name they get first! + llvm.LLVMSetInitializer(discrim_gvar, discrim_val); + llvm.LLVMSetGlobalConstant(discrim_gvar, True); + llvm.LLVMSetLinkage(discrim_gvar, lib.llvm.LLVMPrivateLinkage + as llvm.Linkage); + if (_vec.len[ast.variant_arg](variant.args) == 0u) { // Nullary tags become constants. (N-ary tags are treated // as functions and generated later.) auto union_val = C_zero_byte_arr(info.size as uint); - auto val = C_struct(vec(C_int(i as int), union_val)); + auto val = C_struct(vec(discrim_val, union_val)); // FIXME: better name auto gvar = llvm.LLVMAddGlobal(cx.llmod, val_ty(val), -- cgit v1.2.3 From 1291cc2df90c36eee8642048e1bf1b69a690781f Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Mon, 28 Feb 2011 16:36:08 -0800 Subject: Groundwork for structural comparison. Still lacking the actual loop that does it. --- src/comp/middle/trans.rs | 121 +++++++++++++++++++++++++++++++++++++---------- 1 file changed, 97 insertions(+), 24 deletions(-) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index b2ef0f16..4a45beea 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -1958,10 +1958,66 @@ fn trans_unary(@block_ctxt cx, ast.unop op, fail; } -// FIXME: implement proper structural comparison. +fn trans_compare(@block_ctxt cx, ast.binop op, @ty.t t, + ValueRef lhs, ValueRef rhs) -> result { + + if (ty.type_is_scalar(t)) { + ret res(cx, trans_scalar_compare(cx, op, t, lhs, rhs)); + + } else if (ty.type_is_structural(t)) { + auto scx = new_sub_block_ctxt(cx, "structural compare body"); + auto next = new_sub_block_ctxt(cx, "structural compare completion"); + cx.build.Br(scx.llbb); + + // Start with the assumptioin that our predicate holds. + auto flag = scx.build.Alloca(T_i1()); + scx.build.Store(C_integral(1, T_i1()), flag); + + // Attempt to prove otherwise by inverting the sense of the comparison + // on each inner element and bailing if any succeed. + + // FIXME: finish this. + + auto v = scx.build.Load(flag); + scx.build.Br(next.llbb); + ret res(next, v); + + } else { + // FIXME: compare vec, str, box? + cx.fcx.ccx.sess.unimpl("type in trans_compare"); + ret res(cx, C_bool(false)); + } +} + +fn trans_scalar_compare(@block_ctxt cx, ast.binop op, @ty.t t, + ValueRef lhs, ValueRef rhs) -> ValueRef { + if (ty.type_is_fp(t)) { + ret trans_fp_compare(cx, op, t, lhs, rhs); + } else { + ret trans_integral_compare(cx, op, t, lhs, rhs); + } +} + +fn trans_fp_compare(@block_ctxt cx, ast.binop op, @ty.t fptype, + ValueRef lhs, ValueRef rhs) -> ValueRef { -fn trans_compare(@block_ctxt cx, ast.binop op, @ty.t intype, - ValueRef lhs, ValueRef rhs) -> ValueRef { + auto cmp = lib.llvm.LLVMIntEQ; + alt (op) { + // FIXME: possibly use the unordered-or-< predicates here, + // for now we're only going with ordered-and-< style (no NaNs). + case (ast.eq) { cmp = lib.llvm.LLVMRealOEQ; } + case (ast.ne) { cmp = lib.llvm.LLVMRealONE; } + case (ast.lt) { cmp = lib.llvm.LLVMRealOLT; } + case (ast.gt) { cmp = lib.llvm.LLVMRealOGT; } + case (ast.le) { cmp = lib.llvm.LLVMRealOLE; } + case (ast.ge) { cmp = lib.llvm.LLVMRealOGE; } + } + + ret cx.build.FCmp(cmp, lhs, rhs); +} + +fn trans_integral_compare(@block_ctxt cx, ast.binop op, @ty.t intype, + ValueRef lhs, ValueRef rhs) -> ValueRef { auto cmp = lib.llvm.LLVMIntEQ; alt (op) { case (ast.eq) { cmp = lib.llvm.LLVMIntEQ; } @@ -2000,34 +2056,34 @@ fn trans_compare(@block_ctxt cx, ast.binop op, @ty.t intype, } fn trans_eager_binop(@block_ctxt cx, ast.binop op, @ty.t intype, - ValueRef lhs, ValueRef rhs) -> ValueRef { + ValueRef lhs, ValueRef rhs) -> result { alt (op) { - case (ast.add) { ret cx.build.Add(lhs, rhs); } - case (ast.sub) { ret cx.build.Sub(lhs, rhs); } + case (ast.add) { ret res(cx, cx.build.Add(lhs, rhs)); } + case (ast.sub) { ret res(cx, cx.build.Sub(lhs, rhs)); } - case (ast.mul) { ret cx.build.Mul(lhs, rhs); } + case (ast.mul) { ret res(cx, cx.build.Mul(lhs, rhs)); } case (ast.div) { if (ty.type_is_signed(intype)) { - ret cx.build.SDiv(lhs, rhs); + ret res(cx, cx.build.SDiv(lhs, rhs)); } else { - ret cx.build.UDiv(lhs, rhs); + ret res(cx, cx.build.UDiv(lhs, rhs)); } } case (ast.rem) { if (ty.type_is_signed(intype)) { - ret cx.build.SRem(lhs, rhs); + ret res(cx, cx.build.SRem(lhs, rhs)); } else { - ret cx.build.URem(lhs, rhs); + ret res(cx, cx.build.URem(lhs, rhs)); } } - case (ast.bitor) { ret cx.build.Or(lhs, rhs); } - case (ast.bitand) { ret cx.build.And(lhs, rhs); } - case (ast.bitxor) { ret cx.build.Xor(lhs, rhs); } - case (ast.lsl) { ret cx.build.Shl(lhs, rhs); } - case (ast.lsr) { ret cx.build.LShr(lhs, rhs); } - case (ast.asr) { ret cx.build.AShr(lhs, rhs); } + case (ast.bitor) { ret res(cx, cx.build.Or(lhs, rhs)); } + case (ast.bitand) { ret res(cx, cx.build.And(lhs, rhs)); } + case (ast.bitxor) { ret res(cx, cx.build.Xor(lhs, rhs)); } + case (ast.lsl) { ret res(cx, cx.build.Shl(lhs, rhs)); } + case (ast.lsr) { ret res(cx, cx.build.LShr(lhs, rhs)); } + case (ast.asr) { ret res(cx, cx.build.AShr(lhs, rhs)); } case (_) { ret trans_compare(cx, op, intype, lhs, rhs); } @@ -2055,6 +2111,21 @@ fn autoderef(@block_ctxt cx, ValueRef v, @ty.t t) -> result { } } +fn autoderefed_ty(@ty.t t) -> @ty.t { + let @ty.t t1 = t; + + while (true) { + alt (t1.struct) { + case (ty.ty_box(?inner)) { + t1 = inner; + } + case (_) { + ret t1; + } + } + } +} + fn trans_binary(@block_ctxt cx, ast.binop op, @ast.expr a, @ast.expr b) -> result { @@ -2109,8 +2180,9 @@ fn trans_binary(@block_ctxt cx, ast.binop op, auto rhs = trans_expr(lhs.bcx, b); auto rhty = ty.expr_ty(b); rhs = autoderef(rhs.bcx, rhs.val, rhty); - ret res(rhs.bcx, trans_eager_binop(rhs.bcx, op, lhty, - lhs.val, rhs.val)); + ret trans_eager_binop(rhs.bcx, op, + autoderefed_ty(lhty), + lhs.val, rhs.val); } } fail; @@ -2399,8 +2471,8 @@ fn trans_pat_match(@block_ctxt cx, @ast.pat pat, ValueRef llval, auto lltype = ty.ann_to_type(ann); auto lleq = trans_compare(cx, ast.eq, lltype, llval, lllit); - auto matched_cx = new_sub_block_ctxt(cx, "matched_cx"); - cx.build.CondBr(lleq, matched_cx.llbb, next_cx.llbb); + auto matched_cx = new_sub_block_ctxt(lleq.bcx, "matched_cx"); + lleq.bcx.build.CondBr(lleq.val, matched_cx.llbb, next_cx.llbb); ret res(matched_cx, llval); } @@ -2656,8 +2728,9 @@ fn trans_path(@block_ctxt cx, &ast.path p, &option.t[ast.def] dopt, fn trans_field(@block_ctxt cx, &ast.span sp, @ast.expr base, &ast.ident field, &ast.ann ann) -> lval_result { auto r = trans_expr(cx, base); - r = autoderef(r.bcx, r.val, ty.expr_ty(base)); auto t = ty.expr_ty(base); + r = autoderef(r.bcx, r.val, t); + t = autoderefed_ty(t); alt (t.struct) { case (ty.ty_tup(?fields)) { let uint ix = ty.field_num(cx.fcx.ccx.sess, sp, field); @@ -3439,8 +3512,8 @@ fn trans_expr(@block_ctxt cx, @ast.expr e) -> result { auto v = trans_eager_binop(rhs_res.bcx, op, t, lhs_val, rhs_res.val); // FIXME: calculate copy init-ness in typestate. - ret copy_ty(rhs_res.bcx, DROP_EXISTING, - lhs_res.res.val, v, t); + ret copy_ty(v.bcx, DROP_EXISTING, + lhs_res.res.val, v.val, t); } case (ast.expr_bind(?f, ?args, ?ann)) { -- cgit v1.2.3 From d08f3a1c702c337c494bbc03d8bed9664ac1dddf Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Mon, 28 Feb 2011 17:49:26 -0800 Subject: More complete sketch of structural compare. Still not quite working. --- src/comp/middle/trans.rs | 153 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 115 insertions(+), 38 deletions(-) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 4a45beea..8dc4efb7 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -1493,27 +1493,50 @@ fn mk_plain_tag(ast.def_id tid) -> @ty.t { type val_and_ty_fn = fn(@block_ctxt cx, ValueRef v, @ty.t t) -> result; +type val_pair_and_ty_fn = + fn(@block_ctxt cx, ValueRef av, ValueRef bv, @ty.t t) -> result; + // Iterates through the elements of a structural type. fn iter_structural_ty(@block_ctxt cx, ValueRef v, @ty.t t, val_and_ty_fn f) -> result { + fn adaptor_fn(val_and_ty_fn f, + @block_ctxt cx, + ValueRef av, + ValueRef bv, + @ty.t t) -> result { + ret f(cx, av, t); + } + be iter_structural_ty_full(cx, v, v, t, + bind adaptor_fn(f, _, _, _, _)); +} + + +fn iter_structural_ty_full(@block_ctxt cx, + ValueRef av, + ValueRef bv, + @ty.t t, + val_pair_and_ty_fn f) + -> result { let result r = res(cx, C_nil()); fn iter_boxpp(@block_ctxt cx, - ValueRef box_cell, - val_and_ty_fn f) -> result { - auto box_ptr = cx.build.Load(box_cell); + ValueRef box_a_cell, + ValueRef box_b_cell, + val_pair_and_ty_fn f) -> result { + auto box_a_ptr = cx.build.Load(box_a_cell); + auto box_b_ptr = cx.build.Load(box_b_cell); auto tnil = plain_ty(ty.ty_nil); auto tbox = plain_ty(ty.ty_box(tnil)); auto inner_cx = new_sub_block_ctxt(cx, "iter box"); auto next_cx = new_sub_block_ctxt(cx, "next"); - auto null_test = cx.build.IsNull(box_ptr); + auto null_test = cx.build.IsNull(box_a_ptr); cx.build.CondBr(null_test, next_cx.llbb, inner_cx.llbb); - auto r = f(inner_cx, box_ptr, tbox); + auto r = f(inner_cx, box_a_ptr, box_b_ptr, tbox); r.bcx.build.Br(next_cx.llbb); ret res(next_cx, r.val); } @@ -1522,9 +1545,11 @@ fn iter_structural_ty(@block_ctxt cx, case (ty.ty_tup(?args)) { let int i = 0; for (@ty.t arg in args) { - auto elt = r.bcx.build.GEP(v, vec(C_int(0), C_int(i))); + auto elt_a = r.bcx.build.GEP(av, vec(C_int(0), C_int(i))); + auto elt_b = r.bcx.build.GEP(bv, vec(C_int(0), C_int(i))); r = f(r.bcx, - load_scalar_or_boxed(r.bcx, elt, arg), + load_scalar_or_boxed(r.bcx, elt_a, arg), + load_scalar_or_boxed(r.bcx, elt_b, arg), arg); i += 1; } @@ -1532,9 +1557,11 @@ fn iter_structural_ty(@block_ctxt cx, case (ty.ty_rec(?fields)) { let int i = 0; for (ty.field fld in fields) { - auto llfld = r.bcx.build.GEP(v, vec(C_int(0), C_int(i))); + auto llfld_a = r.bcx.build.GEP(av, vec(C_int(0), C_int(i))); + auto llfld_b = r.bcx.build.GEP(bv, vec(C_int(0), C_int(i))); r = f(r.bcx, - load_scalar_or_boxed(r.bcx, llfld, fld.ty), + load_scalar_or_boxed(r.bcx, llfld_a, fld.ty), + load_scalar_or_boxed(r.bcx, llfld_b, fld.ty), fld.ty); i += 1; } @@ -1545,53 +1572,69 @@ fn iter_structural_ty(@block_ctxt cx, auto variants = tag_variants(cx.fcx.ccx, tid); auto n_variants = _vec.len[ast.variant](variants); - auto lldiscrim_ptr = cx.build.GEP(v, vec(C_int(0), C_int(0))); - auto llunion_ptr = cx.build.GEP(v, vec(C_int(0), C_int(1))); - auto lldiscrim = cx.build.Load(lldiscrim_ptr); + auto lldiscrim_a_ptr = cx.build.GEP(av, vec(C_int(0), C_int(0))); + auto llunion_a_ptr = cx.build.GEP(av, vec(C_int(0), C_int(1))); + auto lldiscrim_a = cx.build.Load(lldiscrim_a_ptr); + + auto lldiscrim_b_ptr = cx.build.GEP(bv, vec(C_int(0), C_int(0))); + auto llunion_b_ptr = cx.build.GEP(bv, vec(C_int(0), C_int(1))); + auto lldiscrim_b = cx.build.Load(lldiscrim_b_ptr); auto unr_cx = new_sub_block_ctxt(cx, "tag-iter-unr"); unr_cx.build.Unreachable(); - auto llswitch = cx.build.Switch(lldiscrim, unr_cx.llbb, - n_variants); + auto llswitch = cx.build.Switch(lldiscrim_a, unr_cx.llbb, + n_variants); auto next_cx = new_sub_block_ctxt(cx, "tag-iter-next"); auto i = 0u; for (ast.variant variant in variants) { - auto variant_cx = new_sub_block_ctxt(cx, "tag-iter-variant-" + + auto variant_cx = new_sub_block_ctxt(cx, + "tag-iter-variant-" + _uint.to_str(i, 10u)); llvm.LLVMAddCase(llswitch, C_int(i as int), variant_cx.llbb); if (_vec.len[ast.variant_arg](variant.args) > 0u) { // N-ary variant. - let vec[ValueRef] vals = vec(C_int(0), C_int(1), - C_int(i as int)); - auto llvar = variant_cx.build.GEP(v, vals); auto llvarty = type_of_variant(cx.fcx.ccx, variants.(i)); auto fn_ty = ty.ann_to_type(variants.(i).ann); alt (fn_ty.struct) { case (ty.ty_fn(_, ?args, _)) { - auto llvarp = variant_cx.build. - TruncOrBitCast(llunion_ptr, T_ptr(llvarty)); + auto llvarp_a = variant_cx.build. + TruncOrBitCast(llunion_a_ptr, T_ptr(llvarty)); + + auto llvarp_b = variant_cx.build. + TruncOrBitCast(llunion_b_ptr, T_ptr(llvarty)); auto ty_params = tag_ty_params(cx.fcx.ccx, tid); auto j = 0u; for (ty.arg a in args) { auto v = vec(C_int(0), C_int(j as int)); - auto llfldp = variant_cx.build.GEP(llvarp, v); + + auto llfldp_a = + variant_cx.build.GEP(llvarp_a, v); + + auto llfldp_b = + variant_cx.build.GEP(llvarp_b, v); auto ty_subst = ty.substitute_ty_params( ty_params, tps, a.ty); - auto llfld = + auto llfld_a = load_scalar_or_boxed(variant_cx, - llfldp, + llfldp_a, ty_subst); - auto res = f(variant_cx, llfld, ty_subst); + auto llfld_b = + load_scalar_or_boxed(variant_cx, + llfldp_b, + ty_subst); + + auto res = f(variant_cx, + llfld_a, llfld_b, ty_subst); variant_cx = res.bcx; j += 1u; } @@ -1611,21 +1654,29 @@ fn iter_structural_ty(@block_ctxt cx, ret res(next_cx, C_nil()); } case (ty.ty_fn(_,_,_)) { - auto box_cell = - cx.build.GEP(v, + auto box_cell_a = + cx.build.GEP(av, + vec(C_int(0), + C_int(abi.fn_field_box))); + auto box_cell_b = + cx.build.GEP(bv, vec(C_int(0), C_int(abi.fn_field_box))); - ret iter_boxpp(cx, box_cell, f); + ret iter_boxpp(cx, box_cell_a, box_cell_b, f); } case (ty.ty_obj(_)) { - auto box_cell = - cx.build.GEP(v, + auto box_cell_a = + cx.build.GEP(av, + vec(C_int(0), + C_int(abi.obj_field_box))); + auto box_cell_b = + cx.build.GEP(bv, vec(C_int(0), C_int(abi.obj_field_box))); - ret iter_boxpp(cx, box_cell, f); + ret iter_boxpp(cx, box_cell_a, box_cell_b, f); } case (_) { - cx.fcx.ccx.sess.unimpl("type in iter_structural_ty"); + cx.fcx.ccx.sess.unimpl("type in iter_structural_ty_full"); } } ret r; @@ -1965,21 +2016,47 @@ fn trans_compare(@block_ctxt cx, ast.binop op, @ty.t t, ret res(cx, trans_scalar_compare(cx, op, t, lhs, rhs)); } else if (ty.type_is_structural(t)) { - auto scx = new_sub_block_ctxt(cx, "structural compare body"); - auto next = new_sub_block_ctxt(cx, "structural compare completion"); + auto scx = new_sub_block_ctxt(cx, "structural compare start"); + auto next = new_sub_block_ctxt(cx, "structural compare end"); cx.build.Br(scx.llbb); // Start with the assumptioin that our predicate holds. auto flag = scx.build.Alloca(T_i1()); scx.build.Store(C_integral(1, T_i1()), flag); - // Attempt to prove otherwise by inverting the sense of the comparison - // on each inner element and bailing if any succeed. + // Attempt to prove otherwise by assuming true, comparing each element + // and writing 0 + early-exiting if any comparisons fail. + + fn inner(@block_ctxt next_cx, + ValueRef flag, + ast.binop op, + @block_ctxt cx, + ValueRef av, + ValueRef bv, + @ty.t t) -> result { + // Compare av op bv + auto cnt_cx = new_sub_block_ctxt(cx, "continue comparison"); + auto stop_cx = new_sub_block_ctxt(cx, "stop comparison"); + + auto r = trans_compare(cx, op, t, av, bv); + + // if true, then carry on, else write 0 to flag, branch to 'next'. + r.bcx.build.CondBr(r.val, cnt_cx.llbb, stop_cx.llbb); + stop_cx.build.Store(C_integral(0, T_i1()), flag); + stop_cx.build.Br(next_cx.llbb); + + ret res(cnt_cx, C_nil()); + } + + // FIXME: this is wrong for tag types; need to confirm discriminants + // are equal before blindly walking over elements. - // FIXME: finish this. + auto r = iter_structural_ty_full(scx, lhs, rhs, t, + bind inner(next, flag, op, + _, _, _, _)); - auto v = scx.build.Load(flag); - scx.build.Br(next.llbb); + r.bcx.build.Br(next.llbb); + auto v = next.build.Load(flag); ret res(next, v); } else { -- cgit v1.2.3 From 687d328d7cf3fdec84ab4f07f86262dc5001738a Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Mon, 28 Feb 2011 18:26:14 -0800 Subject: rustc: Trivial cleanup: Remove unused "arity" tag --- src/comp/middle/trans.rs | 1 - 1 file changed, 1 deletion(-) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 8dc4efb7..de3f99ba 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -59,7 +59,6 @@ type glue_fns = rec(ValueRef activate_glue, ValueRef memcpy_glue, ValueRef bzero_glue); -tag arity { nullary; n_ary; } type tag_info = rec(type_handle th, mutable uint size); state type crate_ctxt = rec(session.session sess, -- cgit v1.2.3 From f239ecb5f2e46cb4c938b6bd481ec75fe137e414 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Tue, 1 Mar 2011 12:41:41 -0800 Subject: rustc: Switch from storing nullary tags as constants to storing their discriminants --- src/comp/middle/trans.rs | 53 ++++++++++++++++++++++++++++-------------------- 1 file changed, 31 insertions(+), 22 deletions(-) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index de3f99ba..61da7f53 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -59,7 +59,11 @@ type glue_fns = rec(ValueRef activate_glue, ValueRef memcpy_glue, ValueRef bzero_glue); -type tag_info = rec(type_handle th, mutable uint size); +type tag_info = rec( + type_handle th, + mutable uint size, + mutable @hashmap[ast.def_id,ValueRef] lldiscrims +); state type crate_ctxt = rec(session.session sess, ModuleRef llmod, @@ -2774,9 +2778,23 @@ fn trans_path(@block_ctxt cx, &ast.path p, &option.t[ast.def] dopt, } ret lval_generic_fn(cx, tup(params, fty), vid, ann); } else { - // Nullary variants are just scalar constants. - check (cx.fcx.ccx.item_ids.contains_key(vid)); - ret lval_val(cx, cx.fcx.ccx.item_ids.get(vid)); + // Nullary variant. + auto tag_ty = node_ann_type(cx.fcx.ccx, ann); + auto info = cx.fcx.ccx.tags.get(tag_ty); + check (info.lldiscrims.contains_key(vid)); + auto lldiscrim_gv = info.lldiscrims.get(vid); + auto lldiscrim = cx.build.Load(lldiscrim_gv); + + auto alloc_result = alloc_ty(cx, tag_ty); + auto lltagblob = alloc_result.val; + auto lltagptr = alloc_result.bcx.build.PointerCast( + lltagblob, T_ptr(type_of(cx.fcx.ccx, tag_ty))); + + auto lldiscrimptr = alloc_result.bcx.build.GEP( + lltagptr, vec(C_int(0), C_int(0))); + alloc_result.bcx.build.Store(lldiscrim, lldiscrimptr); + + ret lval_val(alloc_result.bcx, lltagptr); } } case (ast.def_const(?did)) { @@ -4637,8 +4655,14 @@ fn collect_item(&@crate_ctxt cx, @ast.item i) -> @crate_ctxt { case (ast.item_tag(_, ?variants, ?tps, ?tag_id)) { auto vi = new_def_hash[uint](); auto navi = new_def_hash[uint](); - cx.tags.insert(mk_plain_tag(tag_id), @rec(th=mk_type_handle(), - mutable size=0u)); + + auto info = @rec( + th=mk_type_handle(), + mutable size=0u, + mutable lldiscrims=@new_def_hash[ValueRef]() + ); + + cx.tags.insert(mk_plain_tag(tag_id), info); cx.items.insert(tag_id, i); } @@ -4772,22 +4796,7 @@ fn trans_constant(&@crate_ctxt cx, @ast.item it) -> @crate_ctxt { llvm.LLVMSetLinkage(discrim_gvar, lib.llvm.LLVMPrivateLinkage as llvm.Linkage); - if (_vec.len[ast.variant_arg](variant.args) == 0u) { - // Nullary tags become constants. (N-ary tags are treated - // as functions and generated later.) - - auto union_val = C_zero_byte_arr(info.size as uint); - auto val = C_struct(vec(discrim_val, union_val)); - - // FIXME: better name - auto gvar = llvm.LLVMAddGlobal(cx.llmod, val_ty(val), - _str.buf("tag")); - llvm.LLVMSetInitializer(gvar, val); - llvm.LLVMSetGlobalConstant(gvar, True); - llvm.LLVMSetLinkage(gvar, lib.llvm.LLVMPrivateLinkage - as llvm.Linkage); - cx.item_ids.insert(variant.id, gvar); - } + info.lldiscrims.insert(variant.id, discrim_gvar); i += 1u; } -- cgit v1.2.3 From 7f2398e557d4b75cbf83dc88b6740e83a8d20910 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Tue, 1 Mar 2011 13:00:50 -0800 Subject: Implement structured compare for rec, tup, tag. Un-XFAIL structured-compare.rs. --- src/comp/middle/trans.rs | 76 +++++++++++++++++++++++++++++++++++------------- 1 file changed, 55 insertions(+), 21 deletions(-) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 61da7f53..9a650da5 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -1583,24 +1583,30 @@ fn iter_structural_ty_full(@block_ctxt cx, auto llunion_b_ptr = cx.build.GEP(bv, vec(C_int(0), C_int(1))); auto lldiscrim_b = cx.build.Load(lldiscrim_b_ptr); - auto unr_cx = new_sub_block_ctxt(cx, "tag-iter-unr"); + // NB: we must hit the discriminant first so that structural + // comparison know not to proceed when the discriminants differ. + auto bcx = cx; + bcx = f(bcx, lldiscrim_a, lldiscrim_b, + plain_ty(ty.ty_int)).bcx; + + auto unr_cx = new_sub_block_ctxt(bcx, "tag-iter-unr"); unr_cx.build.Unreachable(); - auto llswitch = cx.build.Switch(lldiscrim_a, unr_cx.llbb, + auto llswitch = bcx.build.Switch(lldiscrim_a, unr_cx.llbb, n_variants); - auto next_cx = new_sub_block_ctxt(cx, "tag-iter-next"); + auto next_cx = new_sub_block_ctxt(bcx, "tag-iter-next"); auto i = 0u; for (ast.variant variant in variants) { - auto variant_cx = new_sub_block_ctxt(cx, + auto variant_cx = new_sub_block_ctxt(bcx, "tag-iter-variant-" + _uint.to_str(i, 10u)); llvm.LLVMAddCase(llswitch, C_int(i as int), variant_cx.llbb); if (_vec.len[ast.variant_arg](variant.args) > 0u) { // N-ary variant. - auto llvarty = type_of_variant(cx.fcx.ccx, variants.(i)); + auto llvarty = type_of_variant(bcx.fcx.ccx, variants.(i)); auto fn_ty = ty.ann_to_type(variants.(i).ann); alt (fn_ty.struct) { @@ -1611,7 +1617,7 @@ fn iter_structural_ty_full(@block_ctxt cx, auto llvarp_b = variant_cx.build. TruncOrBitCast(llunion_b_ptr, T_ptr(llvarty)); - auto ty_params = tag_ty_params(cx.fcx.ccx, tid); + auto ty_params = tag_ty_params(bcx.fcx.ccx, tid); auto j = 0u; for (ty.arg a in args) { @@ -2023,37 +2029,65 @@ fn trans_compare(@block_ctxt cx, ast.binop op, @ty.t t, auto next = new_sub_block_ctxt(cx, "structural compare end"); cx.build.Br(scx.llbb); - // Start with the assumptioin that our predicate holds. + /* + * We're doing lexicographic comparison here. We start with the + * assumption that the two input elements are equal. Depending on + * operator, this means that the result is either true or false; + * equality produces 'true' for ==, <= and >=. It produces 'false' for + * !=, < and >. + * + * We then move one element at a time through the structure checking + * for pairwise element equality. If we have equality, our assumption + * about overall sequence equality is not modified, so we have to move + * to the next element. + * + * If we do not have pairwise element equality, we have reached an + * element that 'decides' the lexicographic comparison. So we exit the + * loop with a flag that indicates the true/false sense of that + * decision, by testing the element again with the operator we're + * interested in. + * + * When we're lucky, LLVM should be able to fold some of these two + * tests together (as they're applied to the same operands and in some + * cases are sometimes redundant). But we don't bother trying to + * optimize combinations like that, at this level. + */ + auto flag = scx.build.Alloca(T_i1()); - scx.build.Store(C_integral(1, T_i1()), flag); - // Attempt to prove otherwise by assuming true, comparing each element - // and writing 0 + early-exiting if any comparisons fail. + alt (op) { + // ==, <= and >= default to true if they find == all the way. + case (ast.eq) { scx.build.Store(C_integral(1, T_i1()), flag); } + case (ast.le) { scx.build.Store(C_integral(1, T_i1()), flag); } + case (ast.ge) { scx.build.Store(C_integral(1, T_i1()), flag); } + case (_) { + // ==, <= and >= default to false if they find == all the way. + scx.build.Store(C_integral(0, T_i1()), flag); + } + } - fn inner(@block_ctxt next_cx, + fn inner(@block_ctxt last_cx, ValueRef flag, ast.binop op, @block_ctxt cx, ValueRef av, ValueRef bv, @ty.t t) -> result { - // Compare av op bv + auto cnt_cx = new_sub_block_ctxt(cx, "continue comparison"); auto stop_cx = new_sub_block_ctxt(cx, "stop comparison"); - auto r = trans_compare(cx, op, t, av, bv); - - // if true, then carry on, else write 0 to flag, branch to 'next'. - r.bcx.build.CondBr(r.val, cnt_cx.llbb, stop_cx.llbb); - stop_cx.build.Store(C_integral(0, T_i1()), flag); - stop_cx.build.Br(next_cx.llbb); + // First 'eq' comparison: if so, continue to next elts. + auto eq_r = trans_compare(cx, ast.eq, t, av, bv); + eq_r.bcx.build.CondBr(eq_r.val, cnt_cx.llbb, stop_cx.llbb); + // Second 'op' comparison: find out how this elt-pair decides. + auto stop_r = trans_compare(stop_cx, op, t, av, bv); + stop_r.bcx.build.Store(stop_r.val, flag); + stop_r.bcx.build.Br(last_cx.llbb); ret res(cnt_cx, C_nil()); } - // FIXME: this is wrong for tag types; need to confirm discriminants - // are equal before blindly walking over elements. - auto r = iter_structural_ty_full(scx, lhs, rhs, t, bind inner(next, flag, op, _, _, _, _)); -- cgit v1.2.3 From bdbaf0c7897366f17e36797e5c9fc7ef12fa9fce Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Tue, 1 Mar 2011 16:01:33 -0800 Subject: rustc: Factor out the align-elements logic in dynamic_size_of() --- src/comp/middle/trans.rs | 63 ++++++++++++++++++++++-------------------------- 1 file changed, 29 insertions(+), 34 deletions(-) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 9a650da5..7bdca92a 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -851,50 +851,45 @@ fn align_of(@block_ctxt cx, @ty.t t) -> result { } fn dynamic_size_of(@block_ctxt cx, @ty.t t) -> result { + fn align_elements(@block_ctxt cx, vec[@ty.t] elts) -> result { + // + // C padding rules: + // + // + // - Pad after each element so that next element is aligned. + // - Pad after final structure member so that whole structure + // is aligned to max alignment of interior. + // + auto off = C_int(0); + auto max_align = C_int(1); + auto bcx = cx; + for (@ty.t e in elts) { + auto elt_align = align_of(bcx, e); + bcx = elt_align.bcx; + auto elt_size = size_of(bcx, e); + bcx = elt_size.bcx; + auto aligned_off = align_to(bcx, off, elt_align.val); + off = cx.build.Add(aligned_off, elt_size.val); + max_align = umax(bcx, max_align, elt_align.val); + } + off = align_to(bcx, off, max_align); + ret res(bcx, off); + } + alt (t.struct) { case (ty.ty_param(?p)) { auto szptr = field_of_tydesc(cx, t, abi.tydesc_field_size); ret res(szptr.bcx, szptr.bcx.build.Load(szptr.val)); } case (ty.ty_tup(?elts)) { - // - // C padding rules: - // - // - // - Pad after each element so that next element is aligned. - // - Pad after final structure member so that whole structure - // is aligned to max alignment of interior. - // - auto off = C_int(0); - auto max_align = C_int(1); - auto bcx = cx; - for (@ty.t e in elts) { - auto elt_align = align_of(bcx, e); - bcx = elt_align.bcx; - auto elt_size = size_of(bcx, e); - bcx = elt_size.bcx; - auto aligned_off = align_to(bcx, off, elt_align.val); - off = cx.build.Add(aligned_off, elt_size.val); - max_align = umax(bcx, max_align, elt_align.val); - } - off = align_to(bcx, off, max_align); - ret res(bcx, off); + ret align_elements(cx, elts); } case (ty.ty_rec(?flds)) { - auto off = C_int(0); - auto max_align = C_int(1); - auto bcx = cx; + let vec[@ty.t] tys = vec(); for (ty.field f in flds) { - auto elt_align = align_of(bcx, f.ty); - bcx = elt_align.bcx; - auto elt_size = size_of(bcx, f.ty); - bcx = elt_size.bcx; - auto aligned_off = align_to(bcx, off, elt_align.val); - off = cx.build.Add(aligned_off, elt_size.val); - max_align = umax(bcx, max_align, elt_align.val); + tys += vec(f.ty); } - off = align_to(bcx, off, max_align); - ret res(bcx, off); + ret align_elements(cx, tys); } } } -- cgit v1.2.3 From 71f853b3fdaede022ac9b680ff2a3767379faacd Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Tue, 1 Mar 2011 16:37:17 -0800 Subject: rustc: Add logic for generic tags to dynamic_size_of(). --- src/comp/middle/trans.rs | 35 ++++++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 7bdca92a..ed61fdd7 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -891,6 +891,26 @@ fn dynamic_size_of(@block_ctxt cx, @ty.t t) -> result { } ret align_elements(cx, tys); } + case (ty.ty_tag(?tid, ?tps)) { + auto bcx = cx; + + // Compute max(variant sizes). + let ValueRef max_size = bcx.build.Alloca(T_int()); + bcx.build.Store(C_int(0), max_size); + + auto variants = tag_variants(bcx.fcx.ccx, tid); + for (ast.variant variant in variants) { + let vec[@ty.t] tys = variant_types(bcx.fcx.ccx, variant); + auto rslt = align_elements(bcx, tys); + bcx = rslt.bcx; + + auto this_size = rslt.val; + auto old_max_size = bcx.build.Load(max_size); + bcx.build.Store(umax(bcx, this_size, old_max_size), max_size); + } + + ret res(bcx, bcx.build.Load(max_size)); + } } } @@ -1450,16 +1470,25 @@ fn decr_refcnt_and_if_zero(@block_ctxt cx, // Tag information -fn type_of_variant(@crate_ctxt cx, &ast.variant v) -> TypeRef { - let vec[TypeRef] lltys = vec(); +fn variant_types(@crate_ctxt cx, &ast.variant v) -> vec[@ty.t] { + let vec[@ty.t] tys = vec(); alt (ty.ann_to_type(v.ann).struct) { case (ty.ty_fn(_, ?args, _)) { for (ty.arg arg in args) { - lltys += vec(type_of(cx, arg.ty)); + tys += vec(arg.ty); } } case (_) { fail; } } + ret tys; +} + +fn type_of_variant(@crate_ctxt cx, &ast.variant v) -> TypeRef { + let vec[TypeRef] lltys = vec(); + auto tys = variant_types(cx, v); + for (@ty.t typ in tys) { + lltys += vec(type_of(cx, typ)); + } ret T_struct(lltys); } -- cgit v1.2.3 From 9d59d33515d889f6e65f50226ba83d91a36bba0e Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Tue, 1 Mar 2011 16:49:05 -0800 Subject: rustc: Add in the size of the discriminant to generic_size_of() for tags --- src/comp/middle/trans.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index ed61fdd7..0aaf582d 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -909,7 +909,9 @@ fn dynamic_size_of(@block_ctxt cx, @ty.t t) -> result { bcx.build.Store(umax(bcx, this_size, old_max_size), max_size); } - ret res(bcx, bcx.build.Load(max_size)); + auto max_size_val = bcx.build.Load(max_size); + auto total_size = bcx.build.Add(max_size_val, llsize_of(T_int())); + ret res(bcx, total_size); } } } -- cgit v1.2.3 From 9869aebf7d21e5076e16193f2fad9c7f9446fdc6 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Tue, 1 Mar 2011 16:58:13 -0800 Subject: rustc: Remove the static "size" field from the tag info --- src/comp/middle/trans.rs | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 0aaf582d..e961acb4 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -61,7 +61,6 @@ type glue_fns = rec(ValueRef activate_glue, type tag_info = rec( type_handle th, - mutable uint size, mutable @hashmap[ast.def_id,ValueRef] lldiscrims ); @@ -4491,15 +4490,6 @@ fn trans_tag_variant(@crate_ctxt cx, ast.def_id tag_id, auto arg_tys = arg_tys_of_fn(variant.ann); copy_args_to_allocas(bcx, none[TypeRef], fn_args, arg_tys); - // FIXME: This is wrong for generic tags. We should be dynamically - // computing "size" below based on the tydescs passed in. - auto info = cx.tags.get(mk_plain_tag(tag_id)); - - auto lltagty = T_struct(vec(T_int(), T_array(T_i8(), info.size))); - - // FIXME: better name. - llvm.LLVMAddTypeName(cx.llmod, _str.buf("tag"), lltagty); - auto lldiscrimptr = bcx.build.GEP(fcx.llretptr, vec(C_int(0), C_int(0))); bcx.build.Store(C_int(index), lldiscrimptr); @@ -4718,7 +4708,6 @@ fn collect_item(&@crate_ctxt cx, @ast.item i) -> @crate_ctxt { auto info = @rec( th=mk_type_handle(), - mutable size=0u, mutable lldiscrims=@new_def_hash[ValueRef]() ); @@ -4780,6 +4769,9 @@ fn collect_tag_ctors(@crate_ctxt cx, @ast.crate crate) { fn resolve_tag_types_for_item(&@crate_ctxt cx, @ast.item i) -> @crate_ctxt { alt (i.node) { case (ast.item_tag(_, ?variants, _, ?tag_id)) { + // FIXME: This is all wrong. Now sizes and alignments are computed + // dynamically instead of up front. + auto max_align = 0u; auto max_size = 0u; @@ -4799,8 +4791,6 @@ fn resolve_tag_types_for_item(&@crate_ctxt cx, @ast.item i) -> @crate_ctxt { } } - info.size = max_size; - // FIXME: alignment is wrong here, manually insert padding I // guess :( auto tag_ty = T_struct(vec(T_int(), T_array(T_i8(), max_size))); -- cgit v1.2.3 From f1500e5872d03e3ec3b140060641136a2ff5a15a Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Sat, 26 Feb 2011 20:51:02 -0500 Subject: Add fold, typecheck and trans for expr_ext --- src/comp/middle/trans.rs | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index e961acb4..f8c3fd61 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -1957,6 +1957,8 @@ fn trans_lit(@crate_ctxt cx, &ast.lit lit, &ast.ann ann) -> ValueRef { ret C_nil(); } case (ast.lit_str(?s)) { + log "translating literal:"; + log s; ret C_str(cx, s); } } @@ -3599,6 +3601,7 @@ fn trans_rec(@block_ctxt cx, vec[ast.field] fields, fn trans_expr(@block_ctxt cx, @ast.expr e) -> result { alt (e.node) { case (ast.expr_lit(?lit, ?ann)) { + log "translating literal"; ret res(cx, trans_lit(cx.fcx.ccx, *lit, ann)); } @@ -3693,6 +3696,11 @@ fn trans_expr(@block_ctxt cx, @ast.expr e) -> result { ret trans_rec(cx, args, base, ann); } + case (ast.expr_ext(_, _, _, ?expanded, _)) { + log "translating extension"; + ret trans_expr(cx, option.get[@ast.expr](expanded)); + } + case (ast.expr_fail) { ret trans_fail(cx, e.span, "explicit failure"); } -- cgit v1.2.3 From fe5de6bfffee3c277f540517b5766547f34e81c7 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Sun, 27 Feb 2011 14:30:44 -0500 Subject: Parse parameter types for fmt extension --- src/comp/middle/trans.rs | 4 ---- 1 file changed, 4 deletions(-) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index f8c3fd61..9fee3dab 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -1957,8 +1957,6 @@ fn trans_lit(@crate_ctxt cx, &ast.lit lit, &ast.ann ann) -> ValueRef { ret C_nil(); } case (ast.lit_str(?s)) { - log "translating literal:"; - log s; ret C_str(cx, s); } } @@ -3601,7 +3599,6 @@ fn trans_rec(@block_ctxt cx, vec[ast.field] fields, fn trans_expr(@block_ctxt cx, @ast.expr e) -> result { alt (e.node) { case (ast.expr_lit(?lit, ?ann)) { - log "translating literal"; ret res(cx, trans_lit(cx.fcx.ccx, *lit, ann)); } @@ -3697,7 +3694,6 @@ fn trans_expr(@block_ctxt cx, @ast.expr e) -> result { } case (ast.expr_ext(_, _, _, ?expanded, _)) { - log "translating extension"; ret trans_expr(cx, option.get[@ast.expr](expanded)); } -- cgit v1.2.3 From c1e6f5328c3f46884ed7a7e29c780e307b02100a Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Sun, 27 Feb 2011 22:35:27 -0500 Subject: Make the expanded expression in expr_ext not optional --- src/comp/middle/trans.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 9fee3dab..2594590a 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -3694,7 +3694,7 @@ fn trans_expr(@block_ctxt cx, @ast.expr e) -> result { } case (ast.expr_ext(_, _, _, ?expanded, _)) { - ret trans_expr(cx, option.get[@ast.expr](expanded)); + ret trans_expr(cx, expanded); } case (ast.expr_fail) { -- cgit v1.2.3 From c19e4e1c2987383ef686ca831f8115a1179ecb40 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Wed, 2 Mar 2011 16:13:33 -0800 Subject: rustc: Don't have type_of_arg() rely on the particular lie told by type_of() --- src/comp/middle/trans.rs | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 2594590a..45f59841 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -621,11 +621,22 @@ fn type_of_inner(@crate_ctxt cx, @ty.t t) -> TypeRef { } fn type_of_arg(@crate_ctxt cx, &ty.arg arg) -> TypeRef { - auto ty = type_of_inner(cx, arg.ty); + alt (arg.ty.struct) { + case (ty.ty_param(_)) { + if (arg.mode == ast.alias) { + ret T_typaram_ptr(cx.tn); + } + } + case (_) { + // fall through + } + } + + auto typ = type_of_inner(cx, arg.ty); if (arg.mode == ast.alias) { - ty = T_ptr(ty); + typ = T_ptr(typ); } - ret ty; + ret typ; } // Name sanitation. LLVM will happily accept identifiers with weird names, but -- cgit v1.2.3 From 21e42ad88a388d2178770fe2ee046c4f30148da9 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Wed, 2 Mar 2011 16:23:14 -0800 Subject: rustc: For derived tydescs, explicitly store 0 for size and align when the type in question has a dynamic size --- src/comp/middle/trans.rs | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 45f59841..2258ee18 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -1201,7 +1201,19 @@ fn make_tydesc(@crate_ctxt cx, @ty.t t, vec[ast.def_id] typaram_defs) { auto dg = make_drop_glue; auto drop_glue = make_generic_glue(cx, t, "drop", dg, typaram_defs); - auto llty = type_of(cx, t); + auto llsize; + auto llalign; + if (!ty.type_has_dynamic_size(t)) { + auto llty = type_of(cx, t); + llsize = llsize_of(llty); + llalign = llalign_of(llty); + } else { + // These will be overwritten as the derived tydesc is generated, so + // we create placeholder values. + llsize = C_int(0); + llalign = C_int(0); + } + auto glue_fn_ty = T_ptr(T_glue_fn(cx.tn)); // FIXME: this adjustment has to do with the ridiculous encoding of @@ -1218,8 +1230,8 @@ fn make_tydesc(@crate_ctxt cx, @ty.t t, vec[ast.def_id] typaram_defs) { auto gvar = llvm.LLVMAddGlobal(cx.llmod, T_tydesc(cx.tn), _str.buf(name)); auto tydesc = C_struct(vec(C_null(T_ptr(T_ptr(T_tydesc(cx.tn)))), - llsize_of(llty), - llalign_of(llty), + llsize, + llalign, off(gvar, take_glue), // take_glue_off off(gvar, drop_glue), // drop_glue_off C_null(glue_fn_ty), // free_glue_off -- cgit v1.2.3 From 5ebb91f24d84391f6c821c54fb8c497964eac6c3 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Wed, 2 Mar 2011 16:31:20 -0800 Subject: rustc: Teach iter_structural_ty about dynamically-sized tuples and records --- src/comp/middle/trans.rs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 2258ee18..f58fe188 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -1596,8 +1596,10 @@ fn iter_structural_ty_full(@block_ctxt cx, case (ty.ty_tup(?args)) { let int i = 0; for (@ty.t arg in args) { - auto elt_a = r.bcx.build.GEP(av, vec(C_int(0), C_int(i))); - auto elt_b = r.bcx.build.GEP(bv, vec(C_int(0), C_int(i))); + r = GEP_tup_like(r.bcx, t, av, vec(0, i)); + auto elt_a = r.val; + r = GEP_tup_like(r.bcx, t, bv, vec(0, i)); + auto elt_b = r.val; r = f(r.bcx, load_scalar_or_boxed(r.bcx, elt_a, arg), load_scalar_or_boxed(r.bcx, elt_b, arg), @@ -1608,8 +1610,10 @@ fn iter_structural_ty_full(@block_ctxt cx, case (ty.ty_rec(?fields)) { let int i = 0; for (ty.field fld in fields) { - auto llfld_a = r.bcx.build.GEP(av, vec(C_int(0), C_int(i))); - auto llfld_b = r.bcx.build.GEP(bv, vec(C_int(0), C_int(i))); + r = GEP_tup_like(r.bcx, t, av, vec(0, i)); + auto llfld_a = r.val; + r = GEP_tup_like(r.bcx, t, bv, vec(0, i)); + auto llfld_b = r.val; r = f(r.bcx, load_scalar_or_boxed(r.bcx, llfld_a, fld.ty), load_scalar_or_boxed(r.bcx, llfld_b, fld.ty), -- cgit v1.2.3 From dddeba19d33a1aa2e7681ae84424dbe4d7b510b7 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Wed, 2 Mar 2011 16:42:09 -0800 Subject: Sketch out some more pieces of vec-append. --- src/comp/middle/trans.rs | 132 ++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 119 insertions(+), 13 deletions(-) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index f58fe188..2cd26664 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -57,7 +57,8 @@ type glue_fns = rec(ValueRef activate_glue, vec[ValueRef] upcall_glues, ValueRef no_op_type_glue, ValueRef memcpy_glue, - ValueRef bzero_glue); + ValueRef bzero_glue, + ValueRef vec_grow_glue); type tag_info = rec( type_handle th, @@ -809,7 +810,7 @@ fn trans_upcall(@block_ctxt cx, str name, vec[ValueRef] args) -> result { } fn trans_non_gc_free(@block_ctxt cx, ValueRef v) -> result { - ret trans_upcall(cx, "upcall_free", vec(cx.build.PtrToInt(v, T_int()), + ret trans_upcall(cx, "upcall_free", vec(vp2i(cx, v), C_int(0))); } @@ -1065,7 +1066,7 @@ fn trans_malloc_inner(@block_ctxt cx, TypeRef llptr_ty) -> result { auto tydesc = C_int(0); auto sz = llsize_of(llbody_ty); auto sub = trans_upcall(cx, "upcall_malloc", vec(sz, tydesc)); - sub.val = sub.bcx.build.IntToPtr(sub.val, llptr_ty); + sub.val = vi2p(sub.bcx, sub.val, llptr_ty); ret sub; } @@ -1181,10 +1182,10 @@ fn get_tydesc(&@block_ctxt cx, @ty.t t) -> result { sz.val, align.val, C_int((1u + n_params) as int), - bcx.build.PtrToInt(tydescs, T_int()))); + vp2i(bcx, tydescs))); - ret res(v.bcx, v.bcx.build.IntToPtr(v.val, - T_ptr(T_tydesc(cx.fcx.ccx.tn)))); + ret res(v.bcx, vi2p(v.bcx, v.val, + T_ptr(T_tydesc(cx.fcx.ccx.tn)))); } // Otherwise, generate a tydesc if necessary, and return it. @@ -1829,9 +1830,9 @@ fn call_tydesc_glue_full(@block_ctxt cx, ValueRef v, // glue-pointer-constants in the tydesc records: They are tydesc-relative // displacements. This is purely for compatibility with rustboot and // should go when it is discarded. - llfn = cx.build.IntToPtr(cx.build.Add(cx.build.PtrToInt(llfn, T_int()), - cx.build.PtrToInt(tydesc, T_int())), - val_ty(llfn)); + llfn = vi2p(cx, cx.build.Add(vp2i(cx, llfn), + vp2i(cx, tydesc)), + val_ty(llfn)); cx.build.FastCall(llfn, vec(C_null(T_ptr(T_nil())), cx.fcx.lltaskptr, @@ -2221,11 +2222,30 @@ fn trans_integral_compare(@block_ctxt cx, ast.binop op, @ty.t intype, ret cx.build.ICmp(cmp, lhs, rhs); } +fn trans_sequence_append(@block_ctxt cx, @ty.t t, + ValueRef lhs, ValueRef rhs) -> result { + cx.fcx.ccx.sess.unimpl("sequence append"); + fail; +} + +fn trans_sequence_add(@block_ctxt cx, @ty.t t, + ValueRef lhs, ValueRef rhs) -> result { + auto r = alloc_ty(cx, t); + r = copy_ty(r.bcx, INIT, r.val, lhs, t); + ret trans_sequence_append(r.bcx, t, lhs, rhs); +} + + fn trans_eager_binop(@block_ctxt cx, ast.binop op, @ty.t intype, ValueRef lhs, ValueRef rhs) -> result { alt (op) { - case (ast.add) { ret res(cx, cx.build.Add(lhs, rhs)); } + case (ast.add) { + if (ty.type_is_sequence(intype)) { + ret trans_sequence_add(cx, intype, lhs, rhs); + } + ret res(cx, cx.build.Add(lhs, rhs)); + } case (ast.sub) { ret res(cx, cx.build.Sub(lhs, rhs)); } case (ast.mul) { ret res(cx, cx.build.Mul(lhs, rhs)); } @@ -3539,7 +3559,7 @@ fn trans_vec(@block_ctxt cx, vec[@ast.expr] args, bcx = sub.bcx; auto llty = type_of(bcx.fcx.ccx, t); - auto vec_val = bcx.build.IntToPtr(sub.val, llty); + auto vec_val = vi2p(bcx, sub.val, llty); find_scope_cx(bcx).cleanups += clean(bind drop_ty(_, vec_val, t)); auto body = bcx.build.GEP(vec_val, vec(C_int(0), @@ -3782,7 +3802,7 @@ fn trans_log(@block_ctxt cx, @ast.expr e) -> result { auto e_ty = ty.expr_ty(e); alt (e_ty.struct) { case (ty.ty_str) { - auto v = sub.bcx.build.PtrToInt(sub.val, T_int()); + auto v = vp2i(sub.bcx, sub.val); ret trans_upcall(sub.bcx, "upcall_log_str", vec(v)); @@ -4907,6 +4927,16 @@ fn trans_constants(@crate_ctxt cx, @ast.crate crate) { fold.fold_crate[@crate_ctxt](cx, fld, crate); } + +fn vp2i(@block_ctxt cx, ValueRef v) -> ValueRef { + ret cx.build.PtrToInt(v, T_int()); +} + + +fn vi2p(@block_ctxt cx, ValueRef v, TypeRef t) -> ValueRef { + ret cx.build.IntToPtr(v, t); +} + fn p2i(ValueRef v) -> ValueRef { ret llvm.LLVMConstPtrToInt(v, T_int()); } @@ -5172,6 +5202,80 @@ fn make_bzero_glue(ModuleRef llmod) -> ValueRef { ret fun; } +fn make_vec_grow_glue(ModuleRef llmod, type_names tn) -> ValueRef { + /* + * Args to vec_grow_glue: + * + * 0. (Implicit) task ptr + * + * 1. Pointer to the tydesc of the vec, so that we can tell if it's gc + * mem, and have a tydesc to pass to malloc if we're allocating anew. + * + * 2. Pointer to the tydesc of the vec's stored element type, so that + * elements can be copied to a newly alloc'ed vec if one must be + * created. + * + * 3. Alias to vec that needs to grow (i.e. ptr to ptr to rust_vec). + * + * 4. Number of bytes of growth requested + * + */ + + auto ty = T_fn(vec(T_taskptr(tn), + T_ptr(T_tydesc(tn)), + T_ptr(T_tydesc(tn)), + T_ptr(T_ptr(T_vec(T_int()))), // a lie. + T_int()), T_void()); + + auto llfn = decl_fastcall_fn(llmod, abi.vec_grow_glue_name(), ty); + ret llfn; +} + +fn trans_vec_grow_glue(@crate_ctxt cx) { + + auto llfn = cx.glues.vec_grow_glue; + + let ValueRef lltaskptr = llvm.LLVMGetParam(llfn, 0u); + let ValueRef llvec_tydesc = llvm.LLVMGetParam(llfn, 1u); + let ValueRef llelt_tydesc = llvm.LLVMGetParam(llfn, 2u); + let ValueRef llvec_ptr = llvm.LLVMGetParam(llfn, 3u); + let ValueRef llnbytes = llvm.LLVMGetParam(llfn, 4u); + + auto fcx = @rec(llfn=llfn, + lltaskptr=lltaskptr, + llenv=C_null(T_ptr(T_nil())), + llretptr=C_null(T_ptr(T_nil())), + mutable llself=none[ValueRef], + mutable lliterbody=none[ValueRef], + llargs=new_def_hash[ValueRef](), + llobjfields=new_def_hash[ValueRef](), + lllocals=new_def_hash[ValueRef](), + lltydescs=new_def_hash[ValueRef](), + ccx=cx); + + auto bcx = new_top_block_ctxt(fcx); + + auto llneed_copy_ptr = bcx.build.Alloca(T_int()); + + auto llnew_vec_res = + trans_upcall(bcx, "upcall_vec_grow", + vec(vp2i(bcx, bcx.build.Load(llvec_ptr)), + llnbytes, + vp2i(bcx, llneed_copy_ptr), + vp2i(bcx, llvec_tydesc))); + + bcx = llnew_vec_res.bcx; + auto llnew_vec = vi2p(bcx, + llnew_vec_res.val, + T_ptr(T_vec(T_int())) // a lie. + ); + + // FIXME: complete this. + + bcx.build.RetVoid(); +} + + fn make_glues(ModuleRef llmod, type_names tn) -> @glue_fns { ret @rec(activate_glue = decl_glue(llmod, tn, abi.activate_glue_name()), yield_glue = decl_glue(llmod, tn, abi.yield_glue_name()), @@ -5197,7 +5301,8 @@ fn make_glues(ModuleRef llmod, type_names tn) -> @glue_fns { abi.n_upcall_glues as uint), no_op_type_glue = make_no_op_type_glue(llmod, tn), memcpy_glue = make_memcpy_glue(llmod), - bzero_glue = make_bzero_glue(llmod)); + bzero_glue = make_bzero_glue(llmod), + vec_grow_glue = make_vec_grow_glue(llmod, tn)); } fn trans_crate(session.session sess, @ast.crate crate, str output, @@ -5256,6 +5361,7 @@ fn trans_crate(session.session sess, @ast.crate crate, str output, trans_mod(cx, crate.node.module); trans_exit_task_glue(cx); + trans_vec_grow_glue(cx); create_crate_constant(cx); if (!shared) { trans_main_fn(cx, cx.crate_ptr); -- cgit v1.2.3 From ec5c5a750d2b9ed7b32902f216a1ae28604c4acb Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Wed, 2 Mar 2011 17:24:22 -0800 Subject: rustc: Rework the API for trans_malloc() to be generic-aware and so that clients don't need to call trans_malloc_inner() --- src/comp/middle/trans.rs | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 2cd26664..8b0747d5 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -1060,22 +1060,26 @@ fn GEP_tup_like(@block_ctxt cx, @ty.t t, } -fn trans_malloc_inner(@block_ctxt cx, TypeRef llptr_ty) -> result { - auto llbody_ty = lib.llvm.llvm.LLVMGetElementType(llptr_ty); +fn trans_raw_malloc(@block_ctxt cx, TypeRef llptr_ty, ValueRef llsize) + -> result { // FIXME: need a table to collect tydesc globals. auto tydesc = C_int(0); - auto sz = llsize_of(llbody_ty); - auto sub = trans_upcall(cx, "upcall_malloc", vec(sz, tydesc)); - sub.val = vi2p(sub.bcx, sub.val, llptr_ty); - ret sub; + auto rslt = trans_upcall(cx, "upcall_malloc", vec(llsize, tydesc)); + rslt = res(rslt.bcx, vi2p(cx, rslt.val, llptr_ty)); + ret rslt; +} + +fn trans_malloc_without_cleanup(@block_ctxt cx, @ty.t t) -> result { + auto llty = type_of(cx.fcx.ccx, t); + auto rslt = size_of(cx, t); + ret trans_raw_malloc(rslt.bcx, llty, rslt.val); } fn trans_malloc(@block_ctxt cx, @ty.t t) -> result { auto scope_cx = find_scope_cx(cx); - auto llptr_ty = type_of(cx.fcx.ccx, t); - auto sub = trans_malloc_inner(cx, llptr_ty); - scope_cx.cleanups += clean(bind drop_ty(_, sub.val, t)); - ret sub; + auto rslt = trans_malloc_without_cleanup(cx, t); + scope_cx.cleanups += clean(bind drop_ty(_, rslt.val, t)); + ret rslt; } @@ -3216,7 +3220,9 @@ fn trans_bind(@block_ctxt cx, @ast.expr f, ty_param_count); // Malloc a box for the body. - auto r = trans_malloc_inner(bcx, llclosure_ty); + // FIXME: this isn't generic-safe + auto r = trans_raw_malloc(bcx, llclosure_ty, + llsize_of(llvm.LLVMGetElementType(llclosure_ty))); auto box = r.val; bcx = r.bcx; auto rc = bcx.build.GEP(box, @@ -4453,7 +4459,8 @@ fn trans_obj(@crate_ctxt cx, &ast._obj ob, ast.def_id oid, let TypeRef llboxed_body_ty = type_of(cx, boxed_body_ty); // Malloc a box for the body. - auto box = trans_malloc_inner(bcx, llboxed_body_ty); + auto box = trans_raw_malloc(bcx, llboxed_body_ty, + llsize_of(llvm.LLVMGetElementType(llboxed_body_ty))); bcx = box.bcx; auto rc = GEP_tup_like(bcx, boxed_body_ty, box.val, vec(0, abi.box_rc_field_refcnt)); -- cgit v1.2.3 From 792af12a3ca706ec4f0fcc6af006371c7f96abe0 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Wed, 2 Mar 2011 18:06:53 -0800 Subject: rustc: Remove unused call to type_of() in trans_tup() --- src/comp/middle/trans.rs | 1 - 1 file changed, 1 deletion(-) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 8b0747d5..4708ffc5 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -3520,7 +3520,6 @@ fn trans_tup(@block_ctxt cx, vec[ast.elt] elts, &ast.ann ann) -> result { auto bcx = cx; auto t = node_ann_type(bcx.fcx.ccx, ann); - auto llty = type_of(bcx.fcx.ccx, t); auto tup_res = alloc_ty(bcx, t); auto tup_val = tup_res.val; bcx = tup_res.bcx; -- cgit v1.2.3 From 675f762621a0e2bb7d746e82bcafa05650786b94 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Wed, 2 Mar 2011 18:23:38 -0800 Subject: rustc: Have make_generic_glue pass an opaque type instead of an incorrect type in the case of dynamically sized types --- src/comp/middle/trans.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 4708ffc5..3d4f44ea 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -1267,7 +1267,9 @@ fn make_generic_glue(@crate_ctxt cx, @ty.t t, str name, auto re; if (!ty.type_is_scalar(t)) { auto llty; - if (ty.type_is_structural(t)) { + if (ty.type_has_dynamic_size(t)) { + llty = T_ptr(T_i8()); + } else if (ty.type_is_structural(t)) { llty = T_ptr(type_of(cx, t)); } else { llty = type_of(cx, t); -- cgit v1.2.3 From 7ab58db4d02443fdfd68e135224a79fe3a212bda Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Wed, 2 Mar 2011 18:36:03 -0800 Subject: rustc: Use llsize_of rather than size_of in trans_malloc_without_cleanup(). Should put out burning tinderbox... --- src/comp/middle/trans.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 3d4f44ea..4d1bfde7 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -1071,8 +1071,8 @@ fn trans_raw_malloc(@block_ctxt cx, TypeRef llptr_ty, ValueRef llsize) fn trans_malloc_without_cleanup(@block_ctxt cx, @ty.t t) -> result { auto llty = type_of(cx.fcx.ccx, t); - auto rslt = size_of(cx, t); - ret trans_raw_malloc(rslt.bcx, llty, rslt.val); + auto llsize = llsize_of(llvm.LLVMGetElementType(llty)); + ret trans_raw_malloc(cx, llty, llsize); } fn trans_malloc(@block_ctxt cx, @ty.t t) -> result { -- cgit v1.2.3 From fae6870d05683e372dd13ec9849dab0b55a66fb8 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Thu, 3 Mar 2011 11:49:35 -0800 Subject: rustc: Make populate_fn_ctxt_from_llself() generic-aware --- src/comp/middle/trans.rs | 92 ++++++++++++++++++++++++++++-------------------- 1 file changed, 54 insertions(+), 38 deletions(-) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 4d1bfde7..f47aed2d 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -401,20 +401,19 @@ fn T_captured_tydescs(type_names tn, uint n) -> TypeRef { ret T_struct(_vec.init_elt[TypeRef](T_ptr(T_tydesc(tn)), n)); } -fn T_obj(type_names tn, uint n_captured_tydescs, - TypeRef llfields_ty) -> TypeRef { - ret T_struct(vec(T_ptr(T_tydesc(tn)), - T_captured_tydescs(tn, n_captured_tydescs), - llfields_ty)); -} +fn T_obj_ptr(type_names tn, uint n_captured_tydescs) -> TypeRef { + // This function is not publicly exposed because it returns an incomplete + // type. The dynamically-sized fields follow the captured tydescs. + fn T_obj(type_names tn, uint n_captured_tydescs) -> TypeRef { + ret T_struct(vec(T_ptr(T_tydesc(tn)), + T_captured_tydescs(tn, n_captured_tydescs))); + } -fn T_obj_ptr(type_names tn, uint n_captured_tydescs, - TypeRef llfields_ty) -> TypeRef { - ret T_ptr(T_box(T_obj(tn, n_captured_tydescs, llfields_ty))); + ret T_ptr(T_box(T_obj(tn, n_captured_tydescs))); } fn T_opaque_obj_ptr(type_names tn) -> TypeRef { - ret T_obj_ptr(tn, 0u, T_nil()); + ret T_obj_ptr(tn, 0u); } @@ -4265,56 +4264,73 @@ fn ret_ty_of_fn(ast.ann ann) -> @ty.t { ret ret_ty_of_fn_ty(ty.ann_to_type(ann)); } -fn populate_fn_ctxt_from_llself(@block_ctxt cx, ValueRef llself) { +fn populate_fn_ctxt_from_llself(@block_ctxt cx, ValueRef llself) -> result { + auto bcx = cx; - let vec[TypeRef] llfield_tys = vec(); + let vec[@ty.t] field_tys = vec(); - for (ast.obj_field f in cx.fcx.ccx.obj_fields) { - llfield_tys += node_type(cx.fcx.ccx, f.ann); + for (ast.obj_field f in bcx.fcx.ccx.obj_fields) { + field_tys += vec(node_ann_type(bcx.fcx.ccx, f.ann)); } - auto n_typarams = _vec.len[ast.ty_param](cx.fcx.ccx.obj_typarams); - let TypeRef llobj_box_ty = T_obj_ptr(cx.fcx.ccx.tn, n_typarams, - T_struct(llfield_tys)); + // Synthesize a tuple type for the fields so that GEP_tup_like() can work + // its magic. + auto fields_tup_ty = ty.plain_ty(ty.ty_tup(field_tys)); + + auto n_typarams = _vec.len[ast.ty_param](bcx.fcx.ccx.obj_typarams); + let TypeRef llobj_box_ty = T_obj_ptr(bcx.fcx.ccx.tn, n_typarams); auto box_cell = - cx.build.GEP(llself, - vec(C_int(0), - C_int(abi.obj_field_box))); + bcx.build.GEP(llself, + vec(C_int(0), + C_int(abi.obj_field_box))); - auto box_ptr = cx.build.Load(box_cell); + auto box_ptr = bcx.build.Load(box_cell); - box_ptr = cx.build.PointerCast(box_ptr, llobj_box_ty); + box_ptr = bcx.build.PointerCast(box_ptr, llobj_box_ty); - auto obj_typarams = cx.build.GEP(box_ptr, + auto obj_typarams = bcx.build.GEP(box_ptr, vec(C_int(0), C_int(abi.box_rc_field_body), C_int(abi.obj_body_elt_typarams))); - auto obj_fields = cx.build.GEP(box_ptr, - vec(C_int(0), - C_int(abi.box_rc_field_body), - C_int(abi.obj_body_elt_fields))); + // The object fields immediately follow the type parameters, so we skip + // over them to get the pointer. + auto obj_fields = bcx.build.Add(vp2i(bcx, obj_typarams), + llsize_of(llvm.LLVMGetElementType(val_ty(obj_typarams)))); + + // If we can (i.e. the type is statically sized), then cast the resulting + // fields pointer to the appropriate LLVM type. If not, just leave it as + // i8 *. + if (!ty.type_has_dynamic_size(fields_tup_ty)) { + auto llfields_ty = type_of(bcx.fcx.ccx, fields_tup_ty); + obj_fields = vi2p(bcx, obj_fields, T_ptr(llfields_ty)); + } else { + obj_fields = vi2p(bcx, obj_fields, T_ptr(T_i8())); + } + let int i = 0; - for (ast.ty_param p in cx.fcx.ccx.obj_typarams) { - let ValueRef lltyparam = cx.build.GEP(obj_typarams, - vec(C_int(0), - C_int(i))); - lltyparam = cx.build.Load(lltyparam); - cx.fcx.lltydescs.insert(p.id, lltyparam); + for (ast.ty_param p in bcx.fcx.ccx.obj_typarams) { + let ValueRef lltyparam = bcx.build.GEP(obj_typarams, + vec(C_int(0), + C_int(i))); + lltyparam = bcx.build.Load(lltyparam); + bcx.fcx.lltydescs.insert(p.id, lltyparam); i += 1; } i = 0; - for (ast.obj_field f in cx.fcx.ccx.obj_fields) { - let ValueRef llfield = cx.build.GEP(obj_fields, - vec(C_int(0), - C_int(i))); + for (ast.obj_field f in bcx.fcx.ccx.obj_fields) { + auto rslt = GEP_tup_like(bcx, fields_tup_ty, obj_fields, vec(0, i)); + bcx = rslt.bcx; + auto llfield = rslt.val; cx.fcx.llobjfields.insert(f.id, llfield); i += 1; } + + ret res(bcx, C_nil()); } fn trans_fn(@crate_ctxt cx, &ast._fn f, ast.def_id fid, @@ -4335,7 +4351,7 @@ fn trans_fn(@crate_ctxt cx, &ast._fn f, ast.def_id fid, alt (fcx.llself) { case (some[ValueRef](?llself)) { - populate_fn_ctxt_from_llself(bcx, llself); + bcx = populate_fn_ctxt_from_llself(bcx, llself).bcx; } case (_) { } -- cgit v1.2.3 From da8058ff836a4e9a30e36ef96449dfef576b13e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20=C3=81vila=20de=20Esp=C3=ADndola?= Date: Thu, 3 Mar 2011 16:43:47 -0500 Subject: Handle native types in calls. --- src/comp/middle/trans.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index f47aed2d..7e463ae9 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -1445,6 +1445,7 @@ fn make_drop_glue(@block_ctxt cx, ValueRef v, @ty.t t) -> result { bind drop_ty(_, _, _)); } else if (ty.type_is_scalar(t) || + ty.type_is_native(t) || ty.type_is_nil(t)) { ret res(cx, C_nil()); } @@ -1927,7 +1928,7 @@ fn copy_ty(@block_ctxt cx, ValueRef dst, ValueRef src, @ty.t t) -> result { - if (ty.type_is_scalar(t)) { + if (ty.type_is_scalar(t) || ty.type_is_native(t)) { ret res(cx, cx.build.Store(src, dst)); } else if (ty.type_is_nil(t)) { @@ -3795,7 +3796,7 @@ fn trans_expr(@block_ctxt cx, @ast.expr e) -> result { fn load_scalar_or_boxed(@block_ctxt cx, ValueRef v, @ty.t t) -> ValueRef { - if (ty.type_is_scalar(t) || ty.type_is_boxed(t)) { + if (ty.type_is_scalar(t) || ty.type_is_boxed(t) || ty.type_is_native(t)) { ret cx.build.Load(v); } else { ret v; -- cgit v1.2.3 From 5dba7a77d2c7396989262da3de5ea055bed151bc Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Thu, 3 Mar 2011 14:02:29 -0800 Subject: rustc: Don't call type_of() in GEP_tup_like() if there are any type parameters in the result --- src/comp/middle/trans.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 7e463ae9..9587b008 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -1049,13 +1049,13 @@ fn GEP_tup_like(@block_ctxt cx, @ty.t t, bcx = sz.bcx; auto raw = bcx.build.PointerCast(base, T_ptr(T_i8())); auto bumped = bcx.build.GEP(raw, vec(sz.val)); - alt (s.target.struct) { - case (ty.ty_param(_)) { ret res(bcx, bumped); } - case (_) { - auto ty = T_ptr(type_of(bcx.fcx.ccx, s.target)); - ret res(bcx, bcx.build.PointerCast(bumped, ty)); - } + + if (ty.type_has_dynamic_size(s.target)) { + ret res(bcx, bumped); } + + auto typ = T_ptr(type_of(bcx.fcx.ccx, s.target)); + ret res(bcx, bcx.build.PointerCast(bumped, typ)); } -- cgit v1.2.3 From 2a241ece3a8fdaa536946b29eeab4524da164903 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Thu, 3 Mar 2011 14:10:36 -0800 Subject: rustc: Disallow calling type_of() on dynamically-sized types --- src/comp/middle/trans.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 9587b008..65f5b135 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -417,7 +417,17 @@ fn T_opaque_obj_ptr(type_names tn) -> TypeRef { } +// This function now fails if called on a type with dynamic size (as its +// return value was always meaningless in that case anyhow). Beware! +// +// TODO: Enforce via a predicate. fn type_of(@crate_ctxt cx, @ty.t t) -> TypeRef { + if (ty.type_has_dynamic_size(t)) { + log "type_of() called on a type with dynamic size: " + + ty.ty_to_str(t); + fail; + } + ret type_of_inner(cx, t); } -- cgit v1.2.3 From f44fea8b6d77c24785fc351c5ca334df47b804b3 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Thu, 3 Mar 2011 15:52:54 -0800 Subject: rustc: Teach trans_tag_variant() about generic tags --- src/comp/middle/trans.rs | 46 +++++++++++++++++++++++++++++++++++----------- 1 file changed, 35 insertions(+), 11 deletions(-) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 65f5b135..e85bcbbc 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -397,6 +397,16 @@ fn T_opaque_closure_ptr(type_names tn) -> TypeRef { ret t; } +fn T_opaque_tag_ptr(type_names tn) -> TypeRef { + auto s = "*tag"; + if (tn.name_has_type(s)) { + ret tn.get_type(s); + } + auto t = T_ptr(T_struct(vec(T_int(), T_i8()))); + tn.associate(s, t); + ret t; +} + fn T_captured_tydescs(type_names tn, uint n) -> TypeRef { ret T_struct(_vec.init_elt[TypeRef](T_ptr(T_tydesc(tn)), n)); } @@ -4576,27 +4586,41 @@ fn trans_tag_variant(@crate_ctxt cx, ast.def_id tag_id, auto arg_tys = arg_tys_of_fn(variant.ann); copy_args_to_allocas(bcx, none[TypeRef], fn_args, arg_tys); - auto lldiscrimptr = bcx.build.GEP(fcx.llretptr, + // Now synthesize a tuple type for the arguments, so that GEP_tup_like() + // will know what the data part of the variant looks like. + let vec[@ty.t] true_arg_tys = vec(); + for (ty.arg a in arg_tys) { + true_arg_tys += vec(a.ty); + } + auto tup_ty = ty.plain_ty(ty.ty_tup(true_arg_tys)); + + // Cast the tag to a type we can GEP into. + auto lltagptr = bcx.build.PointerCast(fcx.llretptr, + T_opaque_tag_ptr(fcx.ccx.tn)); + + auto lldiscrimptr = bcx.build.GEP(lltagptr, vec(C_int(0), C_int(0))); bcx.build.Store(C_int(index), lldiscrimptr); - auto llblobptr = bcx.build.GEP(fcx.llretptr, + auto llblobptr = bcx.build.GEP(lltagptr, vec(C_int(0), C_int(1))); - // First, generate the union type. - let vec[TypeRef] llargtys = vec(); - for (ty.arg arg in arg_tys) { - llargtys += vec(type_of(cx, arg.ty)); + // Cast the blob pointer to the appropriate type, if we need to (i.e. if + // the blob pointer isn't dynamically sized). + let ValueRef llunionptr; + if (!ty.type_has_dynamic_size(tup_ty)) { + auto llty = type_of(cx, tup_ty); + llunionptr = bcx.build.TruncOrBitCast(llblobptr, T_ptr(llty)); + } else { + llunionptr = llblobptr; } - auto llunionty = T_struct(llargtys); - auto llunionptr = bcx.build.TruncOrBitCast(llblobptr, T_ptr(llunionty)); - i = 0u; for (ast.variant_arg va in variant.args) { auto llargval = bcx.build.Load(fcx.llargs.get(va.id)); - auto lldestptr = bcx.build.GEP(llunionptr, - vec(C_int(0), C_int(i as int))); + auto rslt = GEP_tup_like(bcx, tup_ty, llunionptr, vec(0, i as int)); + bcx = rslt.bcx; + auto lldestptr = rslt.val; bcx.build.Store(llargval, lldestptr); i += 1u; -- cgit v1.2.3 From 39b05632057a9d9e71cbf7b486c26f70c84f0c14 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Thu, 3 Mar 2011 16:18:43 -0800 Subject: rustc: Remove dead code that used to generate tag constants from trans_constant() --- src/comp/middle/trans.rs | 6 ------ 1 file changed, 6 deletions(-) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index e85bcbbc..5f163d10 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -4932,12 +4932,6 @@ fn trans_constant(&@crate_ctxt cx, @ast.item it) -> @crate_ctxt { case (ast.item_tag(_, ?variants, _, ?tag_id)) { auto info = cx.tags.get(mk_plain_tag(tag_id)); - auto tag_ty = llvm.LLVMResolveTypeHandle(info.th.llth); - check (llvm.LLVMCountStructElementTypes(tag_ty) == 2u); - auto elts = vec(0 as TypeRef, 0 as TypeRef); - llvm.LLVMGetStructElementTypes(tag_ty, _vec.buf[TypeRef](elts)); - auto union_ty = elts.(1); - auto i = 0u; auto n_variants = _vec.len[ast.variant](variants); while (i < n_variants) { -- cgit v1.2.3 From f6682280f3e3e8923c283df8277964b6cbf8d8b8 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Thu, 3 Mar 2011 16:54:15 -0800 Subject: rustc: Add support for folding over tag types --- src/comp/middle/trans.rs | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 5f163d10..98433305 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -1144,6 +1144,8 @@ fn linearize_ty_params(@block_ctxt cx, @ty.t t) } ret t; } + + fn fold_tag_ty(@ty.t t) -> @ty.t { ret t; } } -- cgit v1.2.3 From 04a0a6fbef0cc7c3c89fbbbeff68ab2c999d9592 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Thu, 3 Mar 2011 17:09:20 -0800 Subject: Revert "rustc: Add support for folding over tag types" as it's unnecessary. Oops. --- src/comp/middle/trans.rs | 2 -- 1 file changed, 2 deletions(-) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 98433305..5f163d10 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -1144,8 +1144,6 @@ fn linearize_ty_params(@block_ctxt cx, @ty.t t) } ret t; } - - fn fold_tag_ty(@ty.t t) -> @ty.t { ret t; } } -- cgit v1.2.3 From b4a85c7b583b75eade31d698ad9862f5f98e8857 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 3 Mar 2011 17:27:35 -0800 Subject: Factor out and generalize sequence pointer walking, for use in vec-grow. --- src/comp/middle/trans.rs | 110 ++++++++++++++++++++++++++++++++++------------- 1 file changed, 80 insertions(+), 30 deletions(-) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 5f163d10..2af5359a 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -1770,6 +1770,81 @@ fn iter_structural_ty_full(@block_ctxt cx, ret r; } +// Iterates through a pair of sequences, until the src* hits the src_lim*. +fn iter_sequence_pair_inner(@block_ctxt cx, + ValueRef dst, // elt* + ValueRef src, // elt* + ValueRef src_lim, // elt* + @ty.t elt_ty, + val_pair_and_ty_fn f) -> result { + + auto bcx = cx; + + auto llunit_ty = type_of(cx.fcx.ccx, elt_ty); + auto unit_sz = size_of(bcx, elt_ty); + bcx = unit_sz.bcx; + + let ValueRef src_int = vp2i(bcx, src); + let ValueRef src_lim_int = vp2i(bcx, src_lim); + let ValueRef dst_int = vp2i(bcx, dst); + + auto cond_cx = new_scope_block_ctxt(cx, "sequence-iter cond"); + auto body_cx = new_scope_block_ctxt(cx, "sequence-iter body"); + auto next_cx = new_sub_block_ctxt(cx, "next"); + + bcx.build.Br(cond_cx.llbb); + + let ValueRef src_curr = cond_cx.build.Phi(T_int(), + vec(src_int), vec(bcx.llbb)); + let ValueRef dst_curr = cond_cx.build.Phi(T_int(), + vec(dst_int), vec(bcx.llbb)); + + auto end_test = cond_cx.build.ICmp(lib.llvm.LLVMIntNE, + src_curr, src_lim_int); + + cond_cx.build.CondBr(end_test, body_cx.llbb, next_cx.llbb); + + auto src_curr_ptr = vi2p(body_cx, src_curr, T_ptr(llunit_ty)); + auto dst_curr_ptr = vi2p(body_cx, dst_curr, T_ptr(llunit_ty)); + + auto body_res = f(body_cx, + dst_curr_ptr, + load_scalar_or_boxed(body_cx, src_curr_ptr, elt_ty), + elt_ty); + body_cx = body_res.bcx; + + auto src_next = body_cx.build.Add(src_curr, unit_sz.val); + auto dst_next = body_cx.build.Add(dst_curr, unit_sz.val); + body_cx.build.Br(cond_cx.llbb); + + cond_cx.build.AddIncomingToPhi(src_curr, vec(src_next), + vec(body_cx.llbb)); + + cond_cx.build.AddIncomingToPhi(dst_curr, vec(dst_next), + vec(body_cx.llbb)); + + ret res(next_cx, C_nil()); +} + + +fn iter_sequence_inner(@block_ctxt cx, + ValueRef src, // elt* + ValueRef src_lim, // elt* + @ty.t elt_ty, + val_and_ty_fn f) -> result { + fn adaptor_fn(val_and_ty_fn f, + @block_ctxt cx, + ValueRef av, + ValueRef bv, + @ty.t t) -> result { + ret f(cx, bv, t); + } + + be iter_sequence_pair_inner(cx, src, src, src_lim, elt_ty, + bind adaptor_fn(f, _, _, _, _)); +} + + // Iterates through the elements of a vec or str. fn iter_sequence(@block_ctxt cx, ValueRef v, @@ -1789,43 +1864,18 @@ fn iter_sequence(@block_ctxt cx, auto llunit_ty = type_of(cx.fcx.ccx, elt_ty); auto bcx = cx; - auto unit_sz = size_of(bcx, elt_ty); - bcx = unit_sz.bcx; auto len = bcx.build.Load(lenptr); if (trailing_null) { + auto unit_sz = size_of(bcx, elt_ty); + bcx = unit_sz.bcx; len = bcx.build.Sub(len, unit_sz.val); } - auto cond_cx = new_scope_block_ctxt(cx, "sequence-iter cond"); - auto body_cx = new_scope_block_ctxt(cx, "sequence-iter body"); - auto next_cx = new_sub_block_ctxt(cx, "next"); - - bcx.build.Br(cond_cx.llbb); - - auto ix = cond_cx.build.Phi(T_int(), vec(C_int(0)), vec(cx.llbb)); - auto scaled_ix = cond_cx.build.Phi(T_int(), - vec(C_int(0)), vec(cx.llbb)); - - auto end_test = cond_cx.build.ICmp(lib.llvm.LLVMIntNE, - scaled_ix, len); - cond_cx.build.CondBr(end_test, body_cx.llbb, next_cx.llbb); + auto p1 = vi2p(bcx, bcx.build.Add(vp2i(bcx, p0), len), + T_ptr(llunit_ty)); - auto elt = body_cx.build.GEP(p0, vec(C_int(0), ix)); - auto body_res = f(body_cx, - load_scalar_or_boxed(body_cx, elt, elt_ty), - elt_ty); - auto next_ix = body_res.bcx.build.Add(ix, C_int(1)); - auto next_scaled_ix = body_res.bcx.build.Add(scaled_ix, unit_sz.val); - - cond_cx.build.AddIncomingToPhi(ix, vec(next_ix), - vec(body_res.bcx.llbb)); - - cond_cx.build.AddIncomingToPhi(scaled_ix, vec(next_scaled_ix), - vec(body_res.bcx.llbb)); - - body_res.bcx.build.Br(cond_cx.llbb); - ret res(next_cx, C_nil()); + ret iter_sequence_inner(cx, p0, p1, elt_ty, f); } alt (t.struct) { -- cgit v1.2.3 From 629eba1d066ba4295baf4bfed41cae240c527af5 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Thu, 3 Mar 2011 17:57:36 -0800 Subject: rustc: Make tag discriminants per-tag-ID, not per-tag-ID-and-subtypes --- src/comp/middle/trans.rs | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 2af5359a..5bee0e11 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -60,10 +60,7 @@ type glue_fns = rec(ValueRef activate_glue, ValueRef bzero_glue, ValueRef vec_grow_glue); -type tag_info = rec( - type_handle th, - mutable @hashmap[ast.def_id,ValueRef] lldiscrims -); +type tag_info = rec(type_handle th); state type crate_ctxt = rec(session.session sess, ModuleRef llmod, @@ -78,6 +75,7 @@ state type crate_ctxt = rec(session.session sess, hashmap[ast.def_id, @ast.native_item] native_items, hashmap[@ty.t, @tag_info] tags, + hashmap[ast.def_id, ValueRef] discrims, hashmap[ast.def_id, ValueRef] fn_pairs, hashmap[ast.def_id, ValueRef] consts, hashmap[ast.def_id,()] obj_methods, @@ -2962,9 +2960,7 @@ fn trans_path(@block_ctxt cx, &ast.path p, &option.t[ast.def] dopt, } else { // Nullary variant. auto tag_ty = node_ann_type(cx.fcx.ccx, ann); - auto info = cx.fcx.ccx.tags.get(tag_ty); - check (info.lldiscrims.contains_key(vid)); - auto lldiscrim_gv = info.lldiscrims.get(vid); + auto lldiscrim_gv = cx.fcx.ccx.discrims.get(vid); auto lldiscrim = cx.build.Load(lldiscrim_gv); auto alloc_result = alloc_ty(cx, tag_ty); @@ -4866,10 +4862,7 @@ fn collect_item(&@crate_ctxt cx, @ast.item i) -> @crate_ctxt { auto vi = new_def_hash[uint](); auto navi = new_def_hash[uint](); - auto info = @rec( - th=mk_type_handle(), - mutable lldiscrims=@new_def_hash[ValueRef]() - ); + auto info = @rec(th=mk_type_handle()); cx.tags.insert(mk_plain_tag(tag_id), info); cx.items.insert(tag_id, i); @@ -4980,8 +4973,6 @@ fn resolve_tag_types(@crate_ctxt cx, @ast.crate crate) { fn trans_constant(&@crate_ctxt cx, @ast.item it) -> @crate_ctxt { alt (it.node) { case (ast.item_tag(_, ?variants, _, ?tag_id)) { - auto info = cx.tags.get(mk_plain_tag(tag_id)); - auto i = 0u; auto n_variants = _vec.len[ast.variant](variants); while (i < n_variants) { @@ -5000,7 +4991,7 @@ fn trans_constant(&@crate_ctxt cx, @ast.item it) -> @crate_ctxt { llvm.LLVMSetLinkage(discrim_gvar, lib.llvm.LLVMPrivateLinkage as llvm.Linkage); - info.lldiscrims.insert(variant.id, discrim_gvar); + cx.discrims.insert(variant.id, discrim_gvar); i += 1u; } @@ -5445,6 +5436,7 @@ fn trans_crate(session.session sess, @ast.crate crate, str output, items = new_def_hash[@ast.item](), native_items = new_def_hash[@ast.native_item](), tags = tags, + discrims = new_def_hash[ValueRef](), fn_pairs = new_def_hash[ValueRef](), consts = new_def_hash[ValueRef](), obj_methods = new_def_hash[()](), -- cgit v1.2.3 From 652cb484758a72811e16a574805ce60827daa153 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 3 Mar 2011 18:18:51 -0800 Subject: Assortment of additional work on vec-append. Not done yet. --- src/comp/middle/trans.rs | 86 ++++++++++++++++++++++++++++++++++-------------- 1 file changed, 62 insertions(+), 24 deletions(-) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 5bee0e11..038e0baf 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -58,7 +58,7 @@ type glue_fns = rec(ValueRef activate_glue, ValueRef no_op_type_glue, ValueRef memcpy_glue, ValueRef bzero_glue, - ValueRef vec_grow_glue); + ValueRef vec_append_glue); type tag_info = rec(type_handle th); @@ -2296,17 +2296,39 @@ fn trans_integral_compare(@block_ctxt cx, ast.binop op, @ty.t intype, ret cx.build.ICmp(cmp, lhs, rhs); } -fn trans_sequence_append(@block_ctxt cx, @ty.t t, - ValueRef lhs, ValueRef rhs) -> result { - cx.fcx.ccx.sess.unimpl("sequence append"); - fail; +fn trans_vec_append(@block_ctxt cx, @ty.t t, + ValueRef lhs, ValueRef rhs) -> result { + + auto elt_ty = ty.sequence_element_type(t); + + auto skip_null = C_bool(false); + alt (t.struct) { + case (ty.ty_str) { skip_null = C_bool(true); } + case (_) { } + } + + auto bcx = cx; + + auto llvec_tydesc = get_tydesc(bcx, t); + bcx = llvec_tydesc.bcx; + + auto llelt_tydesc = get_tydesc(bcx, elt_ty); + bcx = llelt_tydesc.bcx; + + ret res(cx, cx.build.FastCall(cx.fcx.ccx.glues.memcpy_glue, + vec(cx.fcx.lltaskptr, + llvec_tydesc.val, + llelt_tydesc.val, + lhs, + load_scalar_or_boxed(cx, rhs, t), + skip_null))); } -fn trans_sequence_add(@block_ctxt cx, @ty.t t, - ValueRef lhs, ValueRef rhs) -> result { +fn trans_vec_add(@block_ctxt cx, @ty.t t, + ValueRef lhs, ValueRef rhs) -> result { auto r = alloc_ty(cx, t); r = copy_ty(r.bcx, INIT, r.val, lhs, t); - ret trans_sequence_append(r.bcx, t, lhs, rhs); + ret trans_vec_append(r.bcx, t, lhs, rhs); } @@ -2316,7 +2338,7 @@ fn trans_eager_binop(@block_ctxt cx, ast.binop op, @ty.t intype, alt (op) { case (ast.add) { if (ty.type_is_sequence(intype)) { - ret trans_sequence_add(cx, intype, lhs, rhs); + ret trans_vec_add(cx, intype, lhs, rhs); } ret res(cx, cx.build.Add(lhs, rhs)); } @@ -5296,9 +5318,9 @@ fn make_bzero_glue(ModuleRef llmod) -> ValueRef { ret fun; } -fn make_vec_grow_glue(ModuleRef llmod, type_names tn) -> ValueRef { +fn make_vec_append_glue(ModuleRef llmod, type_names tn) -> ValueRef { /* - * Args to vec_grow_glue: + * Args to vec_append_glue: * * 0. (Implicit) task ptr * @@ -5309,9 +5331,11 @@ fn make_vec_grow_glue(ModuleRef llmod, type_names tn) -> ValueRef { * elements can be copied to a newly alloc'ed vec if one must be * created. * - * 3. Alias to vec that needs to grow (i.e. ptr to ptr to rust_vec). + * 3. Dst vec alias (i.e. ptr to ptr to rust_vec, we will mutate it). + * + * 4. Src vec (i.e. ptr to rust_vec). * - * 4. Number of bytes of growth requested + * 5. Flag indicating whether to skip trailing null on dst. * */ @@ -5319,21 +5343,23 @@ fn make_vec_grow_glue(ModuleRef llmod, type_names tn) -> ValueRef { T_ptr(T_tydesc(tn)), T_ptr(T_tydesc(tn)), T_ptr(T_ptr(T_vec(T_int()))), // a lie. - T_int()), T_void()); + T_ptr(T_vec(T_int())), // a lie. + T_bool()), T_void()); - auto llfn = decl_fastcall_fn(llmod, abi.vec_grow_glue_name(), ty); + auto llfn = decl_fastcall_fn(llmod, abi.vec_append_glue_name(), ty); ret llfn; } -fn trans_vec_grow_glue(@crate_ctxt cx) { +fn trans_vec_append_glue(@crate_ctxt cx) { - auto llfn = cx.glues.vec_grow_glue; + auto llfn = cx.glues.vec_append_glue; let ValueRef lltaskptr = llvm.LLVMGetParam(llfn, 0u); let ValueRef llvec_tydesc = llvm.LLVMGetParam(llfn, 1u); let ValueRef llelt_tydesc = llvm.LLVMGetParam(llfn, 2u); - let ValueRef llvec_ptr = llvm.LLVMGetParam(llfn, 3u); - let ValueRef llnbytes = llvm.LLVMGetParam(llfn, 4u); + let ValueRef lldst_vec_ptr = llvm.LLVMGetParam(llfn, 3u); + let ValueRef llsrc_vec = llvm.LLVMGetParam(llfn, 4u); + let ValueRef llskipnull = llvm.LLVMGetParam(llfn, 5u); auto fcx = @rec(llfn=llfn, lltaskptr=lltaskptr, @@ -5349,12 +5375,23 @@ fn trans_vec_grow_glue(@crate_ctxt cx) { auto bcx = new_top_block_ctxt(fcx); - auto llneed_copy_ptr = bcx.build.Alloca(T_int()); + // First the dst vec needs to grow to accommodate the src vec. + // To do this we have to figure out how many bytes to add. + auto n_bytes = + bcx.build.Load(bcx.build.GEP(llsrc_vec, + vec(C_int(0), + C_int(abi.vec_elt_fill)))); + n_bytes = bcx.build.Select(llskipnull, + bcx.build.Sub(n_bytes, C_int(1)), + n_bytes); + + + auto llneed_copy_ptr = bcx.build.Alloca(T_int()); auto llnew_vec_res = trans_upcall(bcx, "upcall_vec_grow", - vec(vp2i(bcx, bcx.build.Load(llvec_ptr)), - llnbytes, + vec(vp2i(bcx, bcx.build.Load(lldst_vec_ptr)), + n_bytes, vp2i(bcx, llneed_copy_ptr), vp2i(bcx, llvec_tydesc))); @@ -5364,6 +5401,7 @@ fn trans_vec_grow_glue(@crate_ctxt cx) { T_ptr(T_vec(T_int())) // a lie. ); + // FIXME: complete this. bcx.build.RetVoid(); @@ -5396,7 +5434,7 @@ fn make_glues(ModuleRef llmod, type_names tn) -> @glue_fns { no_op_type_glue = make_no_op_type_glue(llmod, tn), memcpy_glue = make_memcpy_glue(llmod), bzero_glue = make_bzero_glue(llmod), - vec_grow_glue = make_vec_grow_glue(llmod, tn)); + vec_append_glue = make_vec_append_glue(llmod, tn)); } fn trans_crate(session.session sess, @ast.crate crate, str output, @@ -5456,7 +5494,7 @@ fn trans_crate(session.session sess, @ast.crate crate, str output, trans_mod(cx, crate.node.module); trans_exit_task_glue(cx); - trans_vec_grow_glue(cx); + trans_vec_append_glue(cx); create_crate_constant(cx); if (!shared) { trans_main_fn(cx, cx.crate_ptr); -- cgit v1.2.3 From 2ff67ed94e9835f7ee01088aa479a1ca5796bee5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20=C3=81vila=20de=20Esp=C3=ADndola?= Date: Fri, 4 Mar 2011 14:53:52 -0500 Subject: Remove unused argument. --- src/comp/middle/trans.rs | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 038e0baf..d2fa0acc 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -1278,7 +1278,7 @@ fn make_generic_glue(@crate_ctxt cx, @ty.t t, str name, fn_name = sanitize(fn_name); auto llfn = decl_fastcall_fn(cx.llmod, fn_name, llfnty); - auto fcx = new_fn_ctxt(cx, fn_name, llfn); + auto fcx = new_fn_ctxt(cx, llfn); auto bcx = new_top_block_ctxt(fcx); auto re; @@ -2656,7 +2656,7 @@ fn trans_for_each(@block_ctxt cx, // FIXME: handle ty params properly. let vec[ast.ty_param] ty_params = vec(); - auto fcx = new_fn_ctxt(cx.fcx.ccx, s, lliterbody); + auto fcx = new_fn_ctxt(cx.fcx.ccx, lliterbody); auto bcx = new_top_block_ctxt(fcx); // FIXME: populate lllocals from llenv here. @@ -3151,7 +3151,7 @@ fn trans_bind_thunk(@crate_ctxt cx, let TypeRef llthunk_ty = get_pair_fn_ty(type_of(cx, incoming_fty)); let ValueRef llthunk = decl_fastcall_fn(cx.llmod, s, llthunk_ty); - auto fcx = new_fn_ctxt(cx, s, llthunk); + auto fcx = new_fn_ctxt(cx, llthunk); auto bcx = new_top_block_ctxt(fcx); auto llclosure = bcx.build.PointerCast(fcx.llenv, llclosure_ty); @@ -4213,7 +4213,6 @@ fn trans_block(@block_ctxt cx, &ast.block b) -> result { // - trans_args fn new_fn_ctxt(@crate_ctxt cx, - str name, ValueRef llfndecl) -> @fn_ctxt { let ValueRef llretptr = llvm.LLVMGetParam(llfndecl, 0u); @@ -4429,7 +4428,7 @@ fn trans_fn(@crate_ctxt cx, &ast._fn f, ast.def_id fid, auto llfndecl = cx.item_ids.get(fid); cx.item_names.insert(cx.path, llfndecl); - auto fcx = new_fn_ctxt(cx, cx.path, llfndecl); + auto fcx = new_fn_ctxt(cx, llfndecl); create_llargs_for_fn_args(fcx, f.proto, ty_self, ret_ty_of_fn(ann), f.decl.inputs, ty_params); @@ -4514,7 +4513,7 @@ fn trans_obj(@crate_ctxt cx, &ast._obj ob, ast.def_id oid, id=f.id)); } - auto fcx = new_fn_ctxt(cx, cx.path, llctor_decl); + auto fcx = new_fn_ctxt(cx, llctor_decl); create_llargs_for_fn_args(fcx, ast.proto_fn, none[TypeRef], ret_ty_of_fn(ann), fn_args, ty_params); @@ -4644,7 +4643,7 @@ fn trans_tag_variant(@crate_ctxt cx, ast.def_id tag_id, check (cx.item_ids.contains_key(variant.id)); let ValueRef llfndecl = cx.item_ids.get(variant.id); - auto fcx = new_fn_ctxt(cx, cx.path, llfndecl); + auto fcx = new_fn_ctxt(cx, llfndecl); create_llargs_for_fn_args(fcx, ast.proto_fn, none[TypeRef], ret_ty_of_fn(variant.ann), fn_args, ty_params); -- cgit v1.2.3 From 95c0cefd32bc1af5e91857511187760010aaffc7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20=C3=81vila=20de=20Esp=C3=ADndola?= Date: Fri, 4 Mar 2011 15:29:33 -0500 Subject: Build empty wrappers. This lets us compile hello world, but so far it just returns 0. --- src/comp/middle/trans.rs | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index d2fa0acc..2f45691a 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -4829,6 +4829,11 @@ fn decl_native_fn_and_pair(@crate_ctxt cx, let str s = cx.names.next("_rust_wrapper") + sep() + name; let ValueRef wrapper_fn = decl_fastcall_fn(cx.llmod, s, wrapper_type); + // Build the wrapper. + auto fcx = new_fn_ctxt(cx, wrapper_fn); + auto bcx = new_top_block_ctxt(fcx); + bcx.build.RetVoid(); + // Declare the global constant pair that points to it. auto wrapper_pair_type = T_fn_pair(cx.tn, wrapper_type); let str ps = cx.names.next("_rust_wrapper_pair") + sep() + name; -- cgit v1.2.3 From 76ec67063e3b310aca4d4164577d167862d1bf73 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Fri, 4 Mar 2011 15:08:33 -0800 Subject: rustc: Don't use recursive types for tags; remove tag_info; introduce GEP_tag() --- src/comp/middle/trans.rs | 262 ++++++++++++++++++++++++++++------------------- 1 file changed, 154 insertions(+), 108 deletions(-) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 2f45691a..66539ab2 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -60,8 +60,6 @@ type glue_fns = rec(ValueRef activate_glue, ValueRef bzero_glue, ValueRef vec_append_glue); -type tag_info = rec(type_handle th); - state type crate_ctxt = rec(session.session sess, ModuleRef llmod, target_data td, @@ -74,7 +72,8 @@ state type crate_ctxt = rec(session.session sess, hashmap[ast.def_id, @ast.item] items, hashmap[ast.def_id, @ast.native_item] native_items, - hashmap[@ty.t, @tag_info] tags, + // TODO: hashmap[tup(tag_id,subtys), @tag_info] + hashmap[@ty.t, uint] tag_sizes, hashmap[ast.def_id, ValueRef] discrims, hashmap[ast.def_id, ValueRef] fn_pairs, hashmap[ast.def_id, ValueRef] consts, @@ -395,16 +394,30 @@ fn T_opaque_closure_ptr(type_names tn) -> TypeRef { ret t; } -fn T_opaque_tag_ptr(type_names tn) -> TypeRef { - auto s = "*tag"; +fn T_tag(type_names tn, uint size) -> TypeRef { + auto s = "tag_" + _uint.to_str(size, 10u); + if (tn.name_has_type(s)) { + ret tn.get_type(s); + } + auto t = T_struct(vec(T_int(), T_array(T_i8(), size))); + tn.associate(s, t); + ret t; +} + +fn T_opaque_tag(type_names tn) -> TypeRef { + auto s = "tag"; if (tn.name_has_type(s)) { ret tn.get_type(s); } - auto t = T_ptr(T_struct(vec(T_int(), T_i8()))); + auto t = T_struct(vec(T_int(), T_i8())); tn.associate(s, t); ret t; } +fn T_opaque_tag_ptr(type_names tn) -> TypeRef { + ret T_ptr(T_opaque_tag(tn)); +} + fn T_captured_tydescs(type_names tn, uint n) -> TypeRef { ret T_struct(_vec.init_elt[TypeRef](T_ptr(T_tydesc(tn)), n)); } @@ -436,7 +449,7 @@ fn type_of(@crate_ctxt cx, @ty.t t) -> TypeRef { fail; } - ret type_of_inner(cx, t); + ret type_of_inner(cx, t, false); } fn type_of_explicit_args(@crate_ctxt cx, @@ -447,12 +460,14 @@ fn type_of_explicit_args(@crate_ctxt cx, check (arg.mode == ast.alias); atys += T_typaram_ptr(cx.tn); } else { - let TypeRef t = type_of_inner(cx, arg.ty); + let TypeRef t; alt (arg.mode) { case (ast.alias) { - t = T_ptr(t); + t = T_ptr(type_of_inner(cx, arg.ty, true)); + } + case (_) { + t = type_of_inner(cx, arg.ty, false); } - case (_) { /* fall through */ } } atys += t; } @@ -478,7 +493,7 @@ fn type_of_fn_full(@crate_ctxt cx, if (ty.type_has_dynamic_size(output)) { atys += T_typaram_ptr(cx.tn); } else { - atys += T_ptr(type_of_inner(cx, output)); + atys += T_ptr(type_of_inner(cx, output, false)); } // Arg 1: Task pointer. @@ -545,10 +560,10 @@ fn type_of_native_fn(@crate_ctxt cx, ast.native_abi abi, } } atys += type_of_explicit_args(cx, inputs); - ret T_fn(atys, type_of_inner(cx, output)); + ret T_fn(atys, type_of_inner(cx, output, false)); } -fn type_of_inner(@crate_ctxt cx, @ty.t t) -> TypeRef { +fn type_of_inner(@crate_ctxt cx, @ty.t t, bool boxed) -> TypeRef { let TypeRef llty = 0 as TypeRef; alt (t.struct) { @@ -573,26 +588,31 @@ fn type_of_inner(@crate_ctxt cx, @ty.t t) -> TypeRef { } case (ty.ty_char) { llty = T_char(); } case (ty.ty_str) { llty = T_ptr(T_str()); } - case (ty.ty_tag(?tag_id, _)) { - llty = llvm.LLVMResolveTypeHandle(cx.tags.get(t).th.llth); + case (ty.ty_tag(_, _)) { + if (boxed) { + llty = T_opaque_tag(cx.tn); + } else { + auto size = static_size_of_tag(cx, t); + llty = T_tag(cx.tn, size); + } } case (ty.ty_box(?t)) { - llty = T_ptr(T_box(type_of_inner(cx, t))); + llty = T_ptr(T_box(type_of_inner(cx, t, true))); } case (ty.ty_vec(?t)) { - llty = T_ptr(T_vec(type_of_inner(cx, t))); + llty = T_ptr(T_vec(type_of_inner(cx, t, true))); } case (ty.ty_tup(?elts)) { let vec[TypeRef] tys = vec(); for (@ty.t elt in elts) { - tys += type_of_inner(cx, elt); + tys += type_of_inner(cx, elt, boxed); } llty = T_struct(tys); } case (ty.ty_rec(?fields)) { let vec[TypeRef] tys = vec(); for (ty.field f in fields) { - tys += type_of_inner(cx, f.ty); + tys += type_of_inner(cx, f.ty, boxed); } llty = T_struct(tys); } @@ -650,9 +670,11 @@ fn type_of_arg(@crate_ctxt cx, &ty.arg arg) -> TypeRef { } } - auto typ = type_of_inner(cx, arg.ty); + auto typ; if (arg.mode == ast.alias) { - typ = T_ptr(typ); + typ = T_ptr(type_of_inner(cx, arg.ty, true)); + } else { + typ = type_of_inner(cx, arg.ty, false); } ret typ; } @@ -856,6 +878,11 @@ fn align_to(@block_ctxt cx, ValueRef off, ValueRef align) -> ValueRef { ret cx.build.And(bumped, cx.build.Not(mask)); } +// Returns the real size of the given type for the current target. +fn llsize_of_real(@crate_ctxt cx, TypeRef t) -> uint { + ret llvm.LLVMStoreSizeOfType(cx.td.lltd, t); +} + fn llsize_of(TypeRef t) -> ValueRef { ret llvm.LLVMConstIntCast(lib.llvm.llvm.LLVMSizeOf(t), T_int(), False); } @@ -878,6 +905,49 @@ fn align_of(@block_ctxt cx, @ty.t t) -> result { ret dynamic_align_of(cx, t); } +// Computes the size of the data part of a non-dynamically-sized tag. +fn static_size_of_tag(@crate_ctxt cx, @ty.t t) -> uint { + if (ty.type_has_dynamic_size(t)) { + log "dynamically sized type passed to static_size_of_tag()"; + fail; + } + + if (cx.tag_sizes.contains_key(t)) { + ret cx.tag_sizes.get(t); + } + + auto tid = tup(0, 0); // FIXME (#250): typestate botch + let vec[@ty.t] subtys = vec(); // FIXME (#250): typestate botch + alt (t.struct) { + case (ty.ty_tag(?tid_, ?subtys_)) { + tid = tid_; + subtys = subtys_; + } + case (_) { + log "non-tag passed to static_size_of_tag()"; + fail; + } + } + + // Compute max(variant sizes). + auto max_size = 0u; + auto variants = tag_variants(cx, tid); + for (ast.variant variant in variants) { + let vec[@ty.t] tys = variant_types(cx, variant); + auto tup_ty = ty.plain_ty(ty.ty_tup(tys)); + + // Here we possibly do a recursive call. + auto this_size = llsize_of_real(cx, type_of(cx, tup_ty)); + + if (max_size < this_size) { + max_size = this_size; + } + } + + cx.tag_sizes.insert(t, max_size); + ret max_size; +} + fn dynamic_size_of(@block_ctxt cx, @ty.t t) -> result { fn align_elements(@block_ctxt cx, vec[@ty.t] elts) -> result { // @@ -974,10 +1044,10 @@ fn dynamic_align_of(@block_ctxt cx, @ty.t t) -> result { } // Replacement for the LLVM 'GEP' instruction when field-indexing into a -// tuple-like structure (tup, rec, tag) with a static index. This one is -// driven off ty.struct and knows what to do when it runs into a ty_param -// stuck in the middle of the thing it's GEP'ing into. Much like size_of and -// align_of, above. +// tuple-like structure (tup, rec) with a static index. This one is driven off +// ty.struct and knows what to do when it runs into a ty_param stuck in the +// middle of the thing it's GEP'ing into. Much like size_of and align_of, +// above. fn GEP_tup_like(@block_ctxt cx, @ty.t t, ValueRef base, vec[int] ixs) -> result { @@ -1076,6 +1146,53 @@ fn GEP_tup_like(@block_ctxt cx, @ty.t t, ret res(bcx, bcx.build.PointerCast(bumped, typ)); } +// Replacement for the LLVM 'GEP' instruction when field indexing into a tag. +// This function uses GEP_tup_like() above and automatically performs casts as +// appropriate. @llblobptr is the data part of a tag value; its actual type is +// meaningless, as it will be cast away. +fn GEP_tag(@block_ctxt cx, ValueRef llblobptr, &ast.variant variant, int ix) + -> result { + // Synthesize a tuple type so that GEP_tup_like() can work its magic. + // Separately, store the type of the element we're interested in. + auto arg_tys = arg_tys_of_fn(variant.ann); + auto elem_ty = ty.plain_ty(ty.ty_nil); // typestate infelicity + auto i = 0; + let vec[@ty.t] true_arg_tys = vec(); + for (ty.arg a in arg_tys) { + true_arg_tys += vec(a.ty); + if (i == ix) { + elem_ty = a.ty; + } + + i += 1; + } + auto tup_ty = ty.plain_ty(ty.ty_tup(true_arg_tys)); + + // Cast the blob pointer to the appropriate type, if we need to (i.e. if + // the blob pointer isn't dynamically sized). + let ValueRef llunionptr; + if (!ty.type_has_dynamic_size(tup_ty)) { + auto llty = type_of(cx.fcx.ccx, tup_ty); + llunionptr = cx.build.TruncOrBitCast(llblobptr, T_ptr(llty)); + } else { + llunionptr = llblobptr; + } + + // Do the GEP_tup_like(). + auto rslt = GEP_tup_like(cx, tup_ty, llunionptr, vec(0, ix)); + + // Cast the result to the appropriate type, if necessary. + auto val; + if (!ty.type_has_dynamic_size(elem_ty)) { + auto llelemty = type_of(rslt.bcx.fcx.ccx, elem_ty); + val = rslt.bcx.build.PointerCast(rslt.val, T_ptr(llelemty)); + } else { + val = rslt.val; + } + + ret res(rslt.bcx, val); +} + fn trans_raw_malloc(@block_ctxt cx, TypeRef llptr_ty, ValueRef llsize) -> result { @@ -1527,6 +1644,7 @@ fn variant_types(@crate_ctxt cx, &ast.variant v) -> vec[@ty.t] { tys += vec(arg.ty); } } + case (ty.ty_tag(_, _)) { /* nothing */ } case (_) { fail; } } ret tys; @@ -1647,8 +1765,6 @@ fn iter_structural_ty_full(@block_ctxt cx, } } case (ty.ty_tag(?tid, ?tps)) { - auto info = cx.fcx.ccx.tags.get(mk_plain_tag(tid)); - auto variants = tag_variants(cx.fcx.ccx, tid); auto n_variants = _vec.len[ast.variant](variants); @@ -4653,14 +4769,6 @@ fn trans_tag_variant(@crate_ctxt cx, ast.def_id tag_id, auto arg_tys = arg_tys_of_fn(variant.ann); copy_args_to_allocas(bcx, none[TypeRef], fn_args, arg_tys); - // Now synthesize a tuple type for the arguments, so that GEP_tup_like() - // will know what the data part of the variant looks like. - let vec[@ty.t] true_arg_tys = vec(); - for (ty.arg a in arg_tys) { - true_arg_tys += vec(a.ty); - } - auto tup_ty = ty.plain_ty(ty.ty_tup(true_arg_tys)); - // Cast the tag to a type we can GEP into. auto lltagptr = bcx.build.PointerCast(fcx.llretptr, T_opaque_tag_ptr(fcx.ccx.tn)); @@ -4672,23 +4780,19 @@ fn trans_tag_variant(@crate_ctxt cx, ast.def_id tag_id, auto llblobptr = bcx.build.GEP(lltagptr, vec(C_int(0), C_int(1))); - // Cast the blob pointer to the appropriate type, if we need to (i.e. if - // the blob pointer isn't dynamically sized). - let ValueRef llunionptr; - if (!ty.type_has_dynamic_size(tup_ty)) { - auto llty = type_of(cx, tup_ty); - llunionptr = bcx.build.TruncOrBitCast(llblobptr, T_ptr(llty)); - } else { - llunionptr = llblobptr; - } - i = 0u; for (ast.variant_arg va in variant.args) { - auto llargval = bcx.build.Load(fcx.llargs.get(va.id)); - auto rslt = GEP_tup_like(bcx, tup_ty, llunionptr, vec(0, i as int)); + auto rslt = GEP_tag(bcx, llblobptr, variant, i as int); bcx = rslt.bcx; auto lldestptr = rslt.val; + // If this argument to this function is a tag, it'll have come in to + // this function as an opaque blob due to the way that type_of() + // works. So we have to cast to the destination's view of the type. + auto llargptr = bcx.build.PointerCast(fcx.llargs.get(va.id), + val_ty(lldestptr)); + auto llargval = bcx.build.Load(llargptr); + bcx.build.Store(llargval, lldestptr); i += 1u; } @@ -4747,6 +4851,7 @@ fn trans_item(@crate_ctxt cx, &ast.item item) { case (ast.item_tag(?name, ?variants, ?tps, ?tag_id)) { auto sub_cx = @rec(path=cx.path + sep() + name with *cx); auto i = 0; + log "translating variants for " + name; for (ast.variant variant in variants) { trans_tag_variant(sub_cx, tag_id, variant, i, tps); i += 1; @@ -4885,12 +4990,6 @@ fn collect_item(&@crate_ctxt cx, @ast.item i) -> @crate_ctxt { } case (ast.item_tag(_, ?variants, ?tps, ?tag_id)) { - auto vi = new_def_hash[uint](); - auto navi = new_def_hash[uint](); - - auto info = @rec(th=mk_type_handle()); - - cx.tags.insert(mk_plain_tag(tag_id), info); cx.items.insert(tag_id, i); } @@ -4942,58 +5041,6 @@ fn collect_tag_ctors(@crate_ctxt cx, @ast.crate crate) { } -// The tag type resolution pass, which determines all the LLVM types that -// correspond to each tag type in the crate. - -fn resolve_tag_types_for_item(&@crate_ctxt cx, @ast.item i) -> @crate_ctxt { - alt (i.node) { - case (ast.item_tag(_, ?variants, _, ?tag_id)) { - // FIXME: This is all wrong. Now sizes and alignments are computed - // dynamically instead of up front. - - auto max_align = 0u; - auto max_size = 0u; - - auto info = cx.tags.get(mk_plain_tag(tag_id)); - - for (ast.variant variant in variants) { - if (_vec.len[ast.variant_arg](variant.args) > 0u) { - auto llvariantty = type_of_variant(cx, variant); - auto align = - llvm.LLVMPreferredAlignmentOfType(cx.td.lltd, - llvariantty); - auto size = - llvm.LLVMStoreSizeOfType(cx.td.lltd, - llvariantty) as uint; - if (max_align < align) { max_align = align; } - if (max_size < size) { max_size = size; } - } - } - - // FIXME: alignment is wrong here, manually insert padding I - // guess :( - auto tag_ty = T_struct(vec(T_int(), T_array(T_i8(), max_size))); - auto th = info.th.llth; - llvm.LLVMRefineType(llvm.LLVMResolveTypeHandle(th), tag_ty); - } - case (_) { - // fall through - } - } - - ret cx; -} - -fn resolve_tag_types(@crate_ctxt cx, @ast.crate crate) { - let fold.ast_fold[@crate_ctxt] fld = - fold.new_identity_fold[@crate_ctxt](); - - fld = @rec( update_env_for_item = bind resolve_tag_types_for_item(_,_) - with *fld ); - - fold.fold_crate[@crate_ctxt](cx, fld, crate); -} - // The constant translation pass. fn trans_constant(&@crate_ctxt cx, @ast.item it) -> @crate_ctxt { @@ -5461,7 +5508,7 @@ fn trans_crate(session.session sess, @ast.crate crate, str output, auto glues = make_glues(llmod, tn); auto hasher = ty.hash_ty; auto eqer = ty.eq_ty; - auto tags = map.mk_hashmap[@ty.t,@tag_info](hasher, eqer); + auto tag_sizes = map.mk_hashmap[@ty.t,uint](hasher, eqer); auto tydescs = map.mk_hashmap[@ty.t,ValueRef](hasher, eqer); let vec[ast.ty_param] obj_typarams = vec(); let vec[ast.obj_field] obj_fields = vec(); @@ -5477,7 +5524,7 @@ fn trans_crate(session.session sess, @ast.crate crate, str output, item_ids = new_def_hash[ValueRef](), items = new_def_hash[@ast.item](), native_items = new_def_hash[@ast.native_item](), - tags = tags, + tag_sizes = tag_sizes, discrims = new_def_hash[ValueRef](), fn_pairs = new_def_hash[ValueRef](), consts = new_def_hash[ValueRef](), @@ -5492,7 +5539,6 @@ fn trans_crate(session.session sess, @ast.crate crate, str output, create_typedefs(cx); collect_items(cx, crate); - resolve_tag_types(cx, crate); collect_tag_ctors(cx, crate); trans_constants(cx, crate); -- cgit v1.2.3 From 0aa74828e36f2b57822317e9c99435993633a424 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Fri, 4 Mar 2011 15:15:12 -0800 Subject: rustc: Remove "translating variants" debug string --- src/comp/middle/trans.rs | 1 - 1 file changed, 1 deletion(-) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 66539ab2..af62bb9a 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -4851,7 +4851,6 @@ fn trans_item(@crate_ctxt cx, &ast.item item) { case (ast.item_tag(?name, ?variants, ?tps, ?tag_id)) { auto sub_cx = @rec(path=cx.path + sep() + name with *cx); auto i = 0; - log "translating variants for " + name; for (ast.variant variant in variants) { trans_tag_variant(sub_cx, tag_id, variant, i, tps); i += 1; -- cgit v1.2.3 From 1dc6bdf33191cbd183bb17331e4a71d5c80ad353 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Fri, 4 Mar 2011 17:22:43 -0800 Subject: rustc: Don't recurse forever if type glue needs to refer to its own type descriptor --- src/comp/middle/trans.rs | 61 +++++++++++++++++++++++++++++++++++------------- 1 file changed, 45 insertions(+), 16 deletions(-) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index af62bb9a..9b7a501c 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -60,6 +60,10 @@ type glue_fns = rec(ValueRef activate_glue, ValueRef bzero_glue, ValueRef vec_append_glue); +type tydesc_info = rec(ValueRef tydesc, + ValueRef take_glue, + ValueRef drop_glue); + state type crate_ctxt = rec(session.session sess, ModuleRef llmod, target_data td, @@ -78,7 +82,7 @@ state type crate_ctxt = rec(session.session sess, hashmap[ast.def_id, ValueRef] fn_pairs, hashmap[ast.def_id, ValueRef] consts, hashmap[ast.def_id,()] obj_methods, - hashmap[@ty.t, ValueRef] tydescs, + hashmap[@ty.t, @tydesc_info] tydescs, vec[ast.ty_param] obj_typarams, vec[ast.obj_field] obj_fields, @glue_fns glues, @@ -1291,10 +1295,11 @@ fn get_tydesc(&@block_ctxt cx, @ty.t t) -> result { check (n_params == _vec.len[ValueRef](tys._1)); if (!cx.fcx.ccx.tydescs.contains_key(t)) { - make_tydesc(cx.fcx.ccx, t, tys._0); + declare_tydesc(cx.fcx.ccx, t); + define_tydesc(cx.fcx.ccx, t, tys._0); } - auto root = cx.fcx.ccx.tydescs.get(t); + auto root = cx.fcx.ccx.tydescs.get(t).tydesc; auto tydescs = cx.build.Alloca(T_array(T_ptr(T_tydesc(cx.fcx.ccx.tn)), n_params)); @@ -1329,16 +1334,18 @@ fn get_tydesc(&@block_ctxt cx, @ty.t t) -> result { // Otherwise, generate a tydesc if necessary, and return it. if (!cx.fcx.ccx.tydescs.contains_key(t)) { let vec[ast.def_id] defs = vec(); - make_tydesc(cx.fcx.ccx, t, defs); + declare_tydesc(cx.fcx.ccx, t); + define_tydesc(cx.fcx.ccx, t, defs); } - ret res(cx, cx.fcx.ccx.tydescs.get(t)); + ret res(cx, cx.fcx.ccx.tydescs.get(t).tydesc); } -fn make_tydesc(@crate_ctxt cx, @ty.t t, vec[ast.def_id] typaram_defs) { - auto tg = make_take_glue; - auto take_glue = make_generic_glue(cx, t, "take", tg, typaram_defs); - auto dg = make_drop_glue; - auto drop_glue = make_generic_glue(cx, t, "drop", dg, typaram_defs); +// Generates the declaration for (but doesn't fill in) a type descriptor. This +// needs to be separate from make_tydesc() below, because sometimes type glue +// functions needs to refer to their own type descriptors. +fn declare_tydesc(@crate_ctxt cx, @ty.t t) { + auto take_glue = declare_generic_glue(cx, t, "take"); + auto drop_glue = declare_generic_glue(cx, t, "drop"); auto llsize; auto llalign; @@ -1383,18 +1390,40 @@ fn make_tydesc(@crate_ctxt cx, @ty.t t, vec[ast.def_id] typaram_defs) { llvm.LLVMSetGlobalConstant(gvar, True); llvm.LLVMSetLinkage(gvar, lib.llvm.LLVMPrivateLinkage as llvm.Linkage); - cx.tydescs.insert(t, gvar); + + auto info = rec( + tydesc=gvar, + take_glue=take_glue, + drop_glue=drop_glue + ); + + cx.tydescs.insert(t, @info); } -fn make_generic_glue(@crate_ctxt cx, @ty.t t, str name, - val_and_ty_fn helper, - vec[ast.def_id] typaram_defs) -> ValueRef { +// declare_tydesc() above must have been called first. +fn define_tydesc(@crate_ctxt cx, @ty.t t, vec[ast.def_id] typaram_defs) { + auto info = cx.tydescs.get(t); + auto gvar = info.tydesc; + + auto tg = make_take_glue; + auto take_glue = make_generic_glue(cx, t, info.take_glue, tg, + typaram_defs); + auto dg = make_drop_glue; + auto drop_glue = make_generic_glue(cx, t, info.drop_glue, dg, + typaram_defs); +} + +fn declare_generic_glue(@crate_ctxt cx, @ty.t t, str name) -> ValueRef { auto llfnty = T_glue_fn(cx.tn); auto fn_name = cx.names.next("_rust_" + name) + sep() + ty.ty_to_str(t); fn_name = sanitize(fn_name); - auto llfn = decl_fastcall_fn(cx.llmod, fn_name, llfnty); + ret decl_fastcall_fn(cx.llmod, fn_name, llfnty); +} +fn make_generic_glue(@crate_ctxt cx, @ty.t t, ValueRef llfn, + val_and_ty_fn helper, + vec[ast.def_id] typaram_defs) -> ValueRef { auto fcx = new_fn_ctxt(cx, llfn); auto bcx = new_top_block_ctxt(fcx); @@ -5508,7 +5537,7 @@ fn trans_crate(session.session sess, @ast.crate crate, str output, auto hasher = ty.hash_ty; auto eqer = ty.eq_ty; auto tag_sizes = map.mk_hashmap[@ty.t,uint](hasher, eqer); - auto tydescs = map.mk_hashmap[@ty.t,ValueRef](hasher, eqer); + auto tydescs = map.mk_hashmap[@ty.t,@tydesc_info](hasher, eqer); let vec[ast.ty_param] obj_typarams = vec(); let vec[ast.obj_field] obj_fields = vec(); -- cgit v1.2.3 From 94b681afe4f8fb09141d459963b268c76fbd0072 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Fri, 4 Mar 2011 18:05:48 -0800 Subject: rustc: Use copy_ty() when initializing N-ary tag variants. Un-XFAIL generic-tag.rs. --- src/comp/middle/trans.rs | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 9b7a501c..b5ff4224 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -363,17 +363,22 @@ fn T_taskptr(type_names tn) -> TypeRef { ret T_ptr(T_task(tn)); } -fn T_typaram_ptr(type_names tn) -> TypeRef { +// This type must never be used directly; it must always be cast away. +fn T_typaram(type_names tn) -> TypeRef { auto s = "typaram"; if (tn.name_has_type(s)) { ret tn.get_type(s); } - auto t = T_ptr(T_i8()); + auto t = T_i8(); tn.associate(s, t); ret t; } +fn T_typaram_ptr(type_names tn) -> TypeRef { + ret T_ptr(T_typaram(tn)); +} + fn T_closure_ptr(type_names tn, TypeRef lltarget_ty, TypeRef llbindings_ty, @@ -2068,7 +2073,6 @@ fn call_tydesc_glue(@block_ctxt cx, ValueRef v, @ty.t t, int field) { fn incr_all_refcnts(@block_ctxt cx, ValueRef v, @ty.t t) -> result { - if (!ty.type_is_scalar(t)) { call_tydesc_glue(cx, v, t, abi.tydesc_field_take_glue_off); } @@ -4820,9 +4824,18 @@ fn trans_tag_variant(@crate_ctxt cx, ast.def_id tag_id, // works. So we have to cast to the destination's view of the type. auto llargptr = bcx.build.PointerCast(fcx.llargs.get(va.id), val_ty(lldestptr)); - auto llargval = bcx.build.Load(llargptr); - bcx.build.Store(llargval, lldestptr); + auto arg_ty = arg_tys.(i).ty; + auto llargval; + if (ty.type_is_structural(arg_ty)) { + llargval = llargptr; + } else { + llargval = bcx.build.Load(llargptr); + } + + rslt = copy_ty(bcx, INIT, lldestptr, llargval, arg_ty); + bcx = rslt.bcx; + i += 1u; } -- cgit v1.2.3 From 3eb20f3f6e3e1301897a560629cda1ee2c7c2995 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Sun, 6 Mar 2011 12:46:33 -0800 Subject: Correct signatures and arguments associated with call into vec_append_glue. --- src/comp/middle/trans.rs | 39 ++++++++++++++++++++++----------------- 1 file changed, 22 insertions(+), 17 deletions(-) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index b5ff4224..c30373e2 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -321,6 +321,10 @@ fn T_vec(TypeRef t) -> TypeRef { )); } +fn T_opaque_vec_ptr() -> TypeRef { + ret T_ptr(T_vec(T_int())); +} + fn T_str() -> TypeRef { ret T_vec(T_i8()); } @@ -2464,20 +2468,23 @@ fn trans_vec_append(@block_ctxt cx, @ty.t t, auto llelt_tydesc = get_tydesc(bcx, elt_ty); bcx = llelt_tydesc.bcx; - ret res(cx, cx.build.FastCall(cx.fcx.ccx.glues.memcpy_glue, - vec(cx.fcx.lltaskptr, - llvec_tydesc.val, - llelt_tydesc.val, - lhs, - load_scalar_or_boxed(cx, rhs, t), - skip_null))); + auto dst = bcx.build.PointerCast(lhs, T_ptr(T_opaque_vec_ptr())); + auto src = bcx.build.PointerCast(rhs, T_opaque_vec_ptr()); + + ret res(bcx, bcx.build.FastCall(cx.fcx.ccx.glues.vec_append_glue, + vec(cx.fcx.lltaskptr, + llvec_tydesc.val, + llelt_tydesc.val, + dst, src, skip_null))); } fn trans_vec_add(@block_ctxt cx, @ty.t t, ValueRef lhs, ValueRef rhs) -> result { auto r = alloc_ty(cx, t); - r = copy_ty(r.bcx, INIT, r.val, lhs, t); - ret trans_vec_append(r.bcx, t, lhs, rhs); + auto tmp = r.val; + find_scope_cx(cx).cleanups += clean(bind drop_ty(_, tmp, t)); + r = copy_ty(r.bcx, INIT, tmp, lhs, t); + ret trans_vec_append(r.bcx, t, tmp, rhs); } @@ -5423,7 +5430,7 @@ fn make_vec_append_glue(ModuleRef llmod, type_names tn) -> ValueRef { * elements can be copied to a newly alloc'ed vec if one must be * created. * - * 3. Dst vec alias (i.e. ptr to ptr to rust_vec, we will mutate it). + * 3. Dst vec ptr (i.e. ptr to ptr to rust_vec). * * 4. Src vec (i.e. ptr to rust_vec). * @@ -5434,9 +5441,9 @@ fn make_vec_append_glue(ModuleRef llmod, type_names tn) -> ValueRef { auto ty = T_fn(vec(T_taskptr(tn), T_ptr(T_tydesc(tn)), T_ptr(T_tydesc(tn)), - T_ptr(T_ptr(T_vec(T_int()))), // a lie. - T_ptr(T_vec(T_int())), // a lie. - T_bool()), T_void()); + T_ptr(T_opaque_vec_ptr()), + T_opaque_vec_ptr(), T_bool()), + T_void()); auto llfn = decl_fastcall_fn(llmod, abi.vec_append_glue_name(), ty); ret llfn; @@ -5488,10 +5495,8 @@ fn trans_vec_append_glue(@crate_ctxt cx) { vp2i(bcx, llvec_tydesc))); bcx = llnew_vec_res.bcx; - auto llnew_vec = vi2p(bcx, - llnew_vec_res.val, - T_ptr(T_vec(T_int())) // a lie. - ); + auto llnew_vec = vi2p(bcx, llnew_vec_res.val, + T_opaque_vec_ptr()); // FIXME: complete this. -- cgit v1.2.3 From 138c55a69d44371e4de04ed538c787dec46a7200 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Sun, 6 Mar 2011 15:12:33 -0800 Subject: Fix return value on trans_vec_add. --- src/comp/middle/trans.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index c30373e2..dde5aa60 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -2484,7 +2484,8 @@ fn trans_vec_add(@block_ctxt cx, @ty.t t, auto tmp = r.val; find_scope_cx(cx).cleanups += clean(bind drop_ty(_, tmp, t)); r = copy_ty(r.bcx, INIT, tmp, lhs, t); - ret trans_vec_append(r.bcx, t, tmp, rhs); + auto bcx = trans_vec_append(r.bcx, t, tmp, rhs).bcx; + ret res(bcx, load_scalar_or_boxed(bcx, tmp, t)); } -- cgit v1.2.3 From d39da6f97819becd9ea41c194b5f0daa178814fe Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Sun, 6 Mar 2011 13:56:38 -0500 Subject: Remove typestate workarounds --- src/comp/middle/trans.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index dde5aa60..e00d5a92 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -929,8 +929,8 @@ fn static_size_of_tag(@crate_ctxt cx, @ty.t t) -> uint { ret cx.tag_sizes.get(t); } - auto tid = tup(0, 0); // FIXME (#250): typestate botch - let vec[@ty.t] subtys = vec(); // FIXME (#250): typestate botch + auto tid; + let vec[@ty.t] subtys; alt (t.struct) { case (ty.ty_tag(?tid_, ?subtys_)) { tid = tid_; @@ -3419,12 +3419,12 @@ fn trans_bind(@block_ctxt cx, @ast.expr f, } // Figure out which tydescs we need to pass, if any. - // FIXME: typestate botch - let @ty.t outgoing_fty = ty.plain_ty(ty.ty_nil); - let vec[ValueRef] lltydescs = vec(); + let @ty.t outgoing_fty; + let vec[ValueRef] lltydescs; alt (f_res.generic) { case (none[generic_info]) { outgoing_fty = ty.expr_ty(f); + lltydescs = vec(); } case (some[generic_info](?ginfo)) { outgoing_fty = ginfo.item_type; -- cgit v1.2.3 From 386ba3ae63bd0d642af3349c25370605f5200a05 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Sun, 6 Mar 2011 22:37:14 -0800 Subject: Further work on vec-append. Almost working. --- src/comp/middle/trans.rs | 180 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 135 insertions(+), 45 deletions(-) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index e00d5a92..de9aadae 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -1723,6 +1723,8 @@ fn mk_plain_tag(ast.def_id tid) -> @ty.t { } +type val_fn = fn(@block_ctxt cx, ValueRef v) -> result; + type val_and_ty_fn = fn(@block_ctxt cx, ValueRef v, @ty.t t) -> result; type val_pair_and_ty_fn = @@ -1922,23 +1924,17 @@ fn iter_structural_ty_full(@block_ctxt cx, ret r; } -// Iterates through a pair of sequences, until the src* hits the src_lim*. -fn iter_sequence_pair_inner(@block_ctxt cx, - ValueRef dst, // elt* - ValueRef src, // elt* - ValueRef src_lim, // elt* - @ty.t elt_ty, - val_pair_and_ty_fn f) -> result { +// Iterates through a pointer range, until the src* hits the src_lim*. +fn iter_sequence_raw(@block_ctxt cx, + ValueRef src, // elt* + ValueRef src_lim, // elt* + ValueRef elt_sz, + val_fn f) -> result { auto bcx = cx; - auto llunit_ty = type_of(cx.fcx.ccx, elt_ty); - auto unit_sz = size_of(bcx, elt_ty); - bcx = unit_sz.bcx; - let ValueRef src_int = vp2i(bcx, src); let ValueRef src_lim_int = vp2i(bcx, src_lim); - let ValueRef dst_int = vp2i(bcx, dst); auto cond_cx = new_scope_block_ctxt(cx, "sequence-iter cond"); auto body_cx = new_scope_block_ctxt(cx, "sequence-iter body"); @@ -1948,33 +1944,23 @@ fn iter_sequence_pair_inner(@block_ctxt cx, let ValueRef src_curr = cond_cx.build.Phi(T_int(), vec(src_int), vec(bcx.llbb)); - let ValueRef dst_curr = cond_cx.build.Phi(T_int(), - vec(dst_int), vec(bcx.llbb)); - auto end_test = cond_cx.build.ICmp(lib.llvm.LLVMIntNE, + auto end_test = cond_cx.build.ICmp(lib.llvm.LLVMIntULT, src_curr, src_lim_int); cond_cx.build.CondBr(end_test, body_cx.llbb, next_cx.llbb); - auto src_curr_ptr = vi2p(body_cx, src_curr, T_ptr(llunit_ty)); - auto dst_curr_ptr = vi2p(body_cx, dst_curr, T_ptr(llunit_ty)); + auto src_curr_ptr = vi2p(body_cx, src_curr, T_ptr(T_i8())); - auto body_res = f(body_cx, - dst_curr_ptr, - load_scalar_or_boxed(body_cx, src_curr_ptr, elt_ty), - elt_ty); + auto body_res = f(body_cx, src_curr_ptr); body_cx = body_res.bcx; - auto src_next = body_cx.build.Add(src_curr, unit_sz.val); - auto dst_next = body_cx.build.Add(dst_curr, unit_sz.val); + auto src_next = body_cx.build.Add(src_curr, elt_sz); body_cx.build.Br(cond_cx.llbb); cond_cx.build.AddIncomingToPhi(src_curr, vec(src_next), vec(body_cx.llbb)); - cond_cx.build.AddIncomingToPhi(dst_curr, vec(dst_next), - vec(body_cx.llbb)); - ret res(next_cx, C_nil()); } @@ -1985,15 +1971,17 @@ fn iter_sequence_inner(@block_ctxt cx, @ty.t elt_ty, val_and_ty_fn f) -> result { fn adaptor_fn(val_and_ty_fn f, + @ty.t elt_ty, @block_ctxt cx, - ValueRef av, - ValueRef bv, - @ty.t t) -> result { - ret f(cx, bv, t); + ValueRef v) -> result { + auto llty = type_of(cx.fcx.ccx, elt_ty); + auto p = cx.build.PointerCast(v, T_ptr(llty)); + ret f(cx, load_scalar_or_boxed(cx, p, elt_ty), elt_ty); } - be iter_sequence_pair_inner(cx, src, src, src_lim, elt_ty, - bind adaptor_fn(f, _, _, _, _)); + auto elt_sz = size_of(cx, elt_ty); + be iter_sequence_raw(elt_sz.bcx, src, src_lim, elt_sz.val, + bind adaptor_fn(f, elt_ty, _, _)); } @@ -5475,34 +5463,136 @@ fn trans_vec_append_glue(@crate_ctxt cx) { auto bcx = new_top_block_ctxt(fcx); + auto lldst_vec = bcx.build.Load(lldst_vec_ptr); + // First the dst vec needs to grow to accommodate the src vec. // To do this we have to figure out how many bytes to add. - auto n_bytes = - bcx.build.Load(bcx.build.GEP(llsrc_vec, - vec(C_int(0), - C_int(abi.vec_elt_fill)))); - n_bytes = bcx.build.Select(llskipnull, - bcx.build.Sub(n_bytes, C_int(1)), - n_bytes); + fn vec_fill(@block_ctxt bcx, ValueRef v) -> ValueRef { + ret bcx.build.Load(bcx.build.GEP(v, vec(C_int(0), + C_int(abi.vec_elt_fill)))); + } + + fn put_vec_fill(@block_ctxt bcx, ValueRef v, ValueRef fill) -> ValueRef { + ret bcx.build.Store(fill, + bcx.build.GEP(v, + vec(C_int(0), + C_int(abi.vec_elt_fill)))); + } + fn vec_fill_adjusted(@block_ctxt bcx, ValueRef v, + ValueRef skipnull) -> ValueRef { + auto f = bcx.build.Load(bcx.build.GEP(v, + vec(C_int(0), + C_int(abi.vec_elt_fill)))); + ret bcx.build.Select(skipnull, bcx.build.Sub(f, C_int(1)), f); + } - auto llneed_copy_ptr = bcx.build.Alloca(T_int()); + fn vec_p0(@block_ctxt bcx, ValueRef v) -> ValueRef { + auto p = bcx.build.GEP(v, vec(C_int(0), + C_int(abi.vec_elt_data))); + ret bcx.build.PointerCast(p, T_ptr(T_i8())); + } + + + fn vec_p1(@block_ctxt bcx, ValueRef v) -> ValueRef { + auto len = vec_fill(bcx, v); + ret bcx.build.GEP(vec_p0(bcx, v), vec(len)); + } + + fn vec_p1_adjusted(@block_ctxt bcx, ValueRef v, + ValueRef skipnull) -> ValueRef { + auto len = vec_fill_adjusted(bcx, v, skipnull); + ret bcx.build.GEP(vec_p0(bcx, v), vec(len)); + } + + + auto llcopy_dst_ptr = bcx.build.Alloca(T_int()); auto llnew_vec_res = trans_upcall(bcx, "upcall_vec_grow", - vec(vp2i(bcx, bcx.build.Load(lldst_vec_ptr)), - n_bytes, - vp2i(bcx, llneed_copy_ptr), + vec(vp2i(bcx, lldst_vec), + vec_fill_adjusted(bcx, llsrc_vec, llskipnull), + vp2i(bcx, llcopy_dst_ptr), vp2i(bcx, llvec_tydesc))); bcx = llnew_vec_res.bcx; auto llnew_vec = vi2p(bcx, llnew_vec_res.val, T_opaque_vec_ptr()); + put_vec_fill(bcx, llnew_vec, C_int(0)); - // FIXME: complete this. + auto copy_dst_cx = new_sub_block_ctxt(bcx, "copy new <- dst"); + auto copy_src_cx = new_sub_block_ctxt(bcx, "copy new <- src"); - bcx.build.RetVoid(); + auto pp0 = bcx.build.Alloca(T_ptr(T_i8())); + bcx.build.Store(vec_p0(bcx, llnew_vec), pp0); + + bcx.build.CondBr(bcx.build.TruncOrBitCast + (bcx.build.Load(llcopy_dst_ptr), + T_i1()), + copy_dst_cx.llbb, + copy_src_cx.llbb); + + + fn copy_elts(@block_ctxt cx, + ValueRef elt_tydesc, + ValueRef dst, + ValueRef src, + ValueRef n_bytes) -> result { + + auto src_lim = cx.build.GEP(src, vec(n_bytes)); + + auto elt_llsz = + cx.build.Load(cx.build.GEP(elt_tydesc, + vec(C_int(0), + C_int(abi.tydesc_field_size)))); + + fn take_one(ValueRef elt_tydesc, + @block_ctxt cx, ValueRef v) -> result { + call_tydesc_glue_full(cx, v, + elt_tydesc, + abi.tydesc_field_take_glue_off); + ret res(cx, v); + } + + auto bcx = iter_sequence_raw(cx, src, src_lim, + elt_llsz, bind take_one(elt_tydesc, + _, _)).bcx; + + ret call_memcpy(bcx, dst, src, n_bytes); + } + + // Copy any dst elements in, omitting null if doing str. + auto n_bytes = vec_fill_adjusted(copy_dst_cx, lldst_vec, llskipnull); + copy_dst_cx = copy_elts(copy_dst_cx, + llelt_tydesc, + copy_dst_cx.build.Load(pp0), + vec_p0(copy_dst_cx, lldst_vec), + n_bytes).bcx; + + put_vec_fill(copy_dst_cx, llnew_vec, n_bytes); + copy_dst_cx.build.Store(vec_p1_adjusted(copy_dst_cx, + llnew_vec, llskipnull), + pp0); + copy_dst_cx.build.Br(copy_src_cx.llbb); + + + // Copy any src elements in, carrying along null if doing str. + n_bytes = vec_fill(copy_src_cx, llsrc_vec); + copy_src_cx = copy_elts(copy_src_cx, + llelt_tydesc, + copy_src_cx.build.Load(pp0), + vec_p0(copy_src_cx, llsrc_vec), + n_bytes).bcx; + + put_vec_fill(copy_src_cx, llnew_vec, + copy_src_cx.build.Add(vec_fill(copy_src_cx, + llnew_vec), + n_bytes)); + + // Write new_vec back through the alias we were given. + copy_src_cx.build.Store(llnew_vec, lldst_vec_ptr); + copy_src_cx.build.RetVoid(); } -- cgit v1.2.3 From 2cbfb8795d48028f216ffcaf921add36b9d60499 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Sun, 6 Mar 2011 23:06:01 -0800 Subject: Fix off-by-one in vector append code. --- src/comp/middle/trans.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index de9aadae..05aadee2 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -5571,9 +5571,7 @@ fn trans_vec_append_glue(@crate_ctxt cx) { n_bytes).bcx; put_vec_fill(copy_dst_cx, llnew_vec, n_bytes); - copy_dst_cx.build.Store(vec_p1_adjusted(copy_dst_cx, - llnew_vec, llskipnull), - pp0); + copy_dst_cx.build.Store(vec_p1(copy_dst_cx, llnew_vec), pp0); copy_dst_cx.build.Br(copy_src_cx.llbb); -- cgit v1.2.3 From 60657fa8aa1706fec7925b74dffdb1a0c82ceb0b Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Mon, 7 Mar 2011 00:13:56 -0800 Subject: Set the cleanup on the post-growth vector, not the temporary one. --- src/comp/middle/trans.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 05aadee2..0c0d92d4 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -2470,10 +2470,11 @@ fn trans_vec_add(@block_ctxt cx, @ty.t t, ValueRef lhs, ValueRef rhs) -> result { auto r = alloc_ty(cx, t); auto tmp = r.val; - find_scope_cx(cx).cleanups += clean(bind drop_ty(_, tmp, t)); r = copy_ty(r.bcx, INIT, tmp, lhs, t); auto bcx = trans_vec_append(r.bcx, t, tmp, rhs).bcx; - ret res(bcx, load_scalar_or_boxed(bcx, tmp, t)); + tmp = load_scalar_or_boxed(bcx, tmp, t); + find_scope_cx(cx).cleanups += clean(bind drop_ty(_, tmp, t)); + ret res(bcx, tmp); } -- cgit v1.2.3 From 8047957b9981c4f3539ba3d307a65e0255477e81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20=C3=81vila=20de=20Esp=C3=ADndola?= Date: Mon, 7 Mar 2011 15:37:40 -0500 Subject: Construct the wrappers to native functions. Hello world now works :-) --- src/comp/middle/trans.rs | 40 ++++++++++++++++++++++++++++++++++------ 1 file changed, 34 insertions(+), 6 deletions(-) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 0c0d92d4..61715fd2 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -4972,11 +4972,6 @@ fn decl_native_fn_and_pair(@crate_ctxt cx, let str s = cx.names.next("_rust_wrapper") + sep() + name; let ValueRef wrapper_fn = decl_fastcall_fn(cx.llmod, s, wrapper_type); - // Build the wrapper. - auto fcx = new_fn_ctxt(cx, wrapper_fn); - auto bcx = new_top_block_ctxt(fcx); - bcx.build.RetVoid(); - // Declare the global constant pair that points to it. auto wrapper_pair_type = T_fn_pair(cx.tn, wrapper_type); let str ps = cx.names.next("_rust_wrapper_pair") + sep() + name; @@ -4985,7 +4980,40 @@ fn decl_native_fn_and_pair(@crate_ctxt cx, // Declare the function itself. auto llfty = get_pair_fn_ty(node_type(cx, ann)); - decl_cdecl_fn(cx.llmod, name, llfty); + auto function = decl_cdecl_fn(cx.llmod, name, llfty); + + // Build the wrapper. + auto fcx = new_fn_ctxt(cx, wrapper_fn); + auto bcx = new_top_block_ctxt(fcx); + auto fn_type = node_ann_type(cx, ann); + + let vec[ValueRef] call_args = vec(); + auto abi = ty.ty_fn_abi(fn_type); + auto arg_n = 3u; + alt (abi) { + case (ast.native_abi_rust) { + call_args += vec(fcx.lltaskptr); + auto num_ty_param = ty.count_ty_params(plain_ty(fn_type.struct)); + for each (uint i in _uint.range(0u, num_ty_param)) { + auto llarg = llvm.LLVMGetParam(fcx.llfn, arg_n); + check (llarg as int != 0); + call_args += vec(llarg); + arg_n += 1u; + } + } + case (ast.native_abi_cdecl) { + } + } + auto args = ty.ty_fn_args(fn_type); + for (ty.arg arg in args) { + auto llarg = llvm.LLVMGetParam(fcx.llfn, arg_n); + check (llarg as int != 0); + call_args += vec(llarg); + arg_n += 1u; + } + auto r = bcx.build.Call(function, call_args); + bcx.build.Store(r, fcx.llretptr); + bcx.build.RetVoid(); } fn collect_native_item(&@crate_ctxt cx, @ast.native_item i) -> @crate_ctxt { -- cgit v1.2.3 From abbcc0385dfde85c4254ea0278add7b4c6945885 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Mon, 7 Mar 2011 14:05:16 -0800 Subject: Poison ty_param values in trans; fix buggy parametric obj and box malloc paths. Add generic-box test. --- src/comp/middle/trans.rs | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 61715fd2..aa904674 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -661,7 +661,7 @@ fn type_of_inner(@crate_ctxt cx, @ty.t t, bool boxed) -> TypeRef { fail; } case (ty.ty_param(_)) { - llty = T_typaram_ptr(cx.tn); + llty = T_i8(); } case (ty.ty_type) { llty = T_ptr(T_tydesc(cx.tn)); } } @@ -1216,17 +1216,14 @@ fn trans_raw_malloc(@block_ctxt cx, TypeRef llptr_ty, ValueRef llsize) ret rslt; } -fn trans_malloc_without_cleanup(@block_ctxt cx, @ty.t t) -> result { - auto llty = type_of(cx.fcx.ccx, t); - auto llsize = llsize_of(llvm.LLVMGetElementType(llty)); - ret trans_raw_malloc(cx, llty, llsize); -} - -fn trans_malloc(@block_ctxt cx, @ty.t t) -> result { - auto scope_cx = find_scope_cx(cx); - auto rslt = trans_malloc_without_cleanup(cx, t); - scope_cx.cleanups += clean(bind drop_ty(_, rslt.val, t)); - ret rslt; +fn trans_malloc_boxed(@block_ctxt cx, @ty.t t) -> result { + // Synthesize a fake box type structurally so we have something + // to measure the size of. + auto boxed_body = plain_ty(ty.ty_tup(vec(plain_ty(ty.ty_int), t))); + auto box_ptr = plain_ty(ty.ty_box(t)); + auto sz = size_of(cx, boxed_body); + auto llty = type_of(cx.fcx.ccx, box_ptr); + ret trans_raw_malloc(sz.bcx, llty, sz.val); } @@ -2256,7 +2253,11 @@ fn trans_unary(@block_ctxt cx, ast.unop op, case (ast.box) { auto e_ty = ty.expr_ty(e); auto e_val = sub.val; - sub = trans_malloc(sub.bcx, node_ann_type(sub.bcx.fcx.ccx, a)); + auto box_ty = node_ann_type(sub.bcx.fcx.ccx, a); + sub = trans_malloc_boxed(sub.bcx, e_ty); + find_scope_cx(cx).cleanups += + clean(bind drop_ty(_, sub.val, box_ty)); + auto box = sub.val; auto rc = sub.bcx.build.GEP(box, vec(C_int(0), @@ -4707,11 +4708,8 @@ fn trans_obj(@crate_ctxt cx, &ast._obj ob, ast.def_id oid, fields_ty))); let @ty.t boxed_body_ty = plain_ty(ty.ty_box(body_ty)); - let TypeRef llboxed_body_ty = type_of(cx, boxed_body_ty); - // Malloc a box for the body. - auto box = trans_raw_malloc(bcx, llboxed_body_ty, - llsize_of(llvm.LLVMGetElementType(llboxed_body_ty))); + auto box = trans_malloc_boxed(bcx, body_ty); bcx = box.bcx; auto rc = GEP_tup_like(bcx, boxed_body_ty, box.val, vec(0, abi.box_rc_field_refcnt)); -- cgit v1.2.3 From 6f7e21ddac7bd956db55ea6885fbcfd3fb9f29a7 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Mon, 7 Mar 2011 15:43:55 -0800 Subject: rustc: Truncate or zero-extend indexes appropriately. Un-XFAIL integral-indexing.rs. --- src/comp/middle/trans.rs | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index aa904674..7ad96ba2 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -3209,10 +3209,23 @@ fn trans_index(@block_ctxt cx, &ast.span sp, @ast.expr base, auto v = lv.val; auto bcx = ix.bcx; + // Cast to an LLVM integer. Rust is less strict than LLVM in this regard. + auto ix_val; + auto ix_size = llsize_of_real(cx.fcx.ccx, val_ty(ix.val)); + auto int_size = llsize_of_real(cx.fcx.ccx, T_int()); + if (ix_size < int_size) { + ix_val = bcx.build.ZExt(ix.val, T_int()); + } else if (ix_size > int_size) { + ix_val = bcx.build.Trunc(ix.val, T_int()); + } else { + ix_val = ix.val; + } + auto llunit_ty = node_type(cx.fcx.ccx, ann); auto unit_sz = size_of(bcx, node_ann_type(cx.fcx.ccx, ann)); bcx = unit_sz.bcx; - auto scaled_ix = bcx.build.Mul(ix.val, unit_sz.val); + + auto scaled_ix = bcx.build.Mul(ix_val, unit_sz.val); auto lim = bcx.build.GEP(v, vec(C_int(0), C_int(abi.vec_elt_fill))); lim = bcx.build.Load(lim); @@ -3229,7 +3242,7 @@ fn trans_index(@block_ctxt cx, &ast.span sp, @ast.expr base, fail_res.bcx.build.Br(next_cx.llbb); auto body = next_cx.build.GEP(v, vec(C_int(0), C_int(abi.vec_elt_data))); - auto elt = next_cx.build.GEP(body, vec(C_int(0), ix.val)); + auto elt = next_cx.build.GEP(body, vec(C_int(0), ix_val)); ret lval_mem(next_cx, elt); } -- cgit v1.2.3 From 6ed226c6b3a28f3c10d2176d7dba7e339bf0ab99 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Mon, 7 Mar 2011 16:35:00 -0800 Subject: rustc: Cast the LLVM representations of tag types when constructing boxes. Un-XFAIL list.rs. --- src/comp/middle/trans.rs | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'src/comp/middle/trans.rs') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 7ad96ba2..723a845d 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -2266,6 +2266,15 @@ fn trans_unary(@block_ctxt cx, ast.unop op, vec(C_int(0), C_int(abi.box_rc_field_body))); sub.bcx.build.Store(C_int(1), rc); + + // Cast the body type to the type of the value. This is needed to + // make tags work, since tags have a different LLVM type depending + // on whether they're boxed or not. + if (!ty.type_has_dynamic_size(e_ty)) { + auto llety = T_ptr(type_of(sub.bcx.fcx.ccx, e_ty)); + body = sub.bcx.build.PointerCast(body, llety); + } + sub = copy_ty(sub.bcx, INIT, body, e_val, e_ty); ret res(sub.bcx, box); } -- cgit v1.2.3