From 3473ff3bff2ed2286080812417068552d6b9df31 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Mon, 7 Mar 2011 18:03:33 -0800 Subject: rustc: Cast dynamically-sized tags in iter_structural_ty_full() to opaque tag types. Un-XFAIL generic-recursive-tag.rs. --- src/Makefile | 1 - src/comp/middle/trans.rs | 20 ++++++++++++++++---- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/src/Makefile b/src/Makefile index 8855a2d1..a239329f 100644 --- a/src/Makefile +++ b/src/Makefile @@ -453,7 +453,6 @@ TEST_XFAILS_RUSTC := $(addprefix test/run-pass/, \ foreach-simple-outer-slot.rs \ generic-fn-twice.rs \ generic-iter-frame.rs \ - generic-recursive-tag.rs \ generic-tag-alt.rs \ generic-tag-values.rs \ iter-range.rs \ diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 723a845d..a282c0a2 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -1053,6 +1053,9 @@ fn dynamic_align_of(@block_ctxt cx, @ty.t t) -> result { } ret res(bcx, a); } + case (ty.ty_tag(_, _)) { + ret res(cx, C_int(1)); // FIXME: stub + } } } @@ -1805,12 +1808,21 @@ fn iter_structural_ty_full(@block_ctxt cx, auto variants = tag_variants(cx.fcx.ccx, tid); auto n_variants = _vec.len[ast.variant](variants); - 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))); + // Cast the tags to types we can GEP into. + auto lltagty = T_opaque_tag_ptr(cx.fcx.ccx.tn); + auto av_tag = cx.build.PointerCast(av, lltagty); + auto bv_tag = cx.build.PointerCast(bv, lltagty); + + auto lldiscrim_a_ptr = cx.build.GEP(av_tag, + vec(C_int(0), C_int(0))); + auto llunion_a_ptr = cx.build.GEP(av_tag, + 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_ptr = cx.build.GEP(bv_tag, + vec(C_int(0), C_int(0))); + auto llunion_b_ptr = cx.build.GEP(bv_tag, + vec(C_int(0), C_int(1))); auto lldiscrim_b = cx.build.Load(lldiscrim_b_ptr); // NB: we must hit the discriminant first so that structural -- cgit v1.2.3 From 0d60918855aefde24ee8d72238b167ef1b09628b Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Mon, 7 Mar 2011 18:13:39 -0800 Subject: Most of the way through genericizing bind properly with new malloc path. Still getting the thunk call wrong. --- src/comp/middle/trans.rs | 87 ++++++++++++++++++++++----------------- src/test/run-pass/generic-bind.rs | 9 +++- 2 files changed, 56 insertions(+), 40 deletions(-) diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index a282c0a2..fffa325f 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -387,6 +387,10 @@ fn T_closure_ptr(type_names tn, TypeRef lltarget_ty, TypeRef llbindings_ty, uint n_ty_params) -> TypeRef { + + // NB: keep this in sync with code in trans_bind; we're making + // an LLVM typeref structure that has the same "shape" as the ty.t + // it constructs. ret T_ptr(T_box(T_struct(vec(T_ptr(T_tydesc(tn)), lltarget_ty, llbindings_ty, @@ -3322,7 +3326,7 @@ fn trans_bind_thunk(@crate_ctxt cx, @ty.t incoming_fty, @ty.t outgoing_fty, vec[option.t[@ast.expr]] args, - TypeRef llclosure_ty, + @ty.t closure_ty, vec[@ty.t] bound_tys, uint ty_param_count) -> ValueRef { // Construct a thunk-call with signature incoming_fty, and that copies @@ -3335,21 +3339,15 @@ fn trans_bind_thunk(@crate_ctxt cx, auto fcx = new_fn_ctxt(cx, llthunk); auto bcx = new_top_block_ctxt(fcx); - auto llclosure = bcx.build.PointerCast(fcx.llenv, llclosure_ty); - - auto llbody = bcx.build.GEP(llclosure, - vec(C_int(0), - C_int(abi.box_rc_field_body))); - - auto lltarget = bcx.build.GEP(llbody, - vec(C_int(0), - C_int(abi.closure_elt_target))); - - auto llbound = bcx.build.GEP(llbody, - vec(C_int(0), - C_int(abi.closure_elt_bindings))); + auto llclosure_ptr_ty = type_of(cx, plain_ty(ty.ty_box(closure_ty))); + auto llclosure = bcx.build.PointerCast(fcx.llenv, llclosure_ptr_ty); - auto lltargetclosure = bcx.build.GEP(lltarget, + auto lltarget = GEP_tup_like(bcx, closure_ty, llclosure, + vec(0, + abi.box_rc_field_body, + abi.closure_elt_target)); + bcx = lltarget.bcx; + auto lltargetclosure = bcx.build.GEP(lltarget.val, vec(C_int(0), C_int(abi.fn_field_box))); lltargetclosure = bcx.build.Load(lltargetclosure); @@ -3370,10 +3368,13 @@ fn trans_bind_thunk(@crate_ctxt cx, 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)); + GEP_tup_like(bcx, closure_ty, llclosure, + vec(0, + abi.box_rc_field_body, + abi.closure_elt_ty_params, + (i as int))); + bcx = lltyparam_ptr.bcx; + llargs += vec(bcx.build.Load(lltyparam_ptr.val)); i += 1u; } @@ -3385,11 +3386,15 @@ fn trans_bind_thunk(@crate_ctxt cx, // Arg provided at binding time; thunk copies it from closure. case (some[@ast.expr](_)) { - let ValueRef bound_arg = bcx.build.GEP(llbound, - vec(C_int(0), - C_int(b))); + auto bound_arg = + GEP_tup_like(bcx, closure_ty, llclosure, + vec(0, + abi.box_rc_field_body, + abi.closure_elt_bindings, + b)); // FIXME: possibly support passing aliases someday. - llargs += bcx.build.Load(bound_arg); + bcx = bound_arg.bcx; + llargs += bcx.build.Load(bound_arg.val); b += 1; } @@ -3412,7 +3417,7 @@ fn trans_bind_thunk(@crate_ctxt cx, } // FIXME: turn this call + ret into a tail call. - auto lltargetfn = bcx.build.GEP(lltarget, + auto lltargetfn = bcx.build.GEP(lltarget.val, vec(C_int(0), C_int(abi.fn_field_code))); lltargetfn = bcx.build.Load(lltargetfn); @@ -3479,21 +3484,26 @@ fn trans_bind(@block_ctxt cx, @ast.expr f, 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 llbindings_ty = type_of(bcx.fcx.ccx, bindings_ty); - let TypeRef llclosure_ty = T_closure_ptr(cx.fcx.ccx.tn, - lltarget_ty, - llbindings_ty, - ty_param_count); - - // Malloc a box for the body. - // FIXME: this isn't generic-safe - auto r = trans_raw_malloc(bcx, llclosure_ty, - llsize_of(llvm.LLVMGetElementType(llclosure_ty))); + + // NB: keep this in sync with T_closure_ptr; we're making + // a ty.t structure that has the same "shape" as the LLVM type + // it constructs. + let @ty.t tydesc_ty = plain_ty(ty.ty_type); + + let vec[@ty.t] captured_tys = + _vec.init_elt[@ty.t](tydesc_ty, ty_param_count); + + let vec[@ty.t] closure_tys = + vec(tydesc_ty, + outgoing_fty, + bindings_ty, + plain_ty(ty.ty_tup(captured_tys))); + + let @ty.t closure_ty = plain_ty(ty.ty_tup(closure_tys)); + + auto r = trans_malloc_boxed(bcx, closure_ty); auto box = r.val; bcx = r.bcx; auto rc = bcx.build.GEP(box, @@ -3561,9 +3571,10 @@ fn trans_bind(@block_ctxt cx, @ast.expr f, C_int(abi.fn_field_code))); let @ty.t pair_ty = node_ann_type(cx.fcx.ccx, ann); + let ValueRef llthunk = trans_bind_thunk(cx.fcx.ccx, pair_ty, outgoing_fty, - args, llclosure_ty, bound_tys, + args, closure_ty, bound_tys, ty_param_count); bcx.build.Store(llthunk, pair_code); diff --git a/src/test/run-pass/generic-bind.rs b/src/test/run-pass/generic-bind.rs index 61085eb5..5f44bcee 100644 --- a/src/test/run-pass/generic-bind.rs +++ b/src/test/run-pass/generic-bind.rs @@ -3,6 +3,11 @@ fn id[T](&T t) -> T { } fn main() { - auto f = bind id[int](_); - check (f(10) == 10); + auto t = tup(1,2,3,4,5,6,7); + check (t._5 == 6); + // FIXME: this needs to work. + // auto f0 = bind id[tup(int,int,int,int,int,int,int)](t); + auto f1 = bind id[tup(int,int,int,int,int,int,int)](_); + // check (f0()._5 == 6); + check (f1(t)._5 == 6); } -- cgit v1.2.3 From 5ba012f4a54a1c300e49babdc56d3f1ef01339b5 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Mon, 7 Mar 2011 22:05:55 -0500 Subject: Add missing alt arm to expr_if pretty-printer --- src/comp/pretty/pprust.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/comp/pretty/pprust.rs b/src/comp/pretty/pprust.rs index d10f5e7c..aecbf57a 100644 --- a/src/comp/pretty/pprust.rs +++ b/src/comp/pretty/pprust.rs @@ -384,6 +384,7 @@ impure fn print_expr(ps s, @ast.expr expr) { wrd1(s, "else"); print_block(s, blk); } + case (_) { /* fall through */ } } } case (ast.expr_while(?test,?block,_)) { -- cgit v1.2.3 From fa2525a7bdba20fd038e10e3275ce6ba0b1af5b5 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Mon, 7 Mar 2011 21:34:18 -0500 Subject: Remove old pretty-printer from rustc --- src/comp/front/pretty.rs | 87 ------------------------------------------------ src/comp/rustc.rc | 1 - 2 files changed, 88 deletions(-) delete mode 100644 src/comp/front/pretty.rs diff --git a/src/comp/front/pretty.rs b/src/comp/front/pretty.rs deleted file mode 100644 index 2fd58126..00000000 --- a/src/comp/front/pretty.rs +++ /dev/null @@ -1,87 +0,0 @@ -import std._int; -import std._str; -import std._uint; -import std._vec; - -export print_expr; - -// FIXME this is superseded by ../pretty/pprust.rs. can it be dropped? - -fn unknown() -> str { - ret ""; -} - -fn print_expr(@ast.expr expr) -> str { - alt (expr.node) { - case (ast.expr_lit(?lit, _)) { - ret print_lit(lit); - } - case (ast.expr_binary(?op, ?lhs, ?rhs, _)) { - ret print_expr_binary(op, lhs, rhs); - } - case (ast.expr_call(?path, ?args, _)) { - ret print_expr_call(path, args); - } - case (ast.expr_path(?path, _, _)) { - ret print_path(path); - } - case (_) { - ret unknown(); - } - } -} - -fn print_lit(@ast.lit lit) -> str { - alt (lit.node) { - case (ast.lit_str(?s)) { - ret "\"" + s + "\""; - } - case (ast.lit_int(?i)) { - ret _int.to_str(i, 10u); - } - case (ast.lit_uint(?u)) { - ret _uint.to_str(u, 10u); - } - case (_) { - ret unknown(); - } - } -} - -fn print_expr_binary(ast.binop op, @ast.expr lhs, @ast.expr rhs) -> str { - alt (op) { - case (ast.add) { - auto l = print_expr(lhs); - auto r = print_expr(rhs); - ret l + " + " + r; - } - } -} - -fn print_expr_call(@ast.expr path_expr, vec[@ast.expr] args) -> str { - auto s = print_expr(path_expr); - - s += "("; - fn print_expr_ref(&@ast.expr e) -> str { ret print_expr(e); } - auto mapfn = print_expr_ref; - auto argstrs = _vec.map[@ast.expr, str](mapfn, args); - s += _str.connect(argstrs, ", "); - s += ")"; - - ret s; -} - -fn print_path(ast.path path) -> str { - ret _str.connect(path.node.idents, "."); -} - -// -// Local Variables: -// mode: rust -// fill-column: 78; -// indent-tabs-mode: nil -// c-basic-offset: 4 -// buffer-file-coding-system: utf-8-unix -// compile-command: "make -k -C ../.. 2>&1 | sed -e 's/\\/x\\//x:\\//g'"; -// End: -// diff --git a/src/comp/rustc.rc b/src/comp/rustc.rc index e4833409..7e1d8fd9 100644 --- a/src/comp/rustc.rc +++ b/src/comp/rustc.rc @@ -8,7 +8,6 @@ mod front { mod extfmt; mod lexer; mod parser; - mod pretty; mod token; mod eval; } -- cgit v1.2.3 From 5aabe7e84fd329133909ee4ec66c88df74e06f78 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Mon, 7 Mar 2011 21:52:08 -0500 Subject: Add partial pretty-printing for syntax extensions --- src/comp/pretty/pprust.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/comp/pretty/pprust.rs b/src/comp/pretty/pprust.rs index aecbf57a..c54786fd 100644 --- a/src/comp/pretty/pprust.rs +++ b/src/comp/pretty/pprust.rs @@ -512,8 +512,17 @@ impure fn print_expr(ps s, @ast.expr expr) { wrd1(s, "check"); print_expr(s, expr); } + case (ast.expr_ext(?path, ?args, ?body, _, _)) { + wrd(s, "#"); + print_path(s, path); + if (_vec.len[@ast.expr](args) > 0u) { + popen(s); + commasep[@ast.expr](s, args, pe); + pclose(s); + } + // TODO: extension 'body' + } case (_) {wrd(s, "X");} - // TODO expr_ext(path, vec[@expr], option.t[@expr], @expr, ann); } end(s); } -- cgit v1.2.3 From 0054efc412d8f8a1e08840a5ea2146c799501d91 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Tue, 8 Mar 2011 10:56:55 -0800 Subject: rustc: Store the number of type parameters per item, which will be needed to get unused type params working --- src/comp/middle/typeck.rs | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index c257a167..ec04d684 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -39,10 +39,12 @@ tag any_item { } type ty_item_table = hashmap[ast.def_id,any_item]; +type ty_param_count_table = hashmap[ast.def_id,uint]; type crate_ctxt = rec(session.session sess, @ty_table item_types, @ty_item_table item_items, + @ty_param_count_table ty_param_counts, vec[ast.obj_field] obj_fields, mutable int next_var_id); @@ -356,7 +358,7 @@ fn ty_of_native_fn_decl(@ty_item_table id_to_ty_item, } fn collect_item_types(session.session sess, @ast.crate crate) - -> tup(@ast.crate, @ty_table, @ty_item_table) { + -> tup(@ast.crate, @ty_table, @ty_item_table, @ty_param_count_table) { fn getter(@ty_item_table id_to_ty_item, @ty_table item_to_ty, @@ -600,14 +602,17 @@ fn collect_item_types(session.session sess, @ast.crate crate) // Second pass: translate the types of all items. let @ty_table item_to_ty = @common.new_def_hash[@ty.t](); + let @ty_param_count_table ty_param_counts = @common.new_def_hash[uint](); type env = rec(session.session sess, @ty_item_table id_to_ty_item, @ty_table item_to_ty, + @ty_param_count_table ty_param_counts, ast.native_abi abi); let @env e = @rec(sess=sess, id_to_ty_item=id_to_ty_item, item_to_ty=item_to_ty, + ty_param_counts=ty_param_counts, abi=ast.native_abi_cdecl); fn convert(&@env e, @ast.item i) -> @env { @@ -647,6 +652,8 @@ fn collect_item_types(session.session sess, @ast.crate crate) fn fold_item_fn(&@env e, &span sp, ast.ident i, &ast._fn f, vec[ast.ty_param] ty_params, ast.def_id id, ast.ann a) -> @ast.item { + e.ty_param_counts.insert(id, _vec.len[ast.ty_param](ty_params)); + check (e.item_to_ty.contains_key(id)); auto ty = e.item_to_ty.get(id); auto item = ast.item_fn(i, f, ty_params, id, @@ -657,6 +664,8 @@ fn collect_item_types(session.session sess, @ast.crate crate) fn fold_native_item_fn(&@env e, &span sp, ast.ident i, &ast.fn_decl d, vec[ast.ty_param] ty_params, ast.def_id id, ast.ann a) -> @ast.native_item { + e.ty_param_counts.insert(id, _vec.len[ast.ty_param](ty_params)); + check (e.item_to_ty.contains_key(id)); auto ty = e.item_to_ty.get(id); auto item = ast.native_item_fn(i, d, ty_params, id, @@ -688,6 +697,8 @@ fn collect_item_types(session.session sess, @ast.crate crate) fn fold_item_obj(&@env e, &span sp, ast.ident i, &ast._obj ob, vec[ast.ty_param] ty_params, ast.def_id id, ast.ann a) -> @ast.item { + e.ty_param_counts.insert(id, _vec.len[ast.ty_param](ty_params)); + check (e.item_to_ty.contains_key(id)); auto t = e.item_to_ty.get(id); let vec[method] meth_tys = get_ctor_obj_methods(t); @@ -726,6 +737,8 @@ fn collect_item_types(session.session sess, @ast.crate crate) fn fold_item_ty(&@env e, &span sp, ast.ident i, @ast.ty t, vec[ast.ty_param] ty_params, ast.def_id id, ast.ann a) -> @ast.item { + e.ty_param_counts.insert(id, _vec.len[ast.ty_param](ty_params)); + check (e.item_to_ty.contains_key(id)); auto ty = e.item_to_ty.get(id); auto item = ast.item_ty(i, t, ty_params, id, @@ -737,6 +750,8 @@ fn collect_item_types(session.session sess, @ast.crate crate) vec[ast.variant] variants, vec[ast.ty_param] ty_params, ast.def_id id) -> @ast.item { + e.ty_param_counts.insert(id, _vec.len[ast.ty_param](ty_params)); + auto variants_t = get_tag_variant_types(e.id_to_ty_item, e.item_to_ty, id, @@ -758,7 +773,7 @@ fn collect_item_types(session.session sess, @ast.crate crate) fold_item_tag = bind fold_item_tag(_,_,_,_,_,_) with *fld_2); auto crate_ = fold.fold_crate[@env](e, fld_2, crate); - ret tup(crate_, item_to_ty, id_to_ty_item); + ret tup(crate_, item_to_ty, id_to_ty_item, ty_param_counts); } fn unify(&@fn_ctxt fcx, @ty.t expected, @ty.t actual) -> ty.unify_result { @@ -2255,6 +2270,7 @@ fn check_crate(session.session sess, @ast.crate crate) -> @ast.crate { auto ccx = @rec(sess=sess, item_types=result._1, item_items=result._2, + ty_param_counts=result._3, obj_fields=fields, mutable next_var_id=0); -- cgit v1.2.3 From 473a2425251f43ba6ba003db37ce1f03c964a831 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Tue, 8 Mar 2011 11:27:36 -0800 Subject: rustc: Store type parameter definition IDs instead of type parameter counts in the typechecker --- src/comp/middle/typeck.rs | 36 +++++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index ec04d684..002a011b 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -39,12 +39,12 @@ tag any_item { } type ty_item_table = hashmap[ast.def_id,any_item]; -type ty_param_count_table = hashmap[ast.def_id,uint]; +type ty_param_table = hashmap[ast.def_id,vec[ast.def_id]]; type crate_ctxt = rec(session.session sess, @ty_table item_types, @ty_item_table item_items, - @ty_param_count_table ty_param_counts, + @ty_param_table item_ty_params, vec[ast.obj_field] obj_fields, mutable int next_var_id); @@ -358,7 +358,7 @@ fn ty_of_native_fn_decl(@ty_item_table id_to_ty_item, } fn collect_item_types(session.session sess, @ast.crate crate) - -> tup(@ast.crate, @ty_table, @ty_item_table, @ty_param_count_table) { + -> tup(@ast.crate, @ty_table, @ty_item_table, @ty_param_table) { fn getter(@ty_item_table id_to_ty_item, @ty_table item_to_ty, @@ -602,19 +602,29 @@ fn collect_item_types(session.session sess, @ast.crate crate) // Second pass: translate the types of all items. let @ty_table item_to_ty = @common.new_def_hash[@ty.t](); - let @ty_param_count_table ty_param_counts = @common.new_def_hash[uint](); + auto item_ty_params = @common.new_def_hash[vec[ast.def_id]](); type env = rec(session.session sess, @ty_item_table id_to_ty_item, @ty_table item_to_ty, - @ty_param_count_table ty_param_counts, + @ty_param_table item_ty_params, ast.native_abi abi); let @env e = @rec(sess=sess, id_to_ty_item=id_to_ty_item, item_to_ty=item_to_ty, - ty_param_counts=ty_param_counts, + item_ty_params=item_ty_params, abi=ast.native_abi_cdecl); + // Inserts the given type parameters into the type parameter table of the + // environment. + fn collect_ty_params(&@env e, &ast.def_id id, vec[ast.ty_param] tps) { + let vec[ast.def_id] result = vec(); + for (ast.ty_param tp in tps) { + result += vec(tp.id); + } + e.item_ty_params.insert(id, result); + } + fn convert(&@env e, @ast.item i) -> @env { auto abi = e.abi; alt (i.node) { @@ -652,7 +662,7 @@ fn collect_item_types(session.session sess, @ast.crate crate) fn fold_item_fn(&@env e, &span sp, ast.ident i, &ast._fn f, vec[ast.ty_param] ty_params, ast.def_id id, ast.ann a) -> @ast.item { - e.ty_param_counts.insert(id, _vec.len[ast.ty_param](ty_params)); + collect_ty_params(e, id, ty_params); check (e.item_to_ty.contains_key(id)); auto ty = e.item_to_ty.get(id); @@ -664,7 +674,7 @@ fn collect_item_types(session.session sess, @ast.crate crate) fn fold_native_item_fn(&@env e, &span sp, ast.ident i, &ast.fn_decl d, vec[ast.ty_param] ty_params, ast.def_id id, ast.ann a) -> @ast.native_item { - e.ty_param_counts.insert(id, _vec.len[ast.ty_param](ty_params)); + collect_ty_params(e, id, ty_params); check (e.item_to_ty.contains_key(id)); auto ty = e.item_to_ty.get(id); @@ -697,7 +707,7 @@ fn collect_item_types(session.session sess, @ast.crate crate) fn fold_item_obj(&@env e, &span sp, ast.ident i, &ast._obj ob, vec[ast.ty_param] ty_params, ast.def_id id, ast.ann a) -> @ast.item { - e.ty_param_counts.insert(id, _vec.len[ast.ty_param](ty_params)); + collect_ty_params(e, id, ty_params); check (e.item_to_ty.contains_key(id)); auto t = e.item_to_ty.get(id); @@ -737,7 +747,7 @@ fn collect_item_types(session.session sess, @ast.crate crate) fn fold_item_ty(&@env e, &span sp, ast.ident i, @ast.ty t, vec[ast.ty_param] ty_params, ast.def_id id, ast.ann a) -> @ast.item { - e.ty_param_counts.insert(id, _vec.len[ast.ty_param](ty_params)); + collect_ty_params(e, id, ty_params); check (e.item_to_ty.contains_key(id)); auto ty = e.item_to_ty.get(id); @@ -750,7 +760,7 @@ fn collect_item_types(session.session sess, @ast.crate crate) vec[ast.variant] variants, vec[ast.ty_param] ty_params, ast.def_id id) -> @ast.item { - e.ty_param_counts.insert(id, _vec.len[ast.ty_param](ty_params)); + collect_ty_params(e, id, ty_params); auto variants_t = get_tag_variant_types(e.id_to_ty_item, e.item_to_ty, @@ -773,7 +783,7 @@ fn collect_item_types(session.session sess, @ast.crate crate) fold_item_tag = bind fold_item_tag(_,_,_,_,_,_) with *fld_2); auto crate_ = fold.fold_crate[@env](e, fld_2, crate); - ret tup(crate_, item_to_ty, id_to_ty_item, ty_param_counts); + ret tup(crate_, item_to_ty, id_to_ty_item, item_ty_params); } fn unify(&@fn_ctxt fcx, @ty.t expected, @ty.t actual) -> ty.unify_result { @@ -2270,7 +2280,7 @@ fn check_crate(session.session sess, @ast.crate crate) -> @ast.crate { auto ccx = @rec(sess=sess, item_types=result._1, item_items=result._2, - ty_param_counts=result._3, + item_ty_params=result._3, obj_fields=fields, mutable next_var_id=0); -- cgit v1.2.3 From 51be50490e277ce61d156fcf40a5d5b4057eee64 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Tue, 8 Mar 2011 11:59:38 -0800 Subject: rustc: Expose common.def_eq(). --- src/comp/util/common.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/comp/util/common.rs b/src/comp/util/common.rs index 071acea2..63ec2c69 100644 --- a/src/comp/util/common.rs +++ b/src/comp/util/common.rs @@ -46,6 +46,10 @@ fn new_str_hash[V]() -> std.map.hashmap[str,V] { ret std.map.mk_hashmap[str,V](hasher, eqer); } +fn def_eq(&ast.def_id a, &ast.def_id b) -> bool { + ret a._0 == b._0 && a._1 == b._1; +} + fn new_def_hash[V]() -> std.map.hashmap[ast.def_id,V] { fn hash(&ast.def_id d) -> uint { @@ -55,12 +59,8 @@ fn new_def_hash[V]() -> std.map.hashmap[ast.def_id,V] { ret u; } - fn eq(&ast.def_id a, &ast.def_id b) -> bool { - ret a._0 == b._0 && a._1 == b._1; - } - let std.map.hashfn[ast.def_id] hasher = hash; - let std.map.eqfn[ast.def_id] eqer = eq; + let std.map.eqfn[ast.def_id] eqer = def_eq; ret std.map.mk_hashmap[ast.def_id,V](hasher, eqer); } -- cgit v1.2.3 From e2f6f19fc807e1e9067a5fa6abc188ddf21f775c Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Tue, 8 Mar 2011 12:19:37 -0800 Subject: rustc: Rework type substitution to pair up type parameter IDs with the supplied type parameter instantiations explicitly --- src/comp/middle/typeck.rs | 103 +++++++++++++++++++++++++++------------------- 1 file changed, 60 insertions(+), 43 deletions(-) diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index 002a011b..9634841a 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -85,59 +85,47 @@ fn generalize_ty(@crate_ctxt cx, @ty.t t) -> @ty.t { // expression. fn substitute_ty_params(&@crate_ctxt ccx, @ty.t typ, + vec[ast.def_id] ty_params, vec[@ast.ty] supplied, &span sp) -> @ty.t { state obj ty_substituter(@crate_ctxt ccx, - @mutable uint i, - vec[@ast.ty] supplied, - @hashmap[int,@ty.t] substs) { + vec[ast.def_id] ty_params, + vec[@ast.ty] supplied) { fn fold_simple_ty(@ty.t typ) -> @ty.t { alt (typ.struct) { - case (ty.ty_var(?vid)) { - alt (substs.find(vid)) { - case (some[@ty.t](?resolved_ty)) { - ret resolved_ty; - } - case (none[@ty.t]) { - if (i >= _vec.len[@ast.ty](supplied)) { - // Just leave it as an unresolved parameter - // for now. (We will error out later.) - ret typ; - } - - auto result = ast_ty_to_ty_crate(ccx, - supplied.(*i)); - *i += 1u; - substs.insert(vid, result); - ret result; - } + case (ty.ty_param(?pid)) { + // Find the index of the type parameter. + auto ty_param_len = _vec.len[ast.def_id](ty_params); + auto i = 0u; + while (i < ty_param_len && + !common.def_eq(pid, ty_params.(i))) { + i += 1u; + } + if (i == ty_param_len) { + log "substitute_ty_params(): " + + "no ty param for param id!"; + fail; } + + // Substitute it in. + ret ast_ty_to_ty_crate(ccx, supplied.(i)); } case (_) { ret typ; } } } } - fn hash_int(&int x) -> uint { ret x as uint; } - fn eq_int(&int a, &int b) -> bool { ret a == b; } - auto hasher = hash_int; - auto eqer = eq_int; - auto substs = @map.mk_hashmap[int,@ty.t](hasher, eqer); - - auto subst_count = @mutable 0u; - auto substituter = ty_substituter(ccx, subst_count, supplied, substs); - - auto result = ty.fold_ty(substituter, typ); - + auto ty_param_len = _vec.len[ast.def_id](ty_params); auto supplied_len = _vec.len[@ast.ty](supplied); - if ((*subst_count) != supplied_len) { - ccx.sess.span_err(sp, "expected " + _uint.to_str(*subst_count, 10u) + + if (ty_param_len != supplied_len) { + ccx.sess.span_err(sp, "expected " + _uint.to_str(ty_param_len, 10u) + " type parameter(s) but found " + _uint.to_str(supplied_len, 10u) + " parameter(s)"); fail; } - ret result; + auto substituter = ty_substituter(ccx, ty_params, supplied); + ret ty.fold_ty(substituter, typ); } // Parses the programmer's textual representation of a type into our internal @@ -1476,49 +1464,60 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr { case (ast.expr_path(?pth, ?defopt, _)) { auto t = plain_ty(ty.ty_nil); check (defopt != none[ast.def]); + + auto ty_params; alt (option.get[ast.def](defopt)) { case (ast.def_arg(?id)) { check (fcx.locals.contains_key(id)); t = fcx.locals.get(id); + ty_params = none[vec[ast.def_id]]; } case (ast.def_local(?id)) { alt (fcx.locals.find(id)) { case (some[@ty.t](?t1)) { t = t1; } case (none[@ty.t]) { t = plain_ty(ty.ty_local(id)); } } + ty_params = none[vec[ast.def_id]]; } case (ast.def_obj_field(?id)) { check (fcx.locals.contains_key(id)); t = fcx.locals.get(id); + ty_params = none[vec[ast.def_id]]; } case (ast.def_fn(?id)) { check (fcx.ccx.item_types.contains_key(id)); - t = generalize_ty(fcx.ccx, fcx.ccx.item_types.get(id)); + t = fcx.ccx.item_types.get(id); + ty_params = some(fcx.ccx.item_ty_params.get(id)); } case (ast.def_native_fn(?id)) { check (fcx.ccx.item_types.contains_key(id)); - t = generalize_ty(fcx.ccx, fcx.ccx.item_types.get(id)); + t = fcx.ccx.item_types.get(id); + ty_params = some(fcx.ccx.item_ty_params.get(id)); } case (ast.def_const(?id)) { check (fcx.ccx.item_types.contains_key(id)); t = fcx.ccx.item_types.get(id); + ty_params = none[vec[ast.def_id]]; } - case (ast.def_variant(_, ?variant_id)) { + case (ast.def_variant(?tag_id, ?variant_id)) { check (fcx.ccx.item_types.contains_key(variant_id)); - t = generalize_ty(fcx.ccx, - fcx.ccx.item_types.get(variant_id)); + t = fcx.ccx.item_types.get(variant_id); + ty_params = some(fcx.ccx.item_ty_params.get(tag_id)); } case (ast.def_binding(?id)) { check (fcx.locals.contains_key(id)); t = fcx.locals.get(id); + ty_params = none[vec[ast.def_id]]; } case (ast.def_obj(?id)) { check (fcx.ccx.item_types.contains_key(id)); - t = generalize_ty(fcx.ccx, fcx.ccx.item_types.get(id)); + t = fcx.ccx.item_types.get(id); + ty_params = some(fcx.ccx.item_ty_params.get(id)); } case (ast.def_mod(_)) { // Hopefully part of a path. + ty_params = none[vec[ast.def_id]]; } case (_) { @@ -1531,8 +1530,26 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr { // Substitute type parameters if the user provided some. if (_vec.len[@ast.ty](pth.node.types) > 0u) { - t = substitute_ty_params(fcx.ccx, t, pth.node.types, - expr.span); + alt (ty_params) { + case (none[vec[ast.def_id]]) { + fcx.ccx.sess.span_err(expr.span, "this kind of " + + "item may not take type " + + "parameters"); + } + case (some[vec[ast.def_id]](?tps)) { + t = substitute_ty_params(fcx.ccx, t, tps, + pth.node.types, expr.span); + } + } + } else { + alt (ty_params) { + case (none[vec[ast.def_id]]) { /* nothing */ } + case (some[vec[ast.def_id]](_)) { + // We will acquire the type parameters through + // unification. + t = generalize_ty(fcx.ccx, t); + } + } } ret @fold.respan[ast.expr_](expr.span, -- cgit v1.2.3 From 4654faa67c831728c677027f2beb48fe3592b511 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Tue, 8 Mar 2011 12:42:56 -0800 Subject: rustc: Add a slot for explicit type parameter instantations to the typechecker's AST annotation --- src/comp/front/ast.rs | 2 +- src/comp/middle/trans.rs | 2 +- src/comp/middle/ty.rs | 2 +- src/comp/middle/typeck.rs | 197 ++++++++++++++++++++++++++++------------------ 4 files changed, 122 insertions(+), 81 deletions(-) diff --git a/src/comp/front/ast.rs b/src/comp/front/ast.rs index 52ae66c8..56914800 100644 --- a/src/comp/front/ast.rs +++ b/src/comp/front/ast.rs @@ -21,7 +21,7 @@ type ty_param = rec(ident ident, def_id id); // Annotations added during successive passes. tag ann { ann_none; - ann_type(@middle.ty.t); + ann_type(@middle.ty.t, option.t[vec[@middle.ty.t]] /* ty param substs */); } tag def { diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index fffa325f..7457a532 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -2238,7 +2238,7 @@ fn node_ann_type(@crate_ctxt cx, &ast.ann a) -> @ty.t { case (ast.ann_none) { cx.sess.bug("missing type annotation"); } - case (ast.ann_type(?t)) { + case (ast.ann_type(?t, _)) { ret target_type(cx, t); } } diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs index c33b5d8d..9ae39c9d 100644 --- a/src/comp/middle/ty.rs +++ b/src/comp/middle/ty.rs @@ -599,7 +599,7 @@ fn ann_to_type(&ast.ann ann) -> @t { // shouldn't happen, but can until the typechecker is complete ret plain_ty(ty_var(-1)); // FIXME: broken, broken, broken } - case (ast.ann_type(?ty)) { + case (ast.ann_type(?ty, _)) { ret ty; } } diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index 9634841a..cf917d19 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -540,7 +540,10 @@ fn collect_item_types(session.session sess, @ast.crate crate) item_to_ty.insert(variant.id, result_ty); - auto variant_t = rec(ann=ast.ann_type(result_ty) with variant); + auto variant_t = rec( + ann=ast.ann_type(result_ty, none[vec[@ty.t]]) + with variant + ); result += vec(variant_t); } @@ -641,9 +644,9 @@ fn collect_item_types(session.session sess, @ast.crate crate) @ast.ty t, @ast.expr ex, ast.def_id id, ast.ann a) -> @ast.item { check (e.item_to_ty.contains_key(id)); - auto ty = e.item_to_ty.get(id); + auto typ = e.item_to_ty.get(id); auto item = ast.item_const(i, t, ex, id, - ast.ann_type(ty)); + ast.ann_type(typ, none[vec[@ty.t]])); ret @fold.respan[ast.item_](sp, item); } @@ -653,9 +656,9 @@ fn collect_item_types(session.session sess, @ast.crate crate) collect_ty_params(e, id, ty_params); check (e.item_to_ty.contains_key(id)); - auto ty = e.item_to_ty.get(id); + auto typ = e.item_to_ty.get(id); auto item = ast.item_fn(i, f, ty_params, id, - ast.ann_type(ty)); + ast.ann_type(typ, none[vec[@ty.t]])); ret @fold.respan[ast.item_](sp, item); } @@ -665,9 +668,9 @@ fn collect_item_types(session.session sess, @ast.crate crate) collect_ty_params(e, id, ty_params); check (e.item_to_ty.contains_key(id)); - auto ty = e.item_to_ty.get(id); + auto typ = e.item_to_ty.get(id); auto item = ast.native_item_fn(i, d, ty_params, id, - ast.ann_type(ty)); + ast.ann_type(typ, none[vec[@ty.t]])); ret @fold.respan[ast.native_item_](sp, item); } @@ -713,14 +716,20 @@ fn collect_item_types(session.session sess, @ast.crate crate) auto meth_tfn = plain_ty(ty.ty_fn(meth_ty.proto, meth_ty.inputs, meth_ty.output)); - m_ = rec(ann=ast.ann_type(meth_tfn) with meth.node); + m_ = rec( + ann=ast.ann_type(meth_tfn, none[vec[@ty.t]]) + with meth.node + ); m = @rec(node=m_ with *meth); append[@ast.method](methods, m); } auto g = bind getter(e.id_to_ty_item, e.item_to_ty, _); for (ast.obj_field fld in ob.fields) { let @ty.t fty = ast_ty_to_ty(g, fld.ty); - let ast.obj_field f = rec(ann=ast.ann_type(fty) with fld); + let ast.obj_field f = rec( + ann=ast.ann_type(fty, none[vec[@ty.t]]) + with fld + ); append[ast.obj_field](fields, f); } @@ -728,7 +737,7 @@ fn collect_item_types(session.session sess, @ast.crate crate) fields = fields with ob); auto item = ast.item_obj(i, ob_, ty_params, id, - ast.ann_type(t)); + ast.ann_type(t, none[vec[@ty.t]])); ret @fold.respan[ast.item_](sp, item); } @@ -738,9 +747,9 @@ fn collect_item_types(session.session sess, @ast.crate crate) collect_ty_params(e, id, ty_params); check (e.item_to_ty.contains_key(id)); - auto ty = e.item_to_ty.get(id); + auto typ = e.item_to_ty.get(id); auto item = ast.item_ty(i, t, ty_params, id, - ast.ann_type(ty)); + ast.ann_type(typ, none[vec[@ty.t]])); ret @fold.respan[ast.item_](sp, item); } @@ -908,16 +917,16 @@ fn demand_pat(&@fn_ctxt fcx, @ty.t expected, @ast.pat pat) -> @ast.pat { alt (pat.node) { case (ast.pat_wild(?ann)) { auto t = demand(fcx, pat.span, expected, ann_to_type(ann)); - p_1 = ast.pat_wild(ast.ann_type(t)); + p_1 = ast.pat_wild(ast.ann_type(t, none[vec[@ty.t]])); } case (ast.pat_lit(?lit, ?ann)) { auto t = demand(fcx, pat.span, expected, ann_to_type(ann)); - p_1 = ast.pat_lit(lit, ast.ann_type(t)); + p_1 = ast.pat_lit(lit, ast.ann_type(t, none[vec[@ty.t]])); } case (ast.pat_bind(?id, ?did, ?ann)) { auto t = demand(fcx, pat.span, expected, ann_to_type(ann)); fcx.locals.insert(did, t); - p_1 = ast.pat_bind(id, did, ast.ann_type(t)); + p_1 = ast.pat_bind(id, did, ast.ann_type(t, none[vec[@ty.t]])); } case (ast.pat_tag(?id, ?subpats, ?vdef_opt, ?ann)) { auto t = demand(fcx, pat.span, expected, ann_to_type(ann)); @@ -939,10 +948,14 @@ fn demand_pat(&@fn_ctxt fcx, @ty.t expected, @ast.pat pat) -> @ast.pat { alt (variant_ty.struct) { case (ty.ty_tag(_, _)) { // Nullary tag variant. + // TODO: ty param substs check (subpats_len == 0u); - p_1 = ast.pat_tag(id, subpats, vdef_opt, ast.ann_type(t)); + p_1 = ast.pat_tag(id, subpats, vdef_opt, + ast.ann_type(t, none[vec[@ty.t]])); } case (ty.ty_fn(_, ?args, ?tag_ty)) { + // N-ary tag variant. + // TODO: ty param substs let vec[@ast.pat] new_subpats = vec(); auto i = 0u; for (arg a in args) { @@ -951,7 +964,7 @@ fn demand_pat(&@fn_ctxt fcx, @ty.t expected, @ast.pat pat) -> @ast.pat { i += 1u; } p_1 = ast.pat_tag(id, new_subpats, vdef_opt, - ast.ann_type(tag_ty)); + ast.ann_type(tag_ty, none[vec[@ty.t]])); } } } @@ -990,7 +1003,7 @@ fn demand_expr_full(&@fn_ctxt fcx, @ty.t expected, @ast.expr e, fail; } } - e_1 = ast.expr_vec(es_1, ast.ann_type(t)); + e_1 = ast.expr_vec(es_1, ast.ann_type(t, none[vec[@ty.t]])); } case (ast.expr_tup(?es_0, ?ann)) { auto t = demand(fcx, e.span, expected, ann_to_type(ann)); @@ -1009,7 +1022,7 @@ fn demand_expr_full(&@fn_ctxt fcx, @ty.t expected, @ast.expr e, fail; } } - e_1 = ast.expr_tup(elts_1, ast.ann_type(t)); + e_1 = ast.expr_tup(elts_1, ast.ann_type(t, none[vec[@ty.t]])); } case (ast.expr_rec(?fields_0, ?base_0, ?ann)) { @@ -1062,11 +1075,12 @@ fn demand_expr_full(&@fn_ctxt fcx, @ty.t expected, @ast.expr e, fail; } } - e_1 = ast.expr_rec(fields_1, base_1, ast.ann_type(t)); + e_1 = ast.expr_rec(fields_1, base_1, + ast.ann_type(t, none[vec[@ty.t]])); } case (ast.expr_bind(?sube, ?es, ?ann)) { auto t = demand(fcx, e.span, expected, ann_to_type(ann)); - e_1 = ast.expr_bind(sube, es, ast.ann_type(t)); + e_1 = ast.expr_bind(sube, es, ast.ann_type(t, none[vec[@ty.t]])); } case (ast.expr_call(?sube, ?es, ?ann)) { // NB: we call 'demand_full' and pass in adk only in cases where @@ -1074,25 +1088,28 @@ fn demand_expr_full(&@fn_ctxt fcx, @ty.t expected, @ast.expr e, // like expr_binary or expr_bind can't, so there's no need. auto t = demand_full(fcx, e.span, expected, ann_to_type(ann), adk); - e_1 = ast.expr_call(sube, es, ast.ann_type(t)); + e_1 = ast.expr_call(sube, es, ast.ann_type(t, none[vec[@ty.t]])); } case (ast.expr_binary(?bop, ?lhs, ?rhs, ?ann)) { auto t = demand(fcx, e.span, expected, ann_to_type(ann)); - e_1 = ast.expr_binary(bop, lhs, rhs, ast.ann_type(t)); + e_1 = ast.expr_binary(bop, lhs, rhs, + ast.ann_type(t, none[vec[@ty.t]])); } case (ast.expr_unary(?uop, ?sube, ?ann)) { // See note in expr_unary for why we're calling demand_full. auto t = demand_full(fcx, e.span, expected, ann_to_type(ann), adk); - e_1 = ast.expr_unary(uop, sube, ast.ann_type(t)); + e_1 = ast.expr_unary(uop, sube, + ast.ann_type(t, none[vec[@ty.t]])); } case (ast.expr_lit(?lit, ?ann)) { auto t = demand(fcx, e.span, expected, ann_to_type(ann)); - e_1 = ast.expr_lit(lit, ast.ann_type(t)); + e_1 = ast.expr_lit(lit, ast.ann_type(t, none[vec[@ty.t]])); } case (ast.expr_cast(?sube, ?ast_ty, ?ann)) { auto t = demand(fcx, e.span, expected, ann_to_type(ann)); - e_1 = ast.expr_cast(sube, ast_ty, ast.ann_type(t)); + e_1 = ast.expr_cast(sube, ast_ty, + ast.ann_type(t, none[vec[@ty.t]])); } case (ast.expr_if(?cond, ?then_0, ?elifs_0, ?else_0, ?ann)) { auto t = demand_full(fcx, e.span, expected, @@ -1115,62 +1132,71 @@ fn demand_expr_full(&@fn_ctxt fcx, @ty.t expected, @ast.expr e, else_1 = some[ast.block](b_1); } } - e_1 = ast.expr_if(cond, then_1, elifs_1, else_1, ast.ann_type(t)); + e_1 = ast.expr_if(cond, then_1, elifs_1, else_1, + ast.ann_type(t, none[vec[@ty.t]])); } case (ast.expr_for(?decl, ?seq, ?bloc, ?ann)) { auto t = demand(fcx, e.span, expected, ann_to_type(ann)); - e_1 = ast.expr_for(decl, seq, bloc, ast.ann_type(t)); + e_1 = ast.expr_for(decl, seq, bloc, + ast.ann_type(t, none[vec[@ty.t]])); } case (ast.expr_for_each(?decl, ?seq, ?bloc, ?ann)) { auto t = demand(fcx, e.span, expected, ann_to_type(ann)); - e_1 = ast.expr_for_each(decl, seq, bloc, ast.ann_type(t)); + e_1 = ast.expr_for_each(decl, seq, bloc, + ast.ann_type(t, none[vec[@ty.t]])); } case (ast.expr_while(?cond, ?bloc, ?ann)) { auto t = demand(fcx, e.span, expected, ann_to_type(ann)); - e_1 = ast.expr_while(cond, bloc, ast.ann_type(t)); + e_1 = ast.expr_while(cond, bloc, + ast.ann_type(t, none[vec[@ty.t]])); } case (ast.expr_do_while(?bloc, ?cond, ?ann)) { auto t = demand(fcx, e.span, expected, ann_to_type(ann)); - e_1 = ast.expr_do_while(bloc, cond, ast.ann_type(t)); + e_1 = ast.expr_do_while(bloc, cond, + ast.ann_type(t, none[vec[@ty.t]])); } case (ast.expr_block(?bloc, ?ann)) { auto t = demand_full(fcx, e.span, expected, ann_to_type(ann), adk); - e_1 = ast.expr_block(bloc, ast.ann_type(t)); + e_1 = ast.expr_block(bloc, ast.ann_type(t, none[vec[@ty.t]])); } case (ast.expr_assign(?lhs_0, ?rhs_0, ?ann)) { auto t = demand_full(fcx, e.span, expected, ann_to_type(ann), adk); auto lhs_1 = demand_expr(fcx, expected, lhs_0); auto rhs_1 = demand_expr(fcx, expected, rhs_0); - e_1 = ast.expr_assign(lhs_1, rhs_1, ast.ann_type(t)); + e_1 = ast.expr_assign(lhs_1, rhs_1, + ast.ann_type(t, none[vec[@ty.t]])); } case (ast.expr_assign_op(?op, ?lhs_0, ?rhs_0, ?ann)) { auto t = demand_full(fcx, e.span, expected, ann_to_type(ann), adk); auto lhs_1 = demand_expr(fcx, expected, lhs_0); auto rhs_1 = demand_expr(fcx, expected, rhs_0); - e_1 = ast.expr_assign_op(op, lhs_1, rhs_1, ast.ann_type(t)); + e_1 = ast.expr_assign_op(op, lhs_1, rhs_1, + ast.ann_type(t, none[vec[@ty.t]])); } case (ast.expr_field(?lhs, ?rhs, ?ann)) { auto t = demand_full(fcx, e.span, expected, ann_to_type(ann), adk); - e_1 = ast.expr_field(lhs, rhs, ast.ann_type(t)); + e_1 = ast.expr_field(lhs, rhs, ast.ann_type(t, none[vec[@ty.t]])); } case (ast.expr_index(?base, ?index, ?ann)) { auto t = demand_full(fcx, e.span, expected, ann_to_type(ann), adk); - e_1 = ast.expr_index(base, index, ast.ann_type(t)); + e_1 = ast.expr_index(base, index, + ast.ann_type(t, none[vec[@ty.t]])); } case (ast.expr_path(?pth, ?d, ?ann)) { auto t = demand_full(fcx, e.span, expected, ann_to_type(ann), adk); - e_1 = ast.expr_path(pth, d, ast.ann_type(t)); + e_1 = ast.expr_path(pth, d, ast.ann_type(t, none[vec[@ty.t]])); } case (ast.expr_ext(?p, ?args, ?body, ?expanded, ?ann)) { auto t = demand_full(fcx, e.span, expected, ann_to_type(ann), adk); - e_1 = ast.expr_ext(p, args, body, expanded, ast.ann_type(t)); + e_1 = ast.expr_ext(p, args, body, expanded, + ast.ann_type(t, none[vec[@ty.t]])); } case (ast.expr_fail) { e_1 = e.node; } case (ast.expr_log(_)) { e_1 = e.node; } @@ -1213,7 +1239,10 @@ fn writeback_local(&@fn_ctxt fcx, &span sp, @ast.local local) + local.ident); } auto local_ty = fcx.locals.get(local.id); - auto local_wb = @rec(ann=ast.ann_type(local_ty) with *local); + auto local_wb = @rec( + ann=ast.ann_type(local_ty, none[vec[@ty.t]]) + with *local + ); ret @fold.respan[ast.decl_](sp, ast.decl_local(local_wb)); } @@ -1245,13 +1274,15 @@ fn check_pat(&@fn_ctxt fcx, @ast.pat pat) -> @ast.pat { auto new_pat; alt (pat.node) { case (ast.pat_wild(_)) { - new_pat = ast.pat_wild(ast.ann_type(next_ty_var(fcx.ccx))); + new_pat = ast.pat_wild(ast.ann_type(next_ty_var(fcx.ccx), + none[vec[@ty.t]])); } case (ast.pat_lit(?lt, _)) { - new_pat = ast.pat_lit(lt, ast.ann_type(check_lit(lt))); + new_pat = ast.pat_lit(lt, ast.ann_type(check_lit(lt), + none[vec[@ty.t]])); } case (ast.pat_bind(?id, ?def_id, _)) { - auto ann = ast.ann_type(next_ty_var(fcx.ccx)); + auto ann = ast.ann_type(next_ty_var(fcx.ccx), none[vec[@ty.t]]); new_pat = ast.pat_bind(id, def_id, ann); } case (ast.pat_tag(?p, ?subpats, ?vdef_opt, _)) { @@ -1280,7 +1311,7 @@ fn check_pat(&@fn_ctxt fcx, @ast.pat pat) -> @ast.pat { new_subpats += vec(check_pat(fcx, subpat)); } - auto ann = ast.ann_type(tag_ty); + auto ann = ast.ann_type(tag_ty, none[vec[@ty.t]]); new_pat = ast.pat_tag(p, new_subpats, vdef_opt, ann); } @@ -1302,7 +1333,8 @@ fn check_pat(&@fn_ctxt fcx, @ast.pat pat) -> @ast.pat { } let vec[@ty.t] tys = vec(); // FIXME - auto ann = ast.ann_type(plain_ty(ty.ty_tag(tid, tys))); + auto ann = ast.ann_type(plain_ty(ty.ty_tag(tid, tys)), + none[vec[@ty.t]]); new_pat = ast.pat_tag(p, subpats, vdef_opt, ann); } } @@ -1399,9 +1431,9 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr { alt (expr.node) { case (ast.expr_lit(?lit, _)) { - auto ty = check_lit(lit); - ret @fold.respan[ast.expr_](expr.span, - ast.expr_lit(lit, ast.ann_type(ty))); + auto typ = check_lit(lit); + auto ann = ast.ann_type(typ, none[vec[@ty.t]]); + ret @fold.respan[ast.expr_](expr.span, ast.expr_lit(lit, ann)); } @@ -1427,9 +1459,11 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr { case (ast.gt) { t = plain_ty(ty.ty_bool); } case (_) { /* fall through */ } } + + auto ann = ast.ann_type(t, none[vec[@ty.t]]); ret @fold.respan[ast.expr_](expr.span, ast.expr_binary(binop, lhs_1, rhs_1, - ast.ann_type(t))); + ann)); } @@ -1456,9 +1490,10 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr { } case (_) { oper_t = strip_boxes(oper_t); } } + + auto ann = ast.ann_type(oper_t, none[vec[@ty.t]]); ret @fold.respan[ast.expr_](expr.span, - ast.expr_unary(unop, oper_1, - ast.ann_type(oper_t))); + ast.expr_unary(unop, oper_1, ann)); } case (ast.expr_path(?pth, ?defopt, _)) { @@ -1552,17 +1587,18 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr { } } + auto ann = ast.ann_type(t, none[vec[@ty.t]]); ret @fold.respan[ast.expr_](expr.span, - ast.expr_path(pth, defopt, - ast.ann_type(t))); + ast.expr_path(pth, defopt, ann)); } case (ast.expr_ext(?p, ?args, ?body, ?expanded, _)) { auto exp_ = check_expr(fcx, expanded); auto t = expr_ty(exp_); + auto ann = ast.ann_type(t, none[vec[@ty.t]]); ret @fold.respan[ast.expr_](expr.span, ast.expr_ext(p, args, body, exp_, - ast.ann_type(t))); + ann)); } case (ast.expr_fail) { @@ -1641,7 +1677,7 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr { auto lhs_1 = demand_expr(fcx, rhs_t0, lhs_0); auto rhs_1 = demand_expr(fcx, expr_ty(lhs_1), rhs_0); - auto ann = ast.ann_type(rhs_t0); + auto ann = ast.ann_type(rhs_t0, none[vec[@ty.t]]); ret @fold.respan[ast.expr_](expr.span, ast.expr_assign(lhs_1, rhs_1, ann)); } @@ -1655,7 +1691,7 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr { auto lhs_1 = demand_expr(fcx, rhs_t0, lhs_0); auto rhs_1 = demand_expr(fcx, expr_ty(lhs_1), rhs_0); - auto ann = ast.ann_type(rhs_t0); + auto ann = ast.ann_type(rhs_t0, none[vec[@ty.t]]); ret @fold.respan[ast.expr_](expr.span, ast.expr_assign_op(op, lhs_1, rhs_1, ann)); @@ -1700,10 +1736,10 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr { auto thn_1 = demand_block(fcx, elsopt_t, thn_0); + auto ann = ast.ann_type(elsopt_t, none[vec[@ty.t]]); ret @fold.respan[ast.expr_](expr.span, ast.expr_if(cond_1, thn_1, - elifs_1, elsopt_1, - ast.ann_type(elsopt_t))); + elifs_1, elsopt_1, ann)); } case (ast.expr_for(?decl, ?seq, ?body, _)) { @@ -1714,7 +1750,7 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr { // FIXME: enforce that the type of the decl is the element type // of the seq. - auto ann = ast.ann_type(plain_ty(ty.ty_nil)); + auto ann = ast.ann_type(plain_ty(ty.ty_nil), none[vec[@ty.t]]); ret @fold.respan[ast.expr_](expr.span, ast.expr_for(decl_1, seq_1, body_1, ann)); @@ -1725,7 +1761,7 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr { auto seq_1 = check_expr(fcx, seq); auto body_1 = check_block(fcx, body); - auto ann = ast.ann_type(plain_ty(ty.ty_nil)); + auto ann = ast.ann_type(plain_ty(ty.ty_nil), none[vec[@ty.t]]); ret @fold.respan[ast.expr_](expr.span, ast.expr_for_each(decl_1, seq_1, body_1, ann)); @@ -1736,7 +1772,7 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr { auto cond_1 = demand_expr(fcx, plain_ty(ty.ty_bool), cond_0); auto body_1 = check_block(fcx, body); - auto ann = ast.ann_type(plain_ty(ty.ty_nil)); + auto ann = ast.ann_type(plain_ty(ty.ty_nil), none[vec[@ty.t]]); ret @fold.respan[ast.expr_](expr.span, ast.expr_while(cond_1, body_1, ann)); } @@ -1746,7 +1782,7 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr { auto cond_1 = demand_expr(fcx, plain_ty(ty.ty_bool), cond_0); auto body_1 = check_block(fcx, body); - auto ann = ast.ann_type(block_ty(body_1)); + auto ann = ast.ann_type(block_ty(body_1), none[vec[@ty.t]]); ret @fold.respan[ast.expr_](expr.span, ast.expr_do_while(body_1, cond_1, ann)); @@ -1796,7 +1832,7 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr { auto expr_1 = demand_expr(fcx, pattern_ty, expr_0); - auto ann = ast.ann_type(result_ty); + auto ann = ast.ann_type(result_ty, none[vec[@ty.t]]); ret @fold.respan[ast.expr_](expr.span, ast.expr_alt(expr_1, arms_1, ann)); } @@ -1806,10 +1842,10 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr { auto ann; alt (b_0.node.expr) { case (some[@ast.expr](?expr)) { - ann = ast.ann_type(expr_ty(expr)); + ann = ast.ann_type(expr_ty(expr), none[vec[@ty.t]]); } case (none[@ast.expr]) { - ann = ast.ann_type(plain_ty(ty.ty_nil)); + ann = ast.ann_type(plain_ty(ty.ty_nil), none[vec[@ty.t]]); } } ret @fold.respan[ast.expr_](expr.span, @@ -1849,9 +1885,10 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr { } auto t_1 = plain_ty(ty.ty_fn(proto_1, arg_tys_1, rt_1)); + auto ann = ast.ann_type(t_1, none[vec[@ty.t]]); ret @fold.respan[ast.expr_](expr.span, ast.expr_bind(result._0, result._1, - ast.ann_type(t_1))); + ann)); } case (ast.expr_call(?f, ?args, _)) { @@ -1880,9 +1917,10 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr { } } + auto ann = ast.ann_type(rt_1, none[vec[@ty.t]]); ret @fold.respan[ast.expr_](expr.span, ast.expr_call(result._0, args_1, - ast.ann_type(rt_1))); + ann)); } case (ast.expr_cast(?e, ?t, _)) { @@ -1897,9 +1935,10 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr { + " as " + ty_to_str(t_1)); } + + auto ann = ast.ann_type(t_1, none[vec[@ty.t]]); ret @fold.respan[ast.expr_](expr.span, - ast.expr_cast(e_1, t, - ast.ann_type(t_1))); + ast.expr_cast(e_1, t, ann)); } case (ast.expr_vec(?args, _)) { @@ -1922,7 +1961,7 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr { demand(fcx, expr.span, t, expr_t); append[@ast.expr](args_1,expr_1); } - auto ann = ast.ann_type(plain_ty(ty.ty_vec(t))); + auto ann = ast.ann_type(plain_ty(ty.ty_vec(t)), none[vec[@ty.t]]); ret @fold.respan[ast.expr_](expr.span, ast.expr_vec(args_1, ann)); } @@ -1941,7 +1980,8 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr { append[@ty.t](elts_t, expr_t); } - auto ann = ast.ann_type(plain_ty(ty.ty_tup(elts_t))); + auto ann = ast.ann_type(plain_ty(ty.ty_tup(elts_t)), + none[vec[@ty.t]]); ret @fold.respan[ast.expr_](expr.span, ast.expr_tup(elts_1, ann)); } @@ -1967,7 +2007,8 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr { alt (base) { case (none[@ast.expr]) { - ann = ast.ann_type(plain_ty(ty.ty_rec(fields_t))); + ann = ast.ann_type(plain_ty(ty.ty_rec(fields_t)), + none[vec[@ty.t]]); } case (some[@ast.expr](?bexpr)) { @@ -1987,7 +2028,7 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr { } } - ann = ast.ann_type(bexpr_t); + ann = ast.ann_type(bexpr_t, none[vec[@ty.t]]); for (ty.field f in fields_t) { auto found = false; @@ -2022,7 +2063,7 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr { fcx.ccx.sess.span_err(expr.span, "bad index on tuple"); } - auto ann = ast.ann_type(args.(ix)); + auto ann = ast.ann_type(args.(ix), none[vec[@ty.t]]); ret @fold.respan[ast.expr_](expr.span, ast.expr_field(base_1, field, @@ -2036,7 +2077,7 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr { fcx.ccx.sess.span_err(expr.span, "bad index on record"); } - auto ann = ast.ann_type(fields.(ix).ty); + auto ann = ast.ann_type(fields.(ix).ty, none[vec[@ty.t]]); ret @fold.respan[ast.expr_](expr.span, ast.expr_field(base_1, field, @@ -2053,7 +2094,7 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr { auto meth = methods.(ix); auto t = plain_ty(ty.ty_fn(meth.proto, meth.inputs, meth.output)); - auto ann = ast.ann_type(t); + auto ann = ast.ann_type(t, none[vec[@ty.t]]); ret @fold.respan[ast.expr_](expr.span, ast.expr_field(base_1, field, @@ -2083,7 +2124,7 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr { "non-integral type of vec index: " + ty_to_str(idx_t)); } - auto ann = ast.ann_type(t); + auto ann = ast.ann_type(t, none[vec[@ty.t]]); ret @fold.respan[ast.expr_](expr.span, ast.expr_index(base_1, idx_1, @@ -2097,7 +2138,7 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr { + ty_to_str(idx_t)); } auto t = ty.ty_machine(common.ty_u8); - auto ann = ast.ann_type(plain_ty(t)); + auto ann = ast.ann_type(plain_ty(t), none[vec[@ty.t]]); ret @fold.respan[ast.expr_](expr.span, ast.expr_index(base_1, idx_1, @@ -2272,7 +2313,7 @@ fn check_item_fn(&@crate_ctxt ccx, &span sp, ast.ident ident, &ast._fn f, auto output_ty = ast_ty_to_ty_crate(ccx, f.decl.output); auto fn_sty = ty.ty_fn(f.proto, inputs, output_ty); - auto fn_ann = ast.ann_type(plain_ty(fn_sty)); + auto fn_ann = ast.ann_type(plain_ty(fn_sty), none[vec[@ty.t]]); auto item = ast.item_fn(ident, f, ty_params, id, fn_ann); ret @fold.respan[ast.item_](sp, item); -- cgit v1.2.3 From 35bee753dea812bb8112c5bf5c02e1311bbca2fa Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Tue, 8 Mar 2011 13:00:31 -0800 Subject: rustc: Pass explicit type substitutions to later passes --- src/comp/middle/typeck.rs | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index cf917d19..15383020 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -86,11 +86,11 @@ fn generalize_ty(@crate_ctxt cx, @ty.t t) -> @ty.t { fn substitute_ty_params(&@crate_ctxt ccx, @ty.t typ, vec[ast.def_id] ty_params, - vec[@ast.ty] supplied, + vec[@ty.t] supplied, &span sp) -> @ty.t { state obj ty_substituter(@crate_ctxt ccx, vec[ast.def_id] ty_params, - vec[@ast.ty] supplied) { + vec[@ty.t] supplied) { fn fold_simple_ty(@ty.t typ) -> @ty.t { alt (typ.struct) { case (ty.ty_param(?pid)) { @@ -108,7 +108,7 @@ fn substitute_ty_params(&@crate_ctxt ccx, } // Substitute it in. - ret ast_ty_to_ty_crate(ccx, supplied.(i)); + ret supplied.(i); } case (_) { ret typ; } } @@ -116,7 +116,7 @@ fn substitute_ty_params(&@crate_ctxt ccx, } auto ty_param_len = _vec.len[ast.def_id](ty_params); - auto supplied_len = _vec.len[@ast.ty](supplied); + auto supplied_len = _vec.len[@ty.t](supplied); if (ty_param_len != supplied_len) { ccx.sess.span_err(sp, "expected " + _uint.to_str(ty_param_len, 10u) + " type parameter(s) but found " + @@ -1564,19 +1564,33 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr { } // Substitute type parameters if the user provided some. - if (_vec.len[@ast.ty](pth.node.types) > 0u) { + auto ty_substs_opt; + auto ty_substs_len = _vec.len[@ast.ty](pth.node.types); + if (ty_substs_len > 0u) { + let vec[@ty.t] ty_substs = vec(); + auto i = 0u; + while (i < ty_substs_len) { + ty_substs += vec(ast_ty_to_ty_crate(fcx.ccx, + pth.node.types.(i))); + i += 1u; + } + ty_substs_opt = some[vec[@ty.t]](ty_substs); + alt (ty_params) { case (none[vec[ast.def_id]]) { fcx.ccx.sess.span_err(expr.span, "this kind of " + "item may not take type " + "parameters"); + fail; } case (some[vec[ast.def_id]](?tps)) { - t = substitute_ty_params(fcx.ccx, t, tps, - pth.node.types, expr.span); + t = substitute_ty_params(fcx.ccx, t, tps, ty_substs, + expr.span); } } } else { + ty_substs_opt = none[vec[@ty.t]]; + alt (ty_params) { case (none[vec[ast.def_id]]) { /* nothing */ } case (some[vec[ast.def_id]](_)) { @@ -1587,7 +1601,7 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr { } } - auto ann = ast.ann_type(t, none[vec[@ty.t]]); + auto ann = ast.ann_type(t, ty_substs_opt); ret @fold.respan[ast.expr_](expr.span, ast.expr_path(pth, defopt, ann)); } -- cgit v1.2.3 From 55c80e763bfd850682b3217fcfc5cdb516eafae0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20=C3=81vila=20de=20Esp=C3=ADndola?= Date: Tue, 8 Mar 2011 15:32:42 -0500 Subject: Move the glue asm code to a .o file. This reduces how much asm we print in each "translation unit". --- src/Makefile | 23 +++++++++++++++++++---- src/comp/glue.rc | 37 +++++++++++++++++++++++++++++++++++++ src/comp/glue/glue.rs | 11 +++++++++++ src/comp/middle/trans.rs | 2 -- 4 files changed, 67 insertions(+), 6 deletions(-) create mode 100644 src/comp/glue.rc create mode 100644 src/comp/glue/glue.rs diff --git a/src/Makefile b/src/Makefile index a239329f..cafd8d18 100644 --- a/src/Makefile +++ b/src/Makefile @@ -90,6 +90,7 @@ ifdef CFG_WINDOWSY CFG_EXE_SUFFIX := .exe CFG_BOOT := ./rustboot.exe CFG_RUSTC := ./rustc.exe + CFG_GLUE := ./glue.exe CFG_GCC_CFLAGS += -march=i686 CFG_GCC_LINK_FLAGS += -shared -fPIC CFG_RUN_TARG = $(1) @@ -101,6 +102,7 @@ ifdef CFG_UNIXY CFG_INFO := $(info cfg: unix-y environment) CFG_BOOT := ./rustboot CFG_RUSTC := ./rustc + CFG_GLUE := ./glue CFG_OBJ_SUFFIX := .o CFG_RUN_TARG = LD_LIBRARY_PATH=. $(CFG_VALGRIND) $(1) CFG_GCC := 1 @@ -111,6 +113,7 @@ ifdef CFG_UNIXY CFG_RUNTIME := rustrt.dll CFG_STDLIB := std.dll CFG_RUSTC := ./rustc.exe + CFG_GLUE := ./glue ifdef CFG_VALGRIND CFG_VALGRIND += wine endif @@ -308,11 +311,13 @@ RUNTIME_LIBS := $(CFG_RUNTIME_LIBS) STDLIB_CRATE := lib/std.rc STDLIB_INPUTS := $(wildcard lib/*.rc lib/*.rs lib/*/*.rs) COMPILER_CRATE := comp/rustc.rc -COMPILER_INPUTS := $(wildcard comp/*.rc comp/*.rs comp/*/*.rs) +COMPILER_INPUTS := $(wildcard comp/rustc.rc comp/*.rs comp/*/*.rs) +GLUE_CRATE := comp/glue.rc +GLUE_INPUTS := $(wildcard comp/glue.rc comp/*.rs comp/*/*.rs) GENERATED := boot/fe/lexer.ml boot/util/version.ml -all: $(CFG_RUSTC) $(MKFILES) $(GENERATED) +all: $(CFG_RUSTC) $(CFG_GLUE) $(MKFILES) $(GENERATED) glue.o boot/util/version.ml: Makefile $(CFG_QUIET)git log -1 \ @@ -368,6 +373,16 @@ $(CFG_RUSTC): $(COMPILER_INPUTS) $(CFG_BOOT) $(CFG_RUNTIME) $(CFG_STDLIB) $(BOOT) -minimal -o $@ $< $(CFG_QUIET)chmod 0755 $@ +$(CFG_GLUE): $(GLUE_INPUTS) $(CFG_BOOT) $(CFG_RUNTIME) $(CFG_STDLIB) + @$(call CFG_ECHO, compile: $<) + $(BOOT) -minimal -o $@ $< + $(CFG_QUIET)chmod 0755 $@ + +glue.o: glue.s + +glue.s: $(CFG_GLUE) + $(CFG_GLUE) > $@ + self: $(CFG_RUSTC) @$(call CFG_ECHO, compile: $<) $(RUSTC) $(COMPILER_CRATE) @@ -763,9 +778,9 @@ test/bench/shootout/%.boot$(CFG_EXE_SUFFIX): \ @$(call CFG_ECHO, assemble [llvm]: $<) $(CFG_QUIET)gcc $(CFG_GCC_CFLAGS) -o $@ -c $< -%.rustc$(CFG_EXE_SUFFIX): %.o $(CFG_RUNTIME) +%.rustc$(CFG_EXE_SUFFIX): %.o $(CFG_RUNTIME) glue.o @$(call CFG_ECHO, link [llvm]: $<) - $(CFG_QUIET)gcc $(CFG_GCC_CFLAGS) -o $@ $< -L. -lrustrt + $(CFG_QUIET)gcc $(CFG_GCC_CFLAGS) glue.o -o $@ $< -L. -lrustrt @# dsymutil sometimes fails or prints a warning, but the @# program still runs. Since it simplifies debugging other @# programs, I\'ll live with the noise. diff --git a/src/comp/glue.rc b/src/comp/glue.rc new file mode 100644 index 00000000..1048341a --- /dev/null +++ b/src/comp/glue.rc @@ -0,0 +1,37 @@ +// -*- rust -*- + +use std; + +mod front { + mod ast; +} + +mod middle { + mod ty; +} + +mod driver { + mod session; +} + +mod glue { + mod glue; +} + +mod back { + mod abi; + mod x86; +} + +mod util { + mod common; +} + + +// Local Variables: +// fill-column: 78; +// indent-tabs-mode: nil +// c-basic-offset: 4 +// buffer-file-coding-system: utf-8-unix +// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'"; +// End: diff --git a/src/comp/glue/glue.rs b/src/comp/glue/glue.rs new file mode 100644 index 00000000..96bdba76 --- /dev/null +++ b/src/comp/glue/glue.rs @@ -0,0 +1,11 @@ +import back.x86; +import std._str; +import std._vec; +import std.os.libc; + +fn main(vec[str] args) { + auto module_asm = x86.get_module_asm() + "\n"; + auto bytes = _str.bytes(module_asm); + auto b = _vec.buf[u8](bytes); + libc.write(1, b, _vec.len[u8](bytes)); +} diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 7457a532..e4512a47 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -5708,8 +5708,6 @@ fn trans_crate(session.session sess, @ast.crate crate, str output, let ValueRef crate_ptr = 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, tn); -- cgit v1.2.3 From 27547c6514cf4f358ef2c8d935bd296eb0312ac1 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Tue, 8 Mar 2011 13:20:16 -0800 Subject: Revert "Move the glue asm code to a .o file. This reduces how much asm we print" This reverts commit 55c80e763bfd850682b3217fcfc5cdb516eafae0. --- src/Makefile | 23 ++++------------------- src/comp/glue.rc | 37 ------------------------------------- src/comp/glue/glue.rs | 11 ----------- src/comp/middle/trans.rs | 2 ++ 4 files changed, 6 insertions(+), 67 deletions(-) delete mode 100644 src/comp/glue.rc delete mode 100644 src/comp/glue/glue.rs diff --git a/src/Makefile b/src/Makefile index cafd8d18..a239329f 100644 --- a/src/Makefile +++ b/src/Makefile @@ -90,7 +90,6 @@ ifdef CFG_WINDOWSY CFG_EXE_SUFFIX := .exe CFG_BOOT := ./rustboot.exe CFG_RUSTC := ./rustc.exe - CFG_GLUE := ./glue.exe CFG_GCC_CFLAGS += -march=i686 CFG_GCC_LINK_FLAGS += -shared -fPIC CFG_RUN_TARG = $(1) @@ -102,7 +101,6 @@ ifdef CFG_UNIXY CFG_INFO := $(info cfg: unix-y environment) CFG_BOOT := ./rustboot CFG_RUSTC := ./rustc - CFG_GLUE := ./glue CFG_OBJ_SUFFIX := .o CFG_RUN_TARG = LD_LIBRARY_PATH=. $(CFG_VALGRIND) $(1) CFG_GCC := 1 @@ -113,7 +111,6 @@ ifdef CFG_UNIXY CFG_RUNTIME := rustrt.dll CFG_STDLIB := std.dll CFG_RUSTC := ./rustc.exe - CFG_GLUE := ./glue ifdef CFG_VALGRIND CFG_VALGRIND += wine endif @@ -311,13 +308,11 @@ RUNTIME_LIBS := $(CFG_RUNTIME_LIBS) STDLIB_CRATE := lib/std.rc STDLIB_INPUTS := $(wildcard lib/*.rc lib/*.rs lib/*/*.rs) COMPILER_CRATE := comp/rustc.rc -COMPILER_INPUTS := $(wildcard comp/rustc.rc comp/*.rs comp/*/*.rs) -GLUE_CRATE := comp/glue.rc -GLUE_INPUTS := $(wildcard comp/glue.rc comp/*.rs comp/*/*.rs) +COMPILER_INPUTS := $(wildcard comp/*.rc comp/*.rs comp/*/*.rs) GENERATED := boot/fe/lexer.ml boot/util/version.ml -all: $(CFG_RUSTC) $(CFG_GLUE) $(MKFILES) $(GENERATED) glue.o +all: $(CFG_RUSTC) $(MKFILES) $(GENERATED) boot/util/version.ml: Makefile $(CFG_QUIET)git log -1 \ @@ -373,16 +368,6 @@ $(CFG_RUSTC): $(COMPILER_INPUTS) $(CFG_BOOT) $(CFG_RUNTIME) $(CFG_STDLIB) $(BOOT) -minimal -o $@ $< $(CFG_QUIET)chmod 0755 $@ -$(CFG_GLUE): $(GLUE_INPUTS) $(CFG_BOOT) $(CFG_RUNTIME) $(CFG_STDLIB) - @$(call CFG_ECHO, compile: $<) - $(BOOT) -minimal -o $@ $< - $(CFG_QUIET)chmod 0755 $@ - -glue.o: glue.s - -glue.s: $(CFG_GLUE) - $(CFG_GLUE) > $@ - self: $(CFG_RUSTC) @$(call CFG_ECHO, compile: $<) $(RUSTC) $(COMPILER_CRATE) @@ -778,9 +763,9 @@ test/bench/shootout/%.boot$(CFG_EXE_SUFFIX): \ @$(call CFG_ECHO, assemble [llvm]: $<) $(CFG_QUIET)gcc $(CFG_GCC_CFLAGS) -o $@ -c $< -%.rustc$(CFG_EXE_SUFFIX): %.o $(CFG_RUNTIME) glue.o +%.rustc$(CFG_EXE_SUFFIX): %.o $(CFG_RUNTIME) @$(call CFG_ECHO, link [llvm]: $<) - $(CFG_QUIET)gcc $(CFG_GCC_CFLAGS) glue.o -o $@ $< -L. -lrustrt + $(CFG_QUIET)gcc $(CFG_GCC_CFLAGS) -o $@ $< -L. -lrustrt @# dsymutil sometimes fails or prints a warning, but the @# program still runs. Since it simplifies debugging other @# programs, I\'ll live with the noise. diff --git a/src/comp/glue.rc b/src/comp/glue.rc deleted file mode 100644 index 1048341a..00000000 --- a/src/comp/glue.rc +++ /dev/null @@ -1,37 +0,0 @@ -// -*- rust -*- - -use std; - -mod front { - mod ast; -} - -mod middle { - mod ty; -} - -mod driver { - mod session; -} - -mod glue { - mod glue; -} - -mod back { - mod abi; - mod x86; -} - -mod util { - mod common; -} - - -// Local Variables: -// fill-column: 78; -// indent-tabs-mode: nil -// c-basic-offset: 4 -// buffer-file-coding-system: utf-8-unix -// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'"; -// End: diff --git a/src/comp/glue/glue.rs b/src/comp/glue/glue.rs deleted file mode 100644 index 96bdba76..00000000 --- a/src/comp/glue/glue.rs +++ /dev/null @@ -1,11 +0,0 @@ -import back.x86; -import std._str; -import std._vec; -import std.os.libc; - -fn main(vec[str] args) { - auto module_asm = x86.get_module_asm() + "\n"; - auto bytes = _str.bytes(module_asm); - auto b = _vec.buf[u8](bytes); - libc.write(1, b, _vec.len[u8](bytes)); -} diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index e4512a47..7457a532 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -5708,6 +5708,8 @@ fn trans_crate(session.session sess, @ast.crate crate, str output, let ValueRef crate_ptr = 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, tn); -- cgit v1.2.3 From 16344a0145555448fc202a2bb8eebd2477dc10b2 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Tue, 8 Mar 2011 14:50:03 -0800 Subject: rustc: Re-XFAIL rec-extend.rs. The typechecker never assigned the path expr a type. --- src/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Makefile b/src/Makefile index a239329f..2729fc78 100644 --- a/src/Makefile +++ b/src/Makefile @@ -480,6 +480,7 @@ TEST_XFAILS_RUSTC := $(addprefix test/run-pass/, \ obj-return-polytypes.rs \ pred.rs \ preempt.rs \ + rec-extend.rs \ rt-circular-buffer.rs \ size-and-align.rs \ spawn-fn.rs \ -- cgit v1.2.3 From da9ea9ab69ebcf32ff9cc1ad557a6c2a5134bd0d Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Tue, 8 Mar 2011 14:55:39 -0800 Subject: rustc: Move type parameter resolution from translation into the typechecker --- src/comp/middle/trans.rs | 15 +++++++++-- src/comp/middle/typeck.rs | 64 ++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 76 insertions(+), 3 deletions(-) diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 7457a532..4064cc0a 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -3083,8 +3083,19 @@ fn lval_generic_fn(@block_ctxt cx, 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); + + auto monoty; + auto tys; + alt (ann) { + case (ast.ann_none) { + cx.fcx.ccx.sess.bug("no type annotation for path!"); + fail; + } + case (ast.ann_type(?monoty_, ?tps)) { + monoty = monoty_; + tys = option.get[vec[@ty.t]](tps); + } + } if (_vec.len[@ty.t](tys) != 0u) { auto bcx = cx; diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index 15383020..81458d2d 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -128,6 +128,37 @@ fn substitute_ty_params(&@crate_ctxt ccx, ret ty.fold_ty(substituter, typ); } +// Returns the type parameters and polytype of an item, if it's an item that +// supports type parameters. +fn ty_params_for_item(@crate_ctxt ccx, &ast.def d) + -> option.t[ty.ty_params_and_ty] { + auto params_id; + auto types_id; + alt (d) { + case (ast.def_fn(?id)) { params_id = id; types_id = id; } + case (ast.def_obj(?id)) { params_id = id; types_id = id; } + case (ast.def_obj_field(_)) { ret none[ty.ty_params_and_ty]; } + case (ast.def_mod(_)) { ret none[ty.ty_params_and_ty]; } + case (ast.def_const(_)) { ret none[ty.ty_params_and_ty]; } + case (ast.def_arg(_)) { ret none[ty.ty_params_and_ty]; } + case (ast.def_local(_)) { ret none[ty.ty_params_and_ty]; } + case (ast.def_variant(?tid, ?vid)) { + params_id = tid; + types_id = vid; + } + case (ast.def_ty(_)) { ret none[ty.ty_params_and_ty]; } + case (ast.def_ty_arg(_)) { ret none[ty.ty_params_and_ty]; } + case (ast.def_binding(_)) { ret none[ty.ty_params_and_ty]; } + case (ast.def_use(_)) { ret none[ty.ty_params_and_ty]; } + case (ast.def_native_ty(_)) { ret none[ty.ty_params_and_ty]; } + case (ast.def_native_fn(?id)) { params_id = id; types_id = id; } + } + + auto tps = ccx.item_ty_params.get(params_id); + auto polyty = ccx.item_types.get(types_id); + ret some[ty.ty_params_and_ty](tup(tps, polyty)); +} + // Parses the programmer's textual representation of a type into our internal // notion of a type. `getter` is a function that returns the type // corresponding to a definition ID. @@ -1190,7 +1221,38 @@ fn demand_expr_full(&@fn_ctxt fcx, @ty.t expected, @ast.expr e, case (ast.expr_path(?pth, ?d, ?ann)) { auto t = demand_full(fcx, e.span, expected, ann_to_type(ann), adk); - e_1 = ast.expr_path(pth, d, ast.ann_type(t, none[vec[@ty.t]])); + + // Fill in the type parameter substitutions if they weren't + // provided by the programmer. + auto ty_params_opt; + alt (ann) { + case (ast.ann_none) { + log "demand_expr(): no type annotation for path expr; " + + "did you pass it to check_expr() first?"; + fail; + } + case (ast.ann_type(_, ?tps_opt)) { + alt (tps_opt) { + case (none[vec[@ty.t]]) { + auto defn = option.get[ast.def](d); + alt (ty_params_for_item(fcx.ccx, defn)) { + case (none[ty.ty_params_and_ty]) { + ty_params_opt = none[vec[@ty.t]]; + } + case (some[ty.ty_params_and_ty](?tpt)) { + auto tps = ty.resolve_ty_params(tpt, t); + ty_params_opt = some[vec[@ty.t]](tps); + } + } + } + case (some[vec[@ty.t]](?tps)) { + ty_params_opt = some[vec[@ty.t]](tps); + } + } + } + } + + e_1 = ast.expr_path(pth, d, ast.ann_type(t, ty_params_opt)); } case (ast.expr_ext(?p, ?args, ?body, ?expanded, ?ann)) { auto t = demand_full(fcx, e.span, expected, -- cgit v1.2.3 From 01bfc3ae8bff5131cfd1db748ca996bdb86e100e Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Tue, 8 Mar 2011 16:31:37 -0800 Subject: Fix generic-bind support for bound aliases and generics. --- src/Makefile | 1 + src/comp/middle/trans.rs | 32 ++++++++++++++++++++++++-------- src/test/run-pass/generic-bind-2.rs | 10 ++++++++++ src/test/run-pass/generic-bind.rs | 3 --- 4 files changed, 35 insertions(+), 11 deletions(-) create mode 100644 src/test/run-pass/generic-bind-2.rs diff --git a/src/Makefile b/src/Makefile index 2729fc78..1572764d 100644 --- a/src/Makefile +++ b/src/Makefile @@ -409,6 +409,7 @@ TEST_XFAILS_BOOT := $(TASK_XFAILS) \ test/run-pass/obj-as.rs \ test/run-pass/vec-slice.rs \ test/run-pass/fn-lval.rs \ + test/run-pass/generic-bind-2.rs \ test/run-pass/generic-fn-box.rs \ test/run-pass/generic-tup.rs \ test/run-pass/iter-ret.rs \ diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 4064cc0a..5b2e12a6 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -3364,7 +3364,7 @@ fn trans_bind_thunk(@crate_ctxt cx, lltargetclosure = bcx.build.Load(lltargetclosure); auto outgoing_ret_ty = ty.ty_fn_ret(outgoing_fty); - auto outgoing_arg_tys = ty.ty_fn_args(outgoing_fty); + auto outgoing_args = ty.ty_fn_args(outgoing_fty); auto llretptr = fcx.llretptr; if (ty.type_has_dynamic_size(outgoing_ret_ty)) { @@ -3392,7 +3392,14 @@ fn trans_bind_thunk(@crate_ctxt cx, let uint a = 2u + i; // retptr, task ptr, env come first let int b = 0; let uint outgoing_arg_index = 0u; + let vec[TypeRef] llout_arg_tys = + type_of_explicit_args(cx, outgoing_args); + for (option.t[@ast.expr] arg in args) { + + auto out_arg = outgoing_args.(outgoing_arg_index); + auto llout_arg_ty = llout_arg_tys.(outgoing_arg_index); + alt (arg) { // Arg provided at binding time; thunk copies it from closure. @@ -3403,22 +3410,31 @@ fn trans_bind_thunk(@crate_ctxt cx, abi.box_rc_field_body, abi.closure_elt_bindings, b)); - // FIXME: possibly support passing aliases someday. + bcx = bound_arg.bcx; - llargs += bcx.build.Load(bound_arg.val); + auto val = bound_arg.val; + + if (out_arg.mode == ast.val) { + val = bcx.build.Load(val); + } else if (ty.count_ty_params(out_arg.ty) > 0u) { + check (out_arg.mode == ast.alias); + val = bcx.build.PointerCast(val, llout_arg_ty); + } + + llargs += val; b += 1; } // 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. + + if (ty.count_ty_params(out_arg.ty) > 0u) { + check (out_arg.mode == ast.alias); passed_arg = bcx.build.PointerCast(passed_arg, - T_typaram_ptr(cx.tn)); + llout_arg_ty); } + llargs += passed_arg; a += 1u; } diff --git a/src/test/run-pass/generic-bind-2.rs b/src/test/run-pass/generic-bind-2.rs new file mode 100644 index 00000000..95a8cab4 --- /dev/null +++ b/src/test/run-pass/generic-bind-2.rs @@ -0,0 +1,10 @@ +fn id[T](&T t) -> T { + ret t; +} + +fn main() { + auto t = tup(1,2,3,4,5,6,7); + check (t._5 == 6); + auto f0 = bind id[tup(int,int,int,int,int,int,int)](t); + check (f0()._5 == 6); +} diff --git a/src/test/run-pass/generic-bind.rs b/src/test/run-pass/generic-bind.rs index 5f44bcee..ef1275e3 100644 --- a/src/test/run-pass/generic-bind.rs +++ b/src/test/run-pass/generic-bind.rs @@ -5,9 +5,6 @@ fn id[T](&T t) -> T { fn main() { auto t = tup(1,2,3,4,5,6,7); check (t._5 == 6); - // FIXME: this needs to work. - // auto f0 = bind id[tup(int,int,int,int,int,int,int)](t); auto f1 = bind id[tup(int,int,int,int,int,int,int)](_); - // check (f0()._5 == 6); check (f1(t)._5 == 6); } -- cgit v1.2.3 From 67a9532dee0eb8eefc77d0c4885bcfe170e2a6ef Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Tue, 8 Mar 2011 16:32:33 -0800 Subject: Remove GC overspend; running out of memory on some tinderboxes. --- src/boot/driver/main.ml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/boot/driver/main.ml b/src/boot/driver/main.ml index 9705f1ee..ddcbc9af 100644 --- a/src/boot/driver/main.ml +++ b/src/boot/driver/main.ml @@ -1,11 +1,6 @@ open Common;; -let _ = - Gc.set { (Gc.get()) with - Gc.space_overhead = 400; } -;; - let (targ:Common.target) = match Sys.os_type with -- cgit v1.2.3 From e62424944b197e24025b149e2d4ba2347b76c8d8 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Tue, 8 Mar 2011 16:51:23 -0800 Subject: rustc: Have trans get the type parameters from the annotation instead of trying to deduce them itself. Un-XFAIL generic-fn-twice.rs. --- src/Makefile | 1 - src/comp/middle/trans.rs | 105 ++++++++++++++++++++++++++++++++++++----------- 2 files changed, 81 insertions(+), 25 deletions(-) diff --git a/src/Makefile b/src/Makefile index 1572764d..d66dba1f 100644 --- a/src/Makefile +++ b/src/Makefile @@ -452,7 +452,6 @@ TEST_XFAILS_RUSTC := $(addprefix test/run-pass/, \ foreach-nested.rs \ foreach-put-structured.rs \ foreach-simple-outer-slot.rs \ - generic-fn-twice.rs \ generic-iter-frame.rs \ generic-tag-alt.rs \ generic-tag-values.rs \ diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 5b2e12a6..44dc57fd 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -503,7 +503,8 @@ fn type_of_fn_full(@crate_ctxt cx, ast.proto proto, option.t[TypeRef] obj_self, vec[ty.arg] inputs, - @ty.t output) -> TypeRef { + @ty.t output, + uint ty_param_count) -> TypeRef { let vec[TypeRef] atys = vec(); // Arg 0: Output pointer. @@ -529,10 +530,6 @@ 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(proto, - inputs, - output))); auto i = 0u; while (i < ty_param_count) { atys += T_ptr(T_tydesc(cx.tn)); @@ -547,7 +544,7 @@ fn type_of_fn_full(@crate_ctxt cx, atys += T_fn_pair(cx.tn, type_of_fn_full(cx, ast.proto_fn, none[TypeRef], vec(rec(mode=ast.val, ty=output)), - plain_ty(ty.ty_nil))); + plain_ty(ty.ty_nil), 0u)); } // ... then explicit args. @@ -558,8 +555,11 @@ fn type_of_fn_full(@crate_ctxt cx, fn type_of_fn(@crate_ctxt cx, ast.proto proto, - vec[ty.arg] inputs, @ty.t output) -> TypeRef { - ret type_of_fn_full(cx, proto, none[TypeRef], inputs, output); + vec[ty.arg] inputs, + @ty.t output, + uint ty_param_count) -> TypeRef { + ret type_of_fn_full(cx, proto, none[TypeRef], inputs, output, + ty_param_count); } fn type_of_native_fn(@crate_ctxt cx, ast.native_abi abi, @@ -634,7 +634,7 @@ fn type_of_inner(@crate_ctxt cx, @ty.t t, bool boxed) -> TypeRef { llty = T_struct(tys); } case (ty.ty_fn(?proto, ?args, ?out)) { - llty = 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, 0u)); } case (ty.ty_native_fn(?abi, ?args, ?out)) { llty = T_fn_pair(cx.tn, type_of_native_fn(cx, abi, args, out)); @@ -648,7 +648,7 @@ fn type_of_inner(@crate_ctxt cx, @ty.t t, bool boxed) -> TypeRef { let TypeRef mty = type_of_fn_full(cx, m.proto, some[TypeRef](self_ty), - m.inputs, m.output); + m.inputs, m.output, 0u); mtys += T_ptr(mty); } let TypeRef vtbl = T_struct(mtys); @@ -2820,7 +2820,7 @@ fn trans_for_each(@block_ctxt cx, 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)); + plain_ty(ty.ty_nil), 0u); let ValueRef lliterbody = decl_fastcall_fn(cx.fcx.ccx.llmod, s, iter_body_llty); @@ -3447,6 +3447,16 @@ fn trans_bind_thunk(@crate_ctxt cx, auto lltargetfn = bcx.build.GEP(lltarget.val, vec(C_int(0), C_int(abi.fn_field_code))); + + // Cast the outgoing function to the appropriate type (see the comments in + // trans_bind below for why this is necessary). + auto lltargetty = type_of_fn(bcx.fcx.ccx, + ty.ty_fn_proto(outgoing_fty), + outgoing_args, + outgoing_ret_ty, + ty_param_count); + lltargetfn = bcx.build.PointerCast(lltargetfn, T_ptr(T_ptr(lltargetty))); + lltargetfn = bcx.build.Load(lltargetfn); auto r = bcx.build.FastCall(lltargetfn, llargs); @@ -3551,12 +3561,26 @@ fn trans_bind(@block_ctxt cx, @ast.expr f, bcx = bindings_tydesc.bcx; bcx.build.Store(bindings_tydesc.val, bound_tydesc); + // Determine the LLVM type for the outgoing function type. This + // may be different from the type returned by trans_malloc_boxed() + // since we have more information than that function does; + // specifically, we know how many type descriptors the outgoing + // function has, which type_of() doesn't, as only we know which + // item the function refers to. + auto llfnty = type_of_fn(bcx.fcx.ccx, + ty.ty_fn_proto(outgoing_fty), + ty.ty_fn_args(outgoing_fty), + ty.ty_fn_ret(outgoing_fty), + ty_param_count); + auto llclosurety = T_ptr(T_fn_pair(bcx.fcx.ccx.tn, llfnty)); + // Store thunk-target. auto bound_target = bcx.build.GEP(closure, vec(C_int(0), C_int(abi.closure_elt_target))); auto src = bcx.build.Load(f_res.res.val); + bound_target = bcx.build.PointerCast(bound_target, llclosurety); bcx.build.Store(src, bound_target); // Copy expr values into boxed bindings. @@ -4691,7 +4715,8 @@ fn trans_vtbl(@crate_ctxt cx, TypeRef self_ty, case (ty.ty_fn(?proto, ?inputs, ?output)) { llfnty = type_of_fn_full(cx, proto, some[TypeRef](self_ty), - inputs, output); + inputs, output, + _vec.len[ast.ty_param](ty_params)); } } @@ -4990,11 +5015,23 @@ fn get_pair_fn_ty(TypeRef llpairty) -> TypeRef { fn decl_fn_and_pair(@crate_ctxt cx, str kind, str name, + vec[ast.ty_param] ty_params, &ast.ann ann, ast.def_id id) { - auto llpairty = node_type(cx, ann); - auto llfty = get_pair_fn_ty(llpairty); + auto llfty; + auto llpairty; + alt (node_ann_type(cx, ann).struct) { + case (ty.ty_fn(?proto, ?inputs, ?output)) { + llfty = type_of_fn(cx, proto, inputs, output, + _vec.len[ast.ty_param](ty_params)); + llpairty = T_fn_pair(cx.tn, llfty); + } + case (_) { + cx.sess.bug("decl_fn_and_pair(): fn item doesn't have fn type?!"); + fail; + } + } // Declare the function itself. let str s = cx.names.next("_rust_" + kind) + sep() + name; @@ -5023,11 +5060,29 @@ fn register_fn_pair(@crate_ctxt cx, str ps, TypeRef llpairty, ValueRef llfn, cx.fn_pairs.insert(id, gvar); } -fn native_fn_wrapper_type(@crate_ctxt cx, &ast.ann ann) -> TypeRef { +// Returns the number of type parameters that the given native function has. +fn native_fn_ty_param_count(@crate_ctxt cx, &ast.def_id id) -> uint { + auto count; + auto native_item = cx.native_items.get(id); + alt (native_item.node) { + case (ast.native_item_ty(_,_)) { + cx.sess.bug("decl_native_fn_and_pair(): native fn isn't " + + "actually a fn?!"); + fail; + } + case (ast.native_item_fn(_, _, ?tps, _, _)) { + count = _vec.len[ast.ty_param](tps); + } + } + ret count; +} + +fn native_fn_wrapper_type(@crate_ctxt cx, uint ty_param_count, &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); + ret type_of_fn(cx, ast.proto_fn, args, out, ty_param_count); } } fail; @@ -5037,8 +5092,10 @@ fn decl_native_fn_and_pair(@crate_ctxt cx, str name, &ast.ann ann, ast.def_id id) { + auto num_ty_param = native_fn_ty_param_count(cx, id); + // Declare the wrapper. - auto wrapper_type = native_fn_wrapper_type(cx, ann); + auto wrapper_type = native_fn_wrapper_type(cx, num_ty_param, ann); let str s = cx.names.next("_rust_wrapper") + sep() + name; let ValueRef wrapper_fn = decl_fastcall_fn(cx.llmod, s, wrapper_type); @@ -5063,7 +5120,6 @@ fn decl_native_fn_and_pair(@crate_ctxt cx, 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); @@ -5081,6 +5137,7 @@ fn decl_native_fn_and_pair(@crate_ctxt cx, call_args += vec(llarg); arg_n += 1u; } + auto r = bcx.build.Call(function, call_args); bcx.build.Store(r, fcx.llretptr); bcx.build.RetVoid(); @@ -5102,16 +5159,16 @@ fn collect_native_item(&@crate_ctxt cx, @ast.native_item i) -> @crate_ctxt { fn collect_item(&@crate_ctxt cx, @ast.item i) -> @crate_ctxt { alt (i.node) { - case (ast.item_fn(?name, ?f, _, ?fid, ?ann)) { + case (ast.item_fn(?name, ?f, ?tps, ?fid, ?ann)) { cx.items.insert(fid, i); if (! cx.obj_methods.contains_key(fid)) { - decl_fn_and_pair(cx, "fn", name, ann, fid); + decl_fn_and_pair(cx, "fn", name, tps, ann, fid); } } - case (ast.item_obj(?name, ?ob, _, ?oid, ?ann)) { + case (ast.item_obj(?name, ?ob, ?tps, ?oid, ?ann)) { cx.items.insert(oid, i); - decl_fn_and_pair(cx, "obj_ctor", name, ann, oid); + decl_fn_and_pair(cx, "obj_ctor", name, tps, ann, oid); for (@ast.method m in ob.methods) { cx.obj_methods.insert(m.node.id, ()); } @@ -5151,11 +5208,11 @@ fn collect_tag_ctor(&@crate_ctxt cx, @ast.item i) -> @crate_ctxt { alt (i.node) { - case (ast.item_tag(_, ?variants, _, _)) { + case (ast.item_tag(_, ?variants, ?tps, _)) { for (ast.variant variant in variants) { if (_vec.len[ast.variant_arg](variant.args) != 0u) { decl_fn_and_pair(cx, "tag", variant.name, - variant.ann, variant.id); + tps, variant.ann, variant.id); } } } -- cgit v1.2.3 From e9fe47b359c4f8fe0791b83ebf3a60301f539b5c Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Tue, 8 Mar 2011 17:03:00 -0800 Subject: rustc: Make ann_to_type() fail if the node has no type. Miraculously, no test cases fail. --- src/comp/middle/ty.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs index 9ae39c9d..05558da1 100644 --- a/src/comp/middle/ty.rs +++ b/src/comp/middle/ty.rs @@ -596,8 +596,8 @@ fn eq_ty(&@t a, &@t b) -> bool { fn ann_to_type(&ast.ann ann) -> @t { alt (ann) { case (ast.ann_none) { - // shouldn't happen, but can until the typechecker is complete - ret plain_ty(ty_var(-1)); // FIXME: broken, broken, broken + log "ann_to_type() called on node with no type"; + fail; } case (ast.ann_type(?ty, _)) { ret ty; -- cgit v1.2.3 From 1a05f99a10dacfbdecc1bf2458f14b10390c1180 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Tue, 8 Mar 2011 17:19:06 -0800 Subject: Un-XFAIL obj-return-polytypes.rs --- src/Makefile | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Makefile b/src/Makefile index d66dba1f..3dcb4461 100644 --- a/src/Makefile +++ b/src/Makefile @@ -477,7 +477,6 @@ TEST_XFAILS_RUSTC := $(addprefix test/run-pass/, \ mutable-alias-vec.rs \ obj-as.rs \ obj-dtor.rs \ - obj-return-polytypes.rs \ pred.rs \ preempt.rs \ rec-extend.rs \ -- cgit v1.2.3 From 5b7c3b8b5df8292e27943908fd4c16323c7833a8 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Tue, 8 Mar 2011 17:34:15 -0800 Subject: rustc: Typecheck the base part of record extension expressions. Un-XFAIL rec-extend.rs. --- src/Makefile | 1 - src/comp/middle/typeck.rs | 8 +++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/Makefile b/src/Makefile index 3dcb4461..43cb1a7f 100644 --- a/src/Makefile +++ b/src/Makefile @@ -479,7 +479,6 @@ TEST_XFAILS_RUSTC := $(addprefix test/run-pass/, \ obj-dtor.rs \ pred.rs \ preempt.rs \ - rec-extend.rs \ rt-circular-buffer.rs \ size-and-align.rs \ spawn-fn.rs \ diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index 81458d2d..cbb6e4ac 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -2064,7 +2064,13 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr { case (ast.expr_rec(?fields, ?base, _)) { - auto base_1 = base; + auto base_1; + alt (base) { + case (none[@ast.expr]) { base_1 = none[@ast.expr]; } + case (some[@ast.expr](?b_0)) { + base_1 = some[@ast.expr](check_expr(fcx, b_0)); + } + } let vec[ast.field] fields_1 = vec(); let vec[field] fields_t = vec(); -- cgit v1.2.3 From e64085b0a2b512822ed7f020659fc6bdb8ed8ef5 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Tue, 8 Mar 2011 18:11:00 -0800 Subject: rustc: Fold over the paths in tag patterns so that we can resolve type variables in them --- src/comp/middle/fold.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/comp/middle/fold.rs b/src/comp/middle/fold.rs index 8a1dc70f..ccf3457b 100644 --- a/src/comp/middle/fold.rs +++ b/src/comp/middle/fold.rs @@ -452,11 +452,14 @@ fn fold_pat[ENV](&ENV env, ast_fold[ENV] fld, @ast.pat p) -> @ast.pat { ret fld.fold_pat_bind(env_, p.span, id, did, t); } case (ast.pat_tag(?path, ?pats, ?d, ?t)) { + auto ppath = fold_path(env, fld, path); + let vec[@ast.pat] ppats = vec(); for (@ast.pat pat in pats) { ppats += vec(fold_pat(env_, fld, pat)); } - ret fld.fold_pat_tag(env_, p.span, path, ppats, d, t); + + ret fld.fold_pat_tag(env_, p.span, ppath, ppats, d, t); } } } -- cgit v1.2.3 From 0a22a4edbb2300e338ef01c524265ecc647cbff4 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Tue, 8 Mar 2011 18:48:17 -0800 Subject: rustc: Factor out path type instantiation so that tag patterns can use it as well --- src/comp/middle/typeck.rs | 211 ++++++++++++++++++++++++---------------------- 1 file changed, 108 insertions(+), 103 deletions(-) diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index cbb6e4ac..e035e733 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -128,6 +128,112 @@ fn substitute_ty_params(&@crate_ctxt ccx, ret ty.fold_ty(substituter, typ); } +// Instantiates the given path, which must refer to an item with the given +// definition. +fn instantiate_path(@fn_ctxt fcx, &ast.path pth, &ast.def defn, &span sp) + -> ast.ann { + auto t; + auto ty_params; + alt (defn) { + case (ast.def_arg(?id)) { + check (fcx.locals.contains_key(id)); + t = fcx.locals.get(id); + ty_params = none[vec[ast.def_id]]; + } + case (ast.def_local(?id)) { + alt (fcx.locals.find(id)) { + case (some[@ty.t](?t1)) { t = t1; } + case (none[@ty.t]) { t = plain_ty(ty.ty_local(id)); } + } + ty_params = none[vec[ast.def_id]]; + } + case (ast.def_obj_field(?id)) { + check (fcx.locals.contains_key(id)); + t = fcx.locals.get(id); + ty_params = none[vec[ast.def_id]]; + } + case (ast.def_fn(?id)) { + check (fcx.ccx.item_types.contains_key(id)); + t = fcx.ccx.item_types.get(id); + ty_params = some(fcx.ccx.item_ty_params.get(id)); + } + case (ast.def_native_fn(?id)) { + check (fcx.ccx.item_types.contains_key(id)); + t = fcx.ccx.item_types.get(id); + ty_params = some(fcx.ccx.item_ty_params.get(id)); + } + case (ast.def_const(?id)) { + check (fcx.ccx.item_types.contains_key(id)); + t = fcx.ccx.item_types.get(id); + ty_params = none[vec[ast.def_id]]; + } + case (ast.def_variant(?tag_id, ?variant_id)) { + check (fcx.ccx.item_types.contains_key(variant_id)); + t = fcx.ccx.item_types.get(variant_id); + ty_params = some(fcx.ccx.item_ty_params.get(tag_id)); + } + case (ast.def_binding(?id)) { + check (fcx.locals.contains_key(id)); + t = fcx.locals.get(id); + ty_params = none[vec[ast.def_id]]; + } + case (ast.def_obj(?id)) { + check (fcx.ccx.item_types.contains_key(id)); + t = fcx.ccx.item_types.get(id); + ty_params = some(fcx.ccx.item_ty_params.get(id)); + } + + case (ast.def_mod(_)) { + // Hopefully part of a path. + t = plain_ty(ty.ty_nil); // TODO: something more poisonous? + ty_params = none[vec[ast.def_id]]; + } + + case (_) { + // FIXME: handle other names. + fcx.ccx.sess.unimpl("definition variant for: " + + _str.connect(pth.node.idents, ".")); + fail; + } + } + + auto ty_substs_opt; + auto ty_substs_len = _vec.len[@ast.ty](pth.node.types); + if (ty_substs_len > 0u) { + let vec[@ty.t] ty_substs = vec(); + auto i = 0u; + while (i < ty_substs_len) { + ty_substs += vec(ast_ty_to_ty_crate(fcx.ccx, pth.node.types.(i))); + i += 1u; + } + ty_substs_opt = some[vec[@ty.t]](ty_substs); + + alt (ty_params) { + case (none[vec[ast.def_id]]) { + fcx.ccx.sess.span_err(sp, "this kind of item may not take " + + "type parameters"); + fail; + } + case (some[vec[ast.def_id]](?tps)) { + t = substitute_ty_params(fcx.ccx, t, tps, ty_substs, sp); + } + } + } else { + ty_substs_opt = none[vec[@ty.t]]; + + alt (ty_params) { + case (none[vec[ast.def_id]]) { /* nothing */ } + case (some[vec[ast.def_id]](_)) { + // We will acquire the type parameters through + // unification. + t = generalize_ty(fcx.ccx, t); + } + } + } + + ret ast.ann_type(t, ty_substs_opt); +} + // Returns the type parameters and polytype of an item, if it's an item that // supports type parameters. fn ty_params_for_item(@crate_ctxt ccx, &ast.def d) @@ -1561,109 +1667,8 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr { case (ast.expr_path(?pth, ?defopt, _)) { auto t = plain_ty(ty.ty_nil); check (defopt != none[ast.def]); - - auto ty_params; - alt (option.get[ast.def](defopt)) { - case (ast.def_arg(?id)) { - check (fcx.locals.contains_key(id)); - t = fcx.locals.get(id); - ty_params = none[vec[ast.def_id]]; - } - case (ast.def_local(?id)) { - alt (fcx.locals.find(id)) { - case (some[@ty.t](?t1)) { t = t1; } - case (none[@ty.t]) { t = plain_ty(ty.ty_local(id)); } - } - ty_params = none[vec[ast.def_id]]; - } - case (ast.def_obj_field(?id)) { - check (fcx.locals.contains_key(id)); - t = fcx.locals.get(id); - ty_params = none[vec[ast.def_id]]; - } - case (ast.def_fn(?id)) { - check (fcx.ccx.item_types.contains_key(id)); - t = fcx.ccx.item_types.get(id); - ty_params = some(fcx.ccx.item_ty_params.get(id)); - } - case (ast.def_native_fn(?id)) { - check (fcx.ccx.item_types.contains_key(id)); - t = fcx.ccx.item_types.get(id); - ty_params = some(fcx.ccx.item_ty_params.get(id)); - } - case (ast.def_const(?id)) { - check (fcx.ccx.item_types.contains_key(id)); - t = fcx.ccx.item_types.get(id); - ty_params = none[vec[ast.def_id]]; - } - case (ast.def_variant(?tag_id, ?variant_id)) { - check (fcx.ccx.item_types.contains_key(variant_id)); - t = fcx.ccx.item_types.get(variant_id); - ty_params = some(fcx.ccx.item_ty_params.get(tag_id)); - } - case (ast.def_binding(?id)) { - check (fcx.locals.contains_key(id)); - t = fcx.locals.get(id); - ty_params = none[vec[ast.def_id]]; - } - case (ast.def_obj(?id)) { - check (fcx.ccx.item_types.contains_key(id)); - t = fcx.ccx.item_types.get(id); - ty_params = some(fcx.ccx.item_ty_params.get(id)); - } - - case (ast.def_mod(_)) { - // Hopefully part of a path. - ty_params = none[vec[ast.def_id]]; - } - - case (_) { - // FIXME: handle other names. - fcx.ccx.sess.unimpl("definition variant for: " - + _str.connect(pth.node.idents, ".")); - fail; - } - } - - // Substitute type parameters if the user provided some. - auto ty_substs_opt; - auto ty_substs_len = _vec.len[@ast.ty](pth.node.types); - if (ty_substs_len > 0u) { - let vec[@ty.t] ty_substs = vec(); - auto i = 0u; - while (i < ty_substs_len) { - ty_substs += vec(ast_ty_to_ty_crate(fcx.ccx, - pth.node.types.(i))); - i += 1u; - } - ty_substs_opt = some[vec[@ty.t]](ty_substs); - - alt (ty_params) { - case (none[vec[ast.def_id]]) { - fcx.ccx.sess.span_err(expr.span, "this kind of " + - "item may not take type " + - "parameters"); - fail; - } - case (some[vec[ast.def_id]](?tps)) { - t = substitute_ty_params(fcx.ccx, t, tps, ty_substs, - expr.span); - } - } - } else { - ty_substs_opt = none[vec[@ty.t]]; - - alt (ty_params) { - case (none[vec[ast.def_id]]) { /* nothing */ } - case (some[vec[ast.def_id]](_)) { - // We will acquire the type parameters through - // unification. - t = generalize_ty(fcx.ccx, t); - } - } - } - - auto ann = ast.ann_type(t, ty_substs_opt); + auto defn = option.get[ast.def](defopt); + auto ann = instantiate_path(fcx, pth, defn, expr.span); ret @fold.respan[ast.expr_](expr.span, ast.expr_path(pth, defopt, ann)); } -- cgit v1.2.3 From 3c200f3e14ff618431ea12c52031da43ee651984 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Wed, 9 Mar 2011 10:21:48 -0800 Subject: rustc: Grammar police work in check_pat() error messages --- src/comp/middle/typeck.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index e035e733..ae995491 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -1467,8 +1467,9 @@ fn check_pat(&@fn_ctxt fcx, @ast.pat pat) -> @ast.pat { // TODO: pluralize properly auto err_msg = "tag type " + last_id + " has " + _uint.to_str(subpats_len, 10u) + - " fields, but this pattern has " + - _uint.to_str(arg_len, 10u) + " fields"; + " field(s), but this pattern has " + + _uint.to_str(arg_len, 10u) + + " field(s)"; fcx.ccx.sess.span_err(pat.span, err_msg); fail; // TODO: recover @@ -1491,10 +1492,10 @@ fn check_pat(&@fn_ctxt fcx, @ast.pat pat) -> @ast.pat { if (subpats_len > 0u) { // TODO: pluralize properly auto err_msg = "tag type " + last_id + - " has no fields," + + " has no field(s)," + " but this pattern has " + _uint.to_str(subpats_len, 10u) + - " fields"; + " field(s)"; fcx.ccx.sess.span_err(pat.span, err_msg); fail; // TODO: recover -- cgit v1.2.3 From b828ec36fb6d1b6ef5b41d8366287e0b38b4da2e Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Wed, 9 Mar 2011 10:56:45 -0800 Subject: rustc: Factor the type parameter and type lookup out of instantiate_path(), as patterns need different logic --- src/comp/middle/typeck.rs | 60 +++++++++++++++++++++++++---------------------- 1 file changed, 32 insertions(+), 28 deletions(-) diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index ae995491..0fc99204 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -128,74 +128,77 @@ fn substitute_ty_params(&@crate_ctxt ccx, ret ty.fold_ty(substituter, typ); } -// Instantiates the given path, which must refer to an item with the given -// definition. -fn instantiate_path(@fn_ctxt fcx, &ast.path pth, &ast.def defn, &span sp) - -> ast.ann { - auto t; - auto ty_params; +type ty_params_opt_and_ty = tup(option.t[vec[ast.def_id]], @ty.t); + +// Returns the type parameters and the type for the given definition. +fn ty_params_and_ty_for_def(@fn_ctxt fcx, &ast.def defn) + -> ty_params_opt_and_ty { alt (defn) { case (ast.def_arg(?id)) { check (fcx.locals.contains_key(id)); - t = fcx.locals.get(id); - ty_params = none[vec[ast.def_id]]; + ret tup(none[vec[ast.def_id]], fcx.locals.get(id)); } case (ast.def_local(?id)) { + auto t; alt (fcx.locals.find(id)) { case (some[@ty.t](?t1)) { t = t1; } case (none[@ty.t]) { t = plain_ty(ty.ty_local(id)); } } - ty_params = none[vec[ast.def_id]]; + ret tup(none[vec[ast.def_id]], t); } case (ast.def_obj_field(?id)) { check (fcx.locals.contains_key(id)); - t = fcx.locals.get(id); - ty_params = none[vec[ast.def_id]]; + ret tup(none[vec[ast.def_id]], fcx.locals.get(id)); } case (ast.def_fn(?id)) { check (fcx.ccx.item_types.contains_key(id)); - t = fcx.ccx.item_types.get(id); - ty_params = some(fcx.ccx.item_ty_params.get(id)); + ret tup(some(fcx.ccx.item_ty_params.get(id)), + fcx.ccx.item_types.get(id)); } case (ast.def_native_fn(?id)) { check (fcx.ccx.item_types.contains_key(id)); - t = fcx.ccx.item_types.get(id); - ty_params = some(fcx.ccx.item_ty_params.get(id)); + ret tup(some(fcx.ccx.item_ty_params.get(id)), + fcx.ccx.item_types.get(id)); } case (ast.def_const(?id)) { check (fcx.ccx.item_types.contains_key(id)); - t = fcx.ccx.item_types.get(id); - ty_params = none[vec[ast.def_id]]; + ret tup(none[vec[ast.def_id]], fcx.ccx.item_types.get(id)); } case (ast.def_variant(?tag_id, ?variant_id)) { check (fcx.ccx.item_types.contains_key(variant_id)); - t = fcx.ccx.item_types.get(variant_id); - ty_params = some(fcx.ccx.item_ty_params.get(tag_id)); + ret tup(some(fcx.ccx.item_ty_params.get(tag_id)), + fcx.ccx.item_types.get(variant_id)); } case (ast.def_binding(?id)) { check (fcx.locals.contains_key(id)); - t = fcx.locals.get(id); - ty_params = none[vec[ast.def_id]]; + ret tup(none[vec[ast.def_id]], fcx.locals.get(id)); } case (ast.def_obj(?id)) { check (fcx.ccx.item_types.contains_key(id)); - t = fcx.ccx.item_types.get(id); - ty_params = some(fcx.ccx.item_ty_params.get(id)); + ret tup(some(fcx.ccx.item_ty_params.get(id)), + fcx.ccx.item_types.get(id)); } case (ast.def_mod(_)) { // Hopefully part of a path. - t = plain_ty(ty.ty_nil); // TODO: something more poisonous? - ty_params = none[vec[ast.def_id]]; + // TODO: return a type that's more poisonous, perhaps? + ret tup(none[vec[ast.def_id]], plain_ty(ty.ty_nil)); } case (_) { // FIXME: handle other names. - fcx.ccx.sess.unimpl("definition variant for: " - + _str.connect(pth.node.idents, ".")); + fcx.ccx.sess.unimpl("definition variant"); fail; } } +} + +// Instantiates the given path, which must refer to an item with the given +// type parameters and type. +fn instantiate_path(@fn_ctxt fcx, &ast.path pth, &ty_params_opt_and_ty tpt, + &span sp) -> ast.ann { + auto ty_params = tpt._0; + auto t = tpt._1; auto ty_substs_opt; auto ty_substs_len = _vec.len[@ast.ty](pth.node.types); @@ -1669,7 +1672,8 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr { auto t = plain_ty(ty.ty_nil); check (defopt != none[ast.def]); auto defn = option.get[ast.def](defopt); - auto ann = instantiate_path(fcx, pth, defn, expr.span); + auto tpt = ty_params_and_ty_for_def(fcx, defn); + auto ann = instantiate_path(fcx, pth, tpt, expr.span); ret @fold.respan[ast.expr_](expr.span, ast.expr_path(pth, defopt, ann)); } -- cgit v1.2.3 From 50da3ea5bcf31d3c4784f2e5158fd1e7d74aa2d6 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Wed, 9 Mar 2011 11:08:59 -0800 Subject: rustc: Instantiate tag patterns with the type parameters supplied by the programmer. size-and-align.rs typechecks now. --- src/comp/middle/typeck.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index 0fc99204..50ac6bb7 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -1461,6 +1461,12 @@ fn check_pat(&@fn_ctxt fcx, @ast.pat pat) -> @ast.pat { auto t = fcx.ccx.item_types.get(vdef._1); auto len = _vec.len[ast.ident](p.node.idents); auto last_id = p.node.idents.(len - 1u); + + auto ty_params = fcx.ccx.item_ty_params.get(vdef._0); + auto tag_ty = fcx.ccx.item_types.get(vdef._0); + auto tpt = tup(some(ty_params), tag_ty); + auto ann = instantiate_path(fcx, p, tpt, pat.span); + alt (t.struct) { // N-ary variants have function types. case (ty.ty_fn(_, ?args, ?tag_ty)) { @@ -1483,14 +1489,11 @@ fn check_pat(&@fn_ctxt fcx, @ast.pat pat) -> @ast.pat { new_subpats += vec(check_pat(fcx, subpat)); } - auto ann = ast.ann_type(tag_ty, none[vec[@ty.t]]); new_pat = ast.pat_tag(p, new_subpats, vdef_opt, ann); } // Nullary variants have tag types. case (ty.ty_tag(?tid, _)) { - // TODO: ty params - auto subpats_len = _vec.len[@ast.pat](subpats); if (subpats_len > 0u) { // TODO: pluralize properly @@ -1504,9 +1507,6 @@ fn check_pat(&@fn_ctxt fcx, @ast.pat pat) -> @ast.pat { fail; // TODO: recover } - let vec[@ty.t] tys = vec(); // FIXME - auto ann = ast.ann_type(plain_ty(ty.ty_tag(tid, tys)), - none[vec[@ty.t]]); new_pat = ast.pat_tag(p, subpats, vdef_opt, ann); } } -- cgit v1.2.3 From aeca13894438af8876f88e26a4947b4e7627111d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20=C3=81vila=20de=20Esp=C3=ADndola?= Date: Wed, 9 Mar 2011 14:16:11 -0500 Subject: swap taskptr and callee in preparation for making taskptr optional. --- src/comp/back/x86.rs | 18 ++++++++++-------- src/comp/middle/trans.rs | 6 +++--- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/comp/back/x86.rs b/src/comp/back/x86.rs index 10227df7..04f5d5af 100644 --- a/src/comp/back/x86.rs +++ b/src/comp/back/x86.rs @@ -175,8 +175,11 @@ fn upcall_glue(int n_args) -> vec[str] { */ fn copy_arg(uint i) -> str { - auto src_off = wstr(5 + (i as int)); - auto dst_off = wstr(1 + (i as int)); + if (i == 0u) { + ret "movl %edx, (%esp)"; + } + auto src_off = wstr(4 + (i as int)); + auto dst_off = wstr(0 + (i as int)); auto m = vec("movl " + src_off + "(%ebp),%eax", "movl %eax," + dst_off + "(%esp)"); ret _str.connect(m, "\n\t"); @@ -193,14 +196,13 @@ fn upcall_glue(int n_args) -> vec[str] { + load_esp_from_runtime_sp() + vec("subl $" + wstr(n_args + 1) + ", %esp # esp -= args", - "andl $~0xf, %esp # align esp down", - "movl %ecx, (%esp) # arg[0] = rust_task ") + "andl $~0xf, %esp # align esp down") - + _vec.init_fn[str](carg, n_args as uint) + + _vec.init_fn[str](carg, (n_args + 1) as uint) - + vec("movl %ecx, %edi # save task from ecx to edi", - "call *%edx # call *%edx", - "movl %edi, %ecx # restore edi-saved task to ecx") + + vec("movl %edx, %edi # save task from ecx to edi", + "call *%ecx # call *%edx", + "movl %edi, %edx # restore edi-saved task to ecx") + load_esp_from_rust_sp() + restore_callee_saves() diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 44dc57fd..5a50fbee 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -831,8 +831,8 @@ fn decl_upcall_glue(ModuleRef llmod, type_names tn, uint _n) -> ValueRef { let int n = _n as int; let str s = abi.upcall_glue_name(n); let vec[TypeRef] args = - vec(T_taskptr(tn), // taskptr - T_int()) // callee + vec(T_int(), // callee + T_taskptr(tn)) // taskptr + _vec.init_elt[TypeRef](T_int(), n as uint); ret decl_fastcall_fn(llmod, s, T_fn(args, T_int())); @@ -856,7 +856,7 @@ fn trans_upcall(@block_ctxt cx, str name, vec[ValueRef] args) -> result { llupcall = llvm.LLVMConstPointerCast(llupcall, T_int()); let ValueRef llglue = cx.fcx.ccx.glues.upcall_glues.(n); - let vec[ValueRef] call_args = vec(cx.fcx.lltaskptr, llupcall); + let vec[ValueRef] call_args = vec(llupcall, cx.fcx.lltaskptr); for (ValueRef a in args) { call_args += cx.build.ZExtOrBitCast(a, T_int()); -- cgit v1.2.3 From 10d8b4e861faedb734636a80dc4963392f1f82c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20=C3=81vila=20de=20Esp=C3=ADndola?= Date: Wed, 9 Mar 2011 15:05:22 -0500 Subject: Fix access to the rust stack. --- src/comp/back/x86.rs | 47 ++++++++++++++++++++++++++++++++--------------- 1 file changed, 32 insertions(+), 15 deletions(-) diff --git a/src/comp/back/x86.rs b/src/comp/back/x86.rs index 04f5d5af..b9ba24c6 100644 --- a/src/comp/back/x86.rs +++ b/src/comp/back/x86.rs @@ -25,22 +25,39 @@ fn restore_callee_saves() -> vec[str] { "popl %ebp"); } -fn load_esp_from_rust_sp() -> vec[str] { +fn load_esp_from_rust_sp_first_arg() -> vec[str] { ret vec("movl " + wstr(abi.task_field_rust_sp) + "(%ecx), %esp"); } -fn load_esp_from_runtime_sp() -> vec[str] { +fn load_esp_from_runtime_sp_first_arg() -> vec[str] { ret vec("movl " + wstr(abi.task_field_runtime_sp) + "(%ecx), %esp"); } -fn store_esp_to_rust_sp() -> vec[str] { +fn store_esp_to_rust_sp_first_arg() -> vec[str] { ret vec("movl %esp, " + wstr(abi.task_field_rust_sp) + "(%ecx)"); } -fn store_esp_to_runtime_sp() -> vec[str] { +fn store_esp_to_runtime_sp_first_arg() -> vec[str] { ret vec("movl %esp, " + wstr(abi.task_field_runtime_sp) + "(%ecx)"); } +fn load_esp_from_rust_sp_second_arg() -> vec[str] { + ret vec("movl " + wstr(abi.task_field_rust_sp) + "(%edx), %esp"); +} + +fn load_esp_from_runtime_sp_second_arg() -> vec[str] { + ret vec("movl " + wstr(abi.task_field_runtime_sp) + "(%edx), %esp"); +} + +fn store_esp_to_rust_sp_second_arg() -> vec[str] { + ret vec("movl %esp, " + wstr(abi.task_field_rust_sp) + "(%edx)"); +} + +fn store_esp_to_runtime_sp_second_arg() -> vec[str] { + ret vec("movl %esp, " + wstr(abi.task_field_runtime_sp) + "(%edx)"); +} + + /* * This is a bit of glue-code. It should be emitted once per * compilation unit. @@ -61,8 +78,8 @@ fn store_esp_to_runtime_sp() -> vec[str] { fn rust_activate_glue() -> vec[str] { ret vec("movl 4(%esp), %ecx # ecx = rust_task") + save_callee_saves() - + store_esp_to_runtime_sp() - + load_esp_from_rust_sp() + + store_esp_to_runtime_sp_first_arg() + + load_esp_from_rust_sp_first_arg() /* * There are two paths we can arrive at this code from: @@ -154,10 +171,10 @@ fn rust_activate_glue() -> vec[str] { fn rust_yield_glue() -> vec[str] { ret vec("movl 0(%esp), %ecx # ecx = rust_task") - + load_esp_from_rust_sp() + + load_esp_from_rust_sp_first_arg() + save_callee_saves() - + store_esp_to_rust_sp() - + load_esp_from_runtime_sp() + + store_esp_to_rust_sp_first_arg() + + load_esp_from_runtime_sp_first_arg() + restore_callee_saves() + vec("ret"); } @@ -192,19 +209,19 @@ fn upcall_glue(int n_args) -> vec[str] { + vec("movl %esp, %ebp # ebp = rust_sp") - + store_esp_to_rust_sp() - + load_esp_from_runtime_sp() + + store_esp_to_rust_sp_second_arg() + + load_esp_from_runtime_sp_second_arg() + vec("subl $" + wstr(n_args + 1) + ", %esp # esp -= args", "andl $~0xf, %esp # align esp down") + _vec.init_fn[str](carg, (n_args + 1) as uint) - + vec("movl %edx, %edi # save task from ecx to edi", - "call *%ecx # call *%edx", - "movl %edi, %edx # restore edi-saved task to ecx") + + vec("movl %edx, %edi # save task from edx to edi", + "call *%ecx # call *%ecx", + "movl %edi, %edx # restore edi-saved task to edx") - + load_esp_from_rust_sp() + + load_esp_from_rust_sp_second_arg() + restore_callee_saves() + vec("ret"); -- cgit v1.2.3 From 02f669ca6759f94deb87fb8dc3303eb08544c5a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20=C3=81vila=20de=20Esp=C3=ADndola?= Date: Wed, 9 Mar 2011 15:35:54 -0500 Subject: Pass the task pointer as just another i32. --- src/comp/middle/trans.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 5a50fbee..0b513744 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -832,7 +832,7 @@ fn decl_upcall_glue(ModuleRef llmod, type_names tn, uint _n) -> ValueRef { let str s = abi.upcall_glue_name(n); let vec[TypeRef] args = vec(T_int(), // callee - T_taskptr(tn)) // taskptr + T_int()) // taskptr + _vec.init_elt[TypeRef](T_int(), n as uint); ret decl_fastcall_fn(llmod, s, T_fn(args, T_int())); @@ -856,7 +856,8 @@ fn trans_upcall(@block_ctxt cx, str name, vec[ValueRef] args) -> result { llupcall = llvm.LLVMConstPointerCast(llupcall, T_int()); let ValueRef llglue = cx.fcx.ccx.glues.upcall_glues.(n); - let vec[ValueRef] call_args = vec(llupcall, cx.fcx.lltaskptr); + let vec[ValueRef] call_args = vec(llupcall); + call_args += cx.build.PtrToInt(cx.fcx.lltaskptr, T_int()); for (ValueRef a in args) { call_args += cx.build.ZExtOrBitCast(a, T_int()); -- cgit v1.2.3 From fcd195bb4ca47d4b3c7dfd3e6c14dc5771e139cc Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Wed, 9 Mar 2011 11:33:44 -0800 Subject: rustc: Don't try to load dynamically-sized types when translating tag variants. Add a test case for this. --- src/comp/middle/trans.rs | 3 ++- src/test/run-pass/simple-generic-tag.rs | 7 +++++++ 2 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 src/test/run-pass/simple-generic-tag.rs diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 0b513744..2ad33968 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -4920,7 +4920,8 @@ fn trans_tag_variant(@crate_ctxt cx, ast.def_id tag_id, auto arg_ty = arg_tys.(i).ty; auto llargval; - if (ty.type_is_structural(arg_ty)) { + if (ty.type_is_structural(arg_ty) || + ty.type_has_dynamic_size(arg_ty)) { llargval = llargptr; } else { llargval = bcx.build.Load(llargptr); diff --git a/src/test/run-pass/simple-generic-tag.rs b/src/test/run-pass/simple-generic-tag.rs new file mode 100644 index 00000000..ba6a3242 --- /dev/null +++ b/src/test/run-pass/simple-generic-tag.rs @@ -0,0 +1,7 @@ +tag clam[T] { + a(T); +} + +fn main() { +} + -- cgit v1.2.3 From 80fa01fb5784b91c05443daff0df6c607c2ce276 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Wed, 9 Mar 2011 12:22:08 -0800 Subject: rustc: Perform type parameter substitutions in static_size_of_tag() --- src/comp/middle/trans.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 2ad33968..ae9e408b 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -923,6 +923,18 @@ fn align_of(@block_ctxt cx, @ty.t t) -> result { ret dynamic_align_of(cx, t); } +// Returns the type parameters associated with the tag with the given ID. +fn ty_params_of_tag(@crate_ctxt cx, &ast.def_id tid) -> vec[ast.ty_param] { + alt (cx.items.get(tid).node) { + case (ast.item_tag(_, _, ?tps, _)) { ret tps; } + case (_) { + log "ty_params_of_tag(): tag ID doesn't actually refer to a " + + "tag item"; + fail; + } + } +} + // 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)) { @@ -947,6 +959,9 @@ fn static_size_of_tag(@crate_ctxt cx, @ty.t t) -> uint { } } + // Pull the type parameters out of the corresponding tag item. + let vec[ast.ty_param] ty_params = ty_params_of_tag(cx, tid); + // Compute max(variant sizes). auto max_size = 0u; auto variants = tag_variants(cx, tid); @@ -954,6 +969,9 @@ fn static_size_of_tag(@crate_ctxt cx, @ty.t t) -> uint { let vec[@ty.t] tys = variant_types(cx, variant); auto tup_ty = ty.plain_ty(ty.ty_tup(tys)); + // Perform any type parameter substitutions. + tup_ty = ty.substitute_ty_params(ty_params, subtys, tup_ty); + // Here we possibly do a recursive call. auto this_size = llsize_of_real(cx, type_of(cx, tup_ty)); -- cgit v1.2.3 From 9aa26904b83266576f9a05d5b1b9ca99b8ed0533 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Wed, 9 Mar 2011 13:07:06 -0800 Subject: rustc: Remove redundant ty_params_of_tag() function --- src/comp/middle/trans.rs | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index ae9e408b..06378927 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -923,18 +923,6 @@ fn align_of(@block_ctxt cx, @ty.t t) -> result { ret dynamic_align_of(cx, t); } -// Returns the type parameters associated with the tag with the given ID. -fn ty_params_of_tag(@crate_ctxt cx, &ast.def_id tid) -> vec[ast.ty_param] { - alt (cx.items.get(tid).node) { - case (ast.item_tag(_, _, ?tps, _)) { ret tps; } - case (_) { - log "ty_params_of_tag(): tag ID doesn't actually refer to a " + - "tag item"; - fail; - } - } -} - // 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)) { @@ -960,7 +948,7 @@ fn static_size_of_tag(@crate_ctxt cx, @ty.t t) -> uint { } // Pull the type parameters out of the corresponding tag item. - let vec[ast.ty_param] ty_params = ty_params_of_tag(cx, tid); + let vec[ast.ty_param] ty_params = tag_ty_params(cx, tid); // Compute max(variant sizes). auto max_size = 0u; -- cgit v1.2.3 From 2986ed43e9326d87e97072979a44ebe22e829d66 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Wed, 9 Mar 2011 13:31:25 -0800 Subject: rustc: Substitute type parameters in type_of_variant(). Add a test case. --- src/comp/middle/trans.rs | 15 ++++++++++----- src/test/run-pass/generic-tag-local.rs | 8 ++++++++ 2 files changed, 18 insertions(+), 5 deletions(-) create mode 100644 src/test/run-pass/generic-tag-local.rs diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 06378927..d9037c62 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -1699,11 +1699,15 @@ fn variant_types(@crate_ctxt cx, &ast.variant v) -> vec[@ty.t] { ret tys; } -fn type_of_variant(@crate_ctxt cx, &ast.variant v) -> TypeRef { +fn type_of_variant(@crate_ctxt cx, + &ast.variant v, + vec[ast.ty_param] ty_params, + vec[@ty.t] ty_param_substs) -> TypeRef { let vec[TypeRef] lltys = vec(); auto tys = variant_types(cx, v); for (@ty.t typ in tys) { - lltys += vec(type_of(cx, typ)); + auto typ2 = ty.substitute_ty_params(ty_params, ty_param_substs, typ); + lltys += vec(type_of(cx, typ2)); } ret T_struct(lltys); } @@ -1850,6 +1854,8 @@ fn iter_structural_ty_full(@block_ctxt cx, auto next_cx = new_sub_block_ctxt(bcx, "tag-iter-next"); + auto ty_params = tag_ty_params(bcx.fcx.ccx, tid); + auto i = 0u; for (ast.variant variant in variants) { auto variant_cx = new_sub_block_ctxt(bcx, @@ -1859,7 +1865,8 @@ fn iter_structural_ty_full(@block_ctxt cx, if (_vec.len[ast.variant_arg](variant.args) > 0u) { // N-ary variant. - auto llvarty = type_of_variant(bcx.fcx.ccx, variants.(i)); + auto llvarty = type_of_variant(bcx.fcx.ccx, variants.(i), + ty_params, tps); auto fn_ty = ty.ann_to_type(variants.(i).ann); alt (fn_ty.struct) { @@ -1870,8 +1877,6 @@ 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(bcx.fcx.ccx, tid); - auto j = 0u; for (ty.arg a in args) { auto v = vec(C_int(0), C_int(j as int)); diff --git a/src/test/run-pass/generic-tag-local.rs b/src/test/run-pass/generic-tag-local.rs new file mode 100644 index 00000000..63e2e195 --- /dev/null +++ b/src/test/run-pass/generic-tag-local.rs @@ -0,0 +1,8 @@ +tag clam[T] { + a(T); +} + +fn main() { + auto c = a(3); +} + -- cgit v1.2.3 From 603d820b85ef6fa62721c931ec9a6010fbda9115 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Wed, 9 Mar 2011 14:09:02 -0800 Subject: rustc: Have demand_pat() extract type parameters from tags. Add a test case. --- src/comp/middle/typeck.rs | 27 +++++++++++++++++++-------- src/test/run-pass/simple-generic-alt.rs | 11 +++++++++++ 2 files changed, 30 insertions(+), 8 deletions(-) create mode 100644 src/test/run-pass/simple-generic-alt.rs diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index 50ac6bb7..a0adf55a 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -1071,15 +1071,25 @@ fn demand_pat(&@fn_ctxt fcx, @ty.t expected, @ast.pat pat) -> @ast.pat { case (ast.pat_tag(?id, ?subpats, ?vdef_opt, ?ann)) { auto t = demand(fcx, pat.span, expected, ann_to_type(ann)); + // Figure out the type parameters of the tag. + auto tag_id = option.get[ast.variant_def](vdef_opt)._0; + auto ty_params = fcx.ccx.item_ty_params.get(tag_id); + + // Take the type parameters out of the expected type. + auto ty_param_substs; + alt (t.struct) { + case (ty.ty_tag(_, ?tps)) { ty_param_substs = tps; } + case (_) { + log "demand_pat(): expected type for tag pat isn't " + + "actually a tag?!"; + fail; + } + } + // The type of the tag isn't enough; we also have to get the type // of the variant, which is either a tag type in the case of // nullary variants or a function type in the case of n-ary // variants. - // - // TODO: When we have type-parametric tags, this will get a little - // trickier. Basically, we have to instantiate the variant type we - // acquire here with the type parameters provided to us by - // "expected". auto vdef = option.get[ast.variant_def](vdef_opt); auto variant_ty = fcx.ccx.item_types.get(vdef._1); @@ -1088,18 +1098,19 @@ fn demand_pat(&@fn_ctxt fcx, @ty.t expected, @ast.pat pat) -> @ast.pat { alt (variant_ty.struct) { case (ty.ty_tag(_, _)) { // Nullary tag variant. - // TODO: ty param substs check (subpats_len == 0u); p_1 = ast.pat_tag(id, subpats, vdef_opt, ast.ann_type(t, none[vec[@ty.t]])); } case (ty.ty_fn(_, ?args, ?tag_ty)) { // N-ary tag variant. - // TODO: ty param substs let vec[@ast.pat] new_subpats = vec(); auto i = 0u; for (arg a in args) { - auto new_subpat = demand_pat(fcx, a.ty, subpats.(i)); + auto subpat_ty = substitute_ty_params(fcx.ccx, a.ty, + ty_params, ty_param_substs, pat.span); + auto new_subpat = demand_pat(fcx, subpat_ty, + subpats.(i)); new_subpats += vec(new_subpat); i += 1u; } diff --git a/src/test/run-pass/simple-generic-alt.rs b/src/test/run-pass/simple-generic-alt.rs new file mode 100644 index 00000000..85db5c7c --- /dev/null +++ b/src/test/run-pass/simple-generic-alt.rs @@ -0,0 +1,11 @@ +tag clam[T] { + a(T); +} + +fn main() { + auto c = a(2); + alt (c) { + case (a[int](_)) {} + } +} + -- cgit v1.2.3 From ff15a93d952f0456c8e88d320bb1be27b7801443 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Wed, 9 Mar 2011 14:12:08 -0800 Subject: rustc: Make test/run-pass/generic-tag-alt.rs valid Rust; it was passing a dynamically-sized value by value instead of by alias --- src/test/run-pass/generic-tag-alt.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/run-pass/generic-tag-alt.rs b/src/test/run-pass/generic-tag-alt.rs index 4f04e729..9b19eec7 100644 --- a/src/test/run-pass/generic-tag-alt.rs +++ b/src/test/run-pass/generic-tag-alt.rs @@ -2,7 +2,7 @@ tag foo[T] { arm(T); } -fn altfoo[T](foo[T] f) { +fn altfoo[T](&foo[T] f) { auto hit = false; alt (f) { case (arm[T](?x)) { -- cgit v1.2.3 From ba2e04f271ca4015a3fb22dd01543ab9dc5d6543 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Wed, 9 Mar 2011 14:29:00 -0800 Subject: Rename confusing usage of "lltag" to "lldiscrim" in trans_pat_match() --- src/comp/middle/trans.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index d9037c62..f105247b 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -2943,8 +2943,8 @@ fn trans_pat_match(@block_ctxt cx, @ast.pat pat, ValueRef 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); + auto lldiscrimptr = cx.build.GEP(llval, vec(C_int(0), C_int(0))); + auto lldiscrim = cx.build.Load(lldiscrimptr); auto vdef = option.get[ast.variant_def](vdef_opt); auto variant_id = vdef._1; @@ -2963,7 +2963,7 @@ fn trans_pat_match(@block_ctxt cx, @ast.pat pat, ValueRef llval, auto matched_cx = new_sub_block_ctxt(cx, "matched_cx"); - auto lleq = cx.build.ICmp(lib.llvm.LLVMIntEQ, lltag, + auto lleq = cx.build.ICmp(lib.llvm.LLVMIntEQ, lldiscrim, C_int(variant_tag)); cx.build.CondBr(lleq, matched_cx.llbb, next_cx.llbb); -- cgit v1.2.3 From 7dc64b45b5149a566ad6d1284f8f90eb10468ca3 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Wed, 9 Mar 2011 15:17:06 -0800 Subject: rustc: Make tag pattern translation generic-aware. Un-XFAIL generic-tag-alt.rs. --- src/Makefile | 1 - src/comp/middle/trans.rs | 82 +++++++++++++++++++++++++++++------------------- 2 files changed, 50 insertions(+), 33 deletions(-) diff --git a/src/Makefile b/src/Makefile index 43cb1a7f..2c35d07f 100644 --- a/src/Makefile +++ b/src/Makefile @@ -453,7 +453,6 @@ TEST_XFAILS_RUSTC := $(addprefix test/run-pass/, \ foreach-put-structured.rs \ foreach-simple-outer-slot.rs \ generic-iter-frame.rs \ - generic-tag-alt.rs \ generic-tag-values.rs \ iter-range.rs \ iter-ret.rs \ diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index f105247b..7dea9e0c 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -1730,6 +1730,25 @@ fn tag_variants(@crate_ctxt cx, ast.def_id id) -> vec[ast.variant] { fail; // not reached } +// Returns the tag variant with the given ID. +fn tag_variant_with_id(@crate_ctxt cx, + &ast.def_id tag_id, + &ast.def_id variant_id) -> ast.variant { + auto variants = tag_variants(cx, tag_id); + + auto i = 0u; + while (i < _vec.len[ast.variant](variants)) { + auto variant = variants.(i); + if (common.def_eq(variant.id, variant_id)) { + ret variant; + } + i += 1u; + } + + log "tag_variant_with_id(): no variant exists with that ID"; + fail; +} + // 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 { @@ -2909,23 +2928,6 @@ fn trans_do_while(@block_ctxt cx, &ast.block body, // Pattern matching translation -// Returns a pointer to the union part of the LLVM representation of a tag -// type, cast to the appropriate type. -fn get_pat_union_ptr(@block_ctxt cx, vec[@ast.pat] subpats, ValueRef llval) - -> ValueRef { - auto llblobptr = cx.build.GEP(llval, vec(C_int(0), C_int(1))); - - // Generate the union type. - let vec[TypeRef] llsubpattys = vec(); - for (@ast.pat subpat in subpats) { - llsubpattys += vec(type_of(cx.fcx.ccx, pat_ty(subpat))); - } - - // Recursively check subpatterns. - auto llunionty = T_struct(llsubpattys); - ret cx.build.TruncOrBitCast(llblobptr, T_ptr(llunionty)); -} - fn trans_pat_match(@block_ctxt cx, @ast.pat pat, ValueRef llval, @block_ctxt next_cx) -> result { alt (pat.node) { @@ -2943,7 +2945,11 @@ fn trans_pat_match(@block_ctxt cx, @ast.pat pat, ValueRef llval, } case (ast.pat_tag(?id, ?subpats, ?vdef_opt, ?ann)) { - auto lldiscrimptr = cx.build.GEP(llval, vec(C_int(0), C_int(0))); + auto lltagptr = cx.build.PointerCast(llval, + T_opaque_tag_ptr(cx.fcx.ccx.tn)); + + auto lldiscrimptr = cx.build.GEP(lltagptr, + vec(C_int(0), C_int(0))); auto lldiscrim = cx.build.Load(lldiscrimptr); auto vdef = option.get[ast.variant_def](vdef_opt); @@ -2968,13 +2974,15 @@ fn trans_pat_match(@block_ctxt cx, @ast.pat pat, ValueRef llval, cx.build.CondBr(lleq, matched_cx.llbb, next_cx.llbb); if (_vec.len[@ast.pat](subpats) > 0u) { - auto llunionptr = get_pat_union_ptr(matched_cx, subpats, - llval); + auto llblobptr = matched_cx.build.GEP(lltagptr, + vec(C_int(0), C_int(1))); auto i = 0; for (@ast.pat subpat in subpats) { - auto llsubvalptr = matched_cx.build.GEP(llunionptr, - vec(C_int(0), - C_int(i))); + auto rslt = GEP_tag(matched_cx, llblobptr, variants.(i), + i); + auto llsubvalptr = rslt.val; + matched_cx = rslt.bcx; + auto llsubval = load_scalar_or_boxed(matched_cx, llsubvalptr, pat_ty(subpat)); @@ -2998,25 +3006,35 @@ fn trans_pat_binding(@block_ctxt cx, @ast.pat pat, ValueRef 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); - auto dst = cx.build.Alloca(llty); + auto rslt = alloc_ty(cx, ty); + auto dst = rslt.val; + auto bcx = rslt.bcx; + llvm.LLVMSetValueName(dst, _str.buf(id)); - cx.fcx.lllocals.insert(def_id, dst); - cx.cleanups += clean(bind drop_slot(_, dst, ty)); + bcx.fcx.lllocals.insert(def_id, dst); + bcx.cleanups += clean(bind drop_slot(_, dst, ty)); - ret copy_ty(cx, INIT, dst, llval, ty); + ret copy_ty(bcx, INIT, dst, llval, ty); } - case (ast.pat_tag(_, ?subpats, _, _)) { + case (ast.pat_tag(_, ?subpats, ?vdef_opt, _)) { if (_vec.len[@ast.pat](subpats) == 0u) { ret res(cx, llval); } - auto llunionptr = get_pat_union_ptr(cx, subpats, llval); + // Get the appropriate variant for this tag. + auto vdef = option.get[ast.variant_def](vdef_opt); + auto variant = tag_variant_with_id(cx.fcx.ccx, vdef._0, vdef._1); + + auto lltagptr = cx.build.PointerCast(llval, + T_opaque_tag_ptr(cx.fcx.ccx.tn)); + auto llblobptr = cx.build.GEP(lltagptr, vec(C_int(0), C_int(1))); auto this_cx = cx; auto i = 0; for (@ast.pat subpat in subpats) { - auto llsubvalptr = this_cx.build.GEP(llunionptr, - vec(C_int(0), C_int(i))); + auto rslt = GEP_tag(this_cx, llblobptr, variant, i); + this_cx = rslt.bcx; + auto llsubvalptr = rslt.val; + auto llsubval = load_scalar_or_boxed(this_cx, llsubvalptr, pat_ty(subpat)); auto subpat_res = trans_pat_binding(this_cx, subpat, -- cgit v1.2.3 From 1e65baad94ca8ae1f96472bf9efeb8e5ae04cf26 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Wed, 9 Mar 2011 15:23:41 -0800 Subject: rustc Remove dead "llunit_ty" assignment in trans_index --- src/comp/middle/trans.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 7dea9e0c..57dc9121 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -3287,7 +3287,6 @@ fn trans_index(@block_ctxt cx, &ast.span sp, @ast.expr base, 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; -- cgit v1.2.3 From ea2c86874448439a31012ccb141450c67e3d94d8 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Wed, 9 Mar 2011 16:07:55 -0800 Subject: rustc: Perform type substitutions for tag variants in dynamic_size_of() --- src/comp/middle/trans.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 57dc9121..3c5253ff 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -1020,9 +1020,17 @@ fn dynamic_size_of(@block_ctxt cx, @ty.t t) -> result { let ValueRef max_size = bcx.build.Alloca(T_int()); bcx.build.Store(C_int(0), max_size); + auto ty_params = tag_ty_params(bcx.fcx.ccx, tid); 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); + // Perform type substitution on the raw variant types. + let vec[@ty.t] raw_tys = variant_types(bcx.fcx.ccx, variant); + let vec[@ty.t] tys = vec(); + for (@ty.t raw_ty in raw_tys) { + auto t = ty.substitute_ty_params(ty_params, tps, raw_ty); + tys += vec(t); + } + auto rslt = align_elements(bcx, tys); bcx = rslt.bcx; -- cgit v1.2.3 From dddd7d8f447215a88aa87f438d4f495cf54be84d Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Wed, 9 Mar 2011 10:53:45 +0100 Subject: Add stdout_writer and string_writer to std.io For use by pretty-printer. string_writer API is a bit silly right now, feel free to suggest a cleaner way to do this. --- src/lib/io.rs | 71 ++++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 48 insertions(+), 23 deletions(-) diff --git a/src/lib/io.rs b/src/lib/io.rs index 0c4eb39e..71ebc1c7 100644 --- a/src/lib/io.rs +++ b/src/lib/io.rs @@ -91,6 +91,7 @@ tag fileflag { truncate; } +// FIXME move into fd_buf_writer fn writefd(int fd, vec[u8] v) { auto len = _vec.len[u8](v); auto count = 0u; @@ -107,19 +108,17 @@ fn writefd(int fd, vec[u8] v) { } } -fn new_buf_writer(str path, vec[fileflag] flags) -> buf_writer { - - state obj fd_buf_writer(int fd) { - - fn write(vec[u8] v) { - writefd(fd, v); - } +state obj fd_buf_writer(int fd, bool must_close) { + fn write(vec[u8] v) { + writefd(fd, v); + } - drop { - os.libc.close(fd); - } + drop { + if (must_close) {os.libc.close(fd);} } +} +fn file_buf_writer(str path, vec[fileflag] flags) -> buf_writer { let int fflags = os.libc_constants.O_WRONLY() | os.libc_constants.O_BINARY(); @@ -142,26 +141,52 @@ fn new_buf_writer(str path, vec[fileflag] flags) -> buf_writer { log sys.rustrt.last_os_error(); fail; } - ret fd_buf_writer(fd); + ret fd_buf_writer(fd, true); } type writer = state obj { - fn write_str(str s); - fn write_int(int n); - fn write_uint(uint n); + impure fn write_str(str s); + impure fn write_int(int n); + impure fn write_uint(uint n); }; -fn file_writer(str path, - vec[fileflag] flags) - -> writer -{ - state obj fw(buf_writer out) { - fn write_str(str s) { out.write(_str.bytes(s)); } - fn write_int(int n) { out.write(_str.bytes(_int.to_str(n, 10u))); } - fn write_uint(uint n) { out.write(_str.bytes(_uint.to_str(n, 10u))); } +state obj new_writer(buf_writer out) { + impure fn write_str(str s) { out.write(_str.bytes(s)); } + impure fn write_int(int n) { out.write(_str.bytes(_int.to_str(n, 10u))); } + impure fn write_uint(uint n) { out.write(_str.bytes(_uint.to_str(n, 10u))); } +} + +fn file_writer(str path, vec[fileflag] flags) -> writer { + ret new_writer(file_buf_writer(path, flags)); +} + +// FIXME it would be great if this could be a const named stdout +fn stdout_writer() -> writer { + ret new_writer(fd_buf_writer(1, false)); +} + +type str_writer = + state obj { + fn get_writer() -> writer; + fn get_str() -> str; + }; + +type str_buf = @rec(mutable str buf); + +// TODO awkward! it's not possible to implement a writer with an extra method +fn string_writer() -> str_writer { + auto buf = @rec(mutable buf = ""); + state obj str_writer_writer(str_buf buf) { + impure fn write_str(str s) { buf.buf += s; } + impure fn write_int(int n) { buf.buf += _int.to_str(n, 10u); } + impure fn write_uint(uint n) { buf.buf += _uint.to_str(n, 10u); } + } + state obj str_writer_wrap(writer wr, str_buf buf) { + fn get_writer() -> writer {ret wr;} + fn get_str() -> str {ret buf.buf;} } - ret fw(new_buf_writer(path, flags)); + ret str_writer_wrap(str_writer_writer(buf), buf); } // -- cgit v1.2.3 From aed40fbcd8e81cc1ef7a51b40b76b4631cba299e Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Wed, 9 Mar 2011 11:41:50 +0100 Subject: Have the pretty-printer take a writer stream as argument It now uses a string writer to also fill in for middle.ty.ast_ty_to_str --- src/comp/driver/rustc.rs | 2 +- src/comp/middle/ty.rs | 81 +---------------------------------------------- src/comp/pretty/pp.rs | 43 ++++++++++++++++--------- src/comp/pretty/pprust.rs | 10 ++++-- src/comp/rustc.rc | 1 + src/lib/io.rs | 43 +++++++++++++------------ 6 files changed, 61 insertions(+), 119 deletions(-) diff --git a/src/comp/driver/rustc.rs b/src/comp/driver/rustc.rs index 7ad0cdc7..6366bcaf 100644 --- a/src/comp/driver/rustc.rs +++ b/src/comp/driver/rustc.rs @@ -66,7 +66,7 @@ impure fn pretty_print_input(session.session sess, str input) { auto p = front.parser.new_parser(sess, env, 0, input); auto crate = front.parser.parse_crate_from_source_file(p); - pretty.pprust.print_ast(crate.node.module); + pretty.pprust.print_ast(crate.node.module, std.io.stdout_writer()); } fn warn_wrong_compiler() { diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs index 05558da1..958d0b78 100644 --- a/src/comp/middle/ty.rs +++ b/src/comp/middle/ty.rs @@ -81,87 +81,10 @@ tag unify_result { // Stringification -fn ast_ty_to_str(&@ast.ty ty) -> str { - - fn ast_fn_input_to_str(&rec(ast.mode mode, @ast.ty ty) input) -> str { - auto s; - if (mode_is_alias(input.mode)) { - s = "&"; - } else { - s = ""; - } - - ret s + ast_ty_to_str(input.ty); - } - - fn ast_ty_field_to_str(&ast.ty_field f) -> str { - ret ast_ty_to_str(f.ty) + " " + f.ident; - } - - auto s; - alt (ty.node) { - case (ast.ty_nil) { s = "()"; } - case (ast.ty_bool) { s = "bool"; } - case (ast.ty_int) { s = "int"; } - case (ast.ty_uint) { s = "uint"; } - case (ast.ty_machine(?tm)) { s = common.ty_mach_to_str(tm); } - case (ast.ty_char) { s = "char"; } - case (ast.ty_str) { s = "str"; } - case (ast.ty_box(?t)) { s = "@" + ast_ty_to_str(t); } - case (ast.ty_vec(?t)) { s = "vec[" + ast_ty_to_str(t) + "]"; } - case (ast.ty_type) { s = "type"; } - - case (ast.ty_tup(?elts)) { - auto f = ast_ty_to_str; - s = "tup("; - s += _str.connect(_vec.map[@ast.ty,str](f, elts), ","); - s += ")"; - } - - case (ast.ty_rec(?fields)) { - auto f = ast_ty_field_to_str; - s = "rec("; - s += _str.connect(_vec.map[ast.ty_field,str](f, fields), ","); - s += ")"; - } - - case (ast.ty_fn(?proto, ?inputs, ?output)) { - auto f = ast_fn_input_to_str; - if (proto == ast.proto_fn) { - s = "fn("; - } else { - s = "iter("; - } - auto is = _vec.map[rec(ast.mode mode, @ast.ty ty),str](f, inputs); - s += _str.connect(is, ", "); - s += ")"; - - if (output.node != ast.ty_nil) { - s += " -> " + ast_ty_to_str(output); - } - } - - case (ast.ty_path(?path, _)) { - s = path_to_str(path); - } - - case (ast.ty_mutable(?t)) { - s = "mutable " + ast_ty_to_str(t); - } - - - case (_) { - fail; // FIXME: typestate bug - } - } - - ret s; -} - fn path_to_str(&ast.path pth) -> str { auto result = _str.connect(pth.node.idents, "."); if (_vec.len[@ast.ty](pth.node.types) > 0u) { - auto f = ast_ty_to_str; + auto f = pretty.pprust.ty_to_str; result += "["; result += _str.connect(_vec.map[@ast.ty,str](f, pth.node.types), ","); result += "]"; @@ -169,8 +92,6 @@ fn path_to_str(&ast.path pth) -> str { ret result; } -// FIXME use the pretty-printer for this once it has a concept of an -// abstract stream fn ty_to_str(&@t typ) -> str { fn fn_input_to_str(&rec(ast.mode mode, @t ty) input) -> str { diff --git a/src/comp/pretty/pp.rs b/src/comp/pretty/pp.rs index 43a9220f..d3145180 100644 --- a/src/comp/pretty/pp.rs +++ b/src/comp/pretty/pp.rs @@ -17,17 +17,19 @@ type context = rec(contexttype tp, uint indent); type ps = @rec(mutable vec[context] context, uint width, + io.writer out, mutable vec[token] buffered, mutable uint scandepth, mutable uint bufferedcol, mutable uint col, mutable bool start_of_line); -fn mkstate(uint width) -> ps { +fn mkstate(io.writer out, uint width) -> ps { let vec[context] stack = vec(rec(tp=cx_v, indent=0u)); let vec[token] buff = vec(); ret @rec(mutable context=stack, width=width, + out=out, mutable buffered=buff, mutable scandepth=0u, mutable bufferedcol=0u, @@ -46,10 +48,22 @@ impure fn pop_context(ps p) { } impure fn add_token(ps p, token tok) { - if (p.scandepth == 0u) {do_token(p, tok);} + if (p.width == 0u) {direct_token(p, tok);} + else if (p.scandepth == 0u) {do_token(p, tok);} else {buffer_token(p, tok);} } +impure fn direct_token(ps p, token tok) { + alt (tok) { + case (brk(?sz)) { + while (sz > 0u) {p.out.write_str(" "); sz -= 1u;} + } + case (word(?w)) {p.out.write_str(w);} + case (cword(?w)) {p.out.write_str(w);} + case (_) {} + } +} + impure fn buffer_token(ps p, token tok) { p.buffered += vec(tok); p.bufferedcol += token_size(tok); @@ -101,14 +115,13 @@ impure fn finish_block_scan(ps p, contexttype tp) { impure fn finish_break_scan(ps p) { if (p.bufferedcol > p.width) { - write_str("\n"); - p.col = 0u; + line_break(p); } else { auto width; alt (p.buffered.(0)) {case(brk(?w)) {width = w;}} auto i = 0u; - while (i < width) {write_str(" "); i+=1u;} + while (i < width) {p.out.write_str(" "); i+=1u;} p.col += width; } p.scandepth = 0u; @@ -142,20 +155,18 @@ impure fn do_token(ps p, token tok) { start_scan(p, tok); } case (cx_v) { - write_str("\n"); - p.col = 0u; - p.start_of_line = true; + line_break(p); } } } case (word(?w)) { before_print(p, false); - write_str(w); + p.out.write_str(w); p.col += _str.byte_len(w); // TODO char_len } case (cword(?w)) { before_print(p, true); - write_str(w); + p.out.write_str(w); p.col += _str.byte_len(w); // TODO char_len } case (open(?tp, ?indent)) { @@ -170,6 +181,12 @@ impure fn do_token(ps p, token tok) { } } +impure fn line_break(ps p) { + p.out.write_str("\n"); + p.col = 0u; + p.start_of_line = true; +} + impure fn before_print(ps p, bool closing) { if (p.start_of_line) { p.start_of_line = false; @@ -177,14 +194,10 @@ impure fn before_print(ps p, bool closing) { if (closing) {ind = base_indent(p);} else {ind = cur_context(p).indent;} p.col = ind; - while (ind > 0u) {write_str(" "); ind -= 1u;} + while (ind > 0u) {p.out.write_str(" "); ind -= 1u;} } } -fn write_str(str s) { - io.writefd(1, _str.bytes(s)); -} - fn token_size(token tok) -> uint { alt (tok) { case (brk(?sz)) {ret sz;} diff --git a/src/comp/pretty/pprust.rs b/src/comp/pretty/pprust.rs index c54786fd..e766cacd 100644 --- a/src/comp/pretty/pprust.rs +++ b/src/comp/pretty/pprust.rs @@ -11,13 +11,19 @@ import foo = std.io; const uint indent_unit = 2u; const int as_prec = 5; -impure fn print_ast(ast._mod _mod) { - auto s = pp.mkstate(80u); +impure fn print_ast(ast._mod _mod, std.io.writer out) { + auto s = pp.mkstate(out, 80u); for (@ast.view_item vitem in _mod.view_items) {print_view_item(s, vitem);} line(s); for (@ast.item item in _mod.items) {print_item(s, item);} } +fn ty_to_str(&@ast.ty ty) -> str { + auto writer = std.io.string_writer(); + print_type(pp.mkstate(writer.get_writer(), 0u), ty); + ret writer.get_str(); +} + impure fn hbox(ps s) { pp.hbox(s, indent_unit); } diff --git a/src/comp/rustc.rc b/src/comp/rustc.rc index 7e1d8fd9..c7d3ff6b 100644 --- a/src/comp/rustc.rc +++ b/src/comp/rustc.rc @@ -44,6 +44,7 @@ auth middle.trans = unsafe; auth middle.trans.copy_args_to_allocas = impure; auth middle.trans.trans_block = impure; auth lib.llvm = unsafe; +auth pretty.pprust = impure; mod lib { alt (target_os) { diff --git a/src/lib/io.rs b/src/lib/io.rs index 71ebc1c7..dbe6de7a 100644 --- a/src/lib/io.rs +++ b/src/lib/io.rs @@ -91,26 +91,21 @@ tag fileflag { truncate; } -// FIXME move into fd_buf_writer -fn writefd(int fd, vec[u8] v) { - auto len = _vec.len[u8](v); - auto count = 0u; - auto vbuf; - while (count < len) { - vbuf = _vec.buf_off[u8](v, count); - auto nout = os.libc.write(fd, vbuf, len); - if (nout < 0) { - log "error dumping buffer"; - log sys.rustrt.last_os_error(); - fail; - } - count += nout as uint; - } -} - state obj fd_buf_writer(int fd, bool must_close) { fn write(vec[u8] v) { - writefd(fd, v); + auto len = _vec.len[u8](v); + auto count = 0u; + auto vbuf; + while (count < len) { + vbuf = _vec.buf_off[u8](v, count); + auto nout = os.libc.write(fd, vbuf, len); + if (nout < 0) { + log "error dumping buffer"; + log sys.rustrt.last_os_error(); + fail; + } + count += nout as uint; + } } drop { @@ -152,9 +147,15 @@ type writer = }; state obj new_writer(buf_writer out) { - impure fn write_str(str s) { out.write(_str.bytes(s)); } - impure fn write_int(int n) { out.write(_str.bytes(_int.to_str(n, 10u))); } - impure fn write_uint(uint n) { out.write(_str.bytes(_uint.to_str(n, 10u))); } + impure fn write_str(str s) { + out.write(_str.bytes(s)); + } + impure fn write_int(int n) { + out.write(_str.bytes(_int.to_str(n, 10u))); + } + impure fn write_uint(uint n) { + out.write(_str.bytes(_uint.to_str(n, 10u))); + } } fn file_writer(str path, vec[fileflag] flags) -> writer { -- cgit v1.2.3 From ec22fe9733b536e50dfd159bd8cbc2cb2ab40beb Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Wed, 9 Mar 2011 12:28:18 +0100 Subject: Add ty_obj case to pretty printer --- src/comp/pretty/pprust.rs | 53 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 37 insertions(+), 16 deletions(-) diff --git a/src/comp/pretty/pprust.rs b/src/comp/pretty/pprust.rs index e766cacd..9ef9bb16 100644 --- a/src/comp/pretty/pprust.rs +++ b/src/comp/pretty/pprust.rs @@ -91,24 +91,21 @@ impure fn print_type(ps s, @ast.ty ty) { commasep[ast.ty_field](s, fields, f); pclose(s); } - case (ast.ty_fn(?proto,?inputs,?output)) { - if (proto == ast.proto_fn) {wrd(s, "fn");} - else {wrd(s, "iter");} - popen(s); - impure fn print_arg(ps s, ast.ty_arg input) { - if (middle.ty.mode_is_alias(input.mode)) {wrd(s, "&");} - print_type(s, input.ty); - } - auto f = print_arg; - commasep[ast.ty_arg](s, inputs, f); - pclose(s); - if (output.node != ast.ty_nil) { - space(s); + case (ast.ty_obj(?methods)) { + wrd1(s, "obj"); + bopen(s); + for (ast.ty_method m in methods) { hbox(s); - wrd1(s, "->"); - print_type(s, output); + print_ty_fn(s, m.proto, option.some[str](m.ident), + m.inputs, m.output); + wrd(s, ";"); end(s); + line(s); } + bclose(s); + } + case (ast.ty_fn(?proto,?inputs,?output)) { + print_ty_fn(s, proto, option.none[str], inputs, output); } case (ast.ty_path(?path,_)) { print_path(s, path); @@ -528,7 +525,6 @@ impure fn print_expr(ps s, @ast.expr expr) { } // TODO: extension 'body' } - case (_) {wrd(s, "X");} } end(s); } @@ -730,3 +726,28 @@ fn escape_str(str st, char to_escape) -> str { impure fn print_string(ps s, str st) { wrd(s, "\""); wrd(s, escape_str(st, '"')); wrd(s, "\""); } + +impure fn print_ty_fn(ps s, ast.proto proto, option.t[str] id, + vec[ast.ty_arg] inputs, @ast.ty output) { + if (proto == ast.proto_fn) {wrd(s, "fn");} + else {wrd(s, "iter");} + alt (id) { + case (option.some[str](?id)) {space(s); wrd(s, id);} + case (_) {} + } + popen(s); + impure fn print_arg(ps s, ast.ty_arg input) { + if (middle.ty.mode_is_alias(input.mode)) {wrd(s, "&");} + print_type(s, input.ty); + } + auto f = print_arg; + commasep[ast.ty_arg](s, inputs, f); + pclose(s); + if (output.node != ast.ty_nil) { + space(s); + hbox(s); + wrd1(s, "->"); + print_type(s, output); + end(s); + } +} -- cgit v1.2.3 From 11a10c7a7b86c7bf91a8adcd41573f9de9eeaf0e Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Wed, 9 Mar 2011 17:29:18 -0800 Subject: Remove redundant imports in lib (rustc doesn't like 'std' as a synonym for root within std.rc anyway) --- src/lib/_int.rs | 1 - src/lib/_str.rs | 2 +- src/lib/_uint.rs | 1 - src/lib/_vec.rs | 1 - src/lib/bitv.rs | 4 ---- src/lib/dbg.rs | 2 -- src/lib/deque.rs | 4 ---- src/lib/io.rs | 5 +---- src/lib/list.rs | 2 -- src/lib/map.rs | 6 ------ src/lib/sha1.rs | 3 --- 11 files changed, 2 insertions(+), 29 deletions(-) diff --git a/src/lib/_int.rs b/src/lib/_int.rs index 38e161bc..ee660f01 100644 --- a/src/lib/_int.rs +++ b/src/lib/_int.rs @@ -1,4 +1,3 @@ -import std.sys; fn add(int x, int y) -> int { ret x + y; } fn sub(int x, int y) -> int { ret x - y; } diff --git a/src/lib/_str.rs b/src/lib/_str.rs index 0e0e7650..3f453349 100644 --- a/src/lib/_str.rs +++ b/src/lib/_str.rs @@ -1,6 +1,6 @@ import rustrt.sbuf; -import std._vec.rustrt.vbuf; +import _vec.rustrt.vbuf; native "rust" mod rustrt { type sbuf; diff --git a/src/lib/_uint.rs b/src/lib/_uint.rs index 79b5fa24..ceee9c77 100644 --- a/src/lib/_uint.rs +++ b/src/lib/_uint.rs @@ -1,4 +1,3 @@ -import std.sys; fn add(uint x, uint y) -> uint { ret x + y; } fn sub(uint x, uint y) -> uint { ret x - y; } diff --git a/src/lib/_vec.rs b/src/lib/_vec.rs index 2ffe8bad..680c8884 100644 --- a/src/lib/_vec.rs +++ b/src/lib/_vec.rs @@ -1,5 +1,4 @@ import vbuf = rustrt.vbuf; -import std.option; type operator2[T,U,V] = fn(&T, &U) -> V; diff --git a/src/lib/bitv.rs b/src/lib/bitv.rs index adb3dc86..2322c693 100644 --- a/src/lib/bitv.rs +++ b/src/lib/bitv.rs @@ -1,7 +1,3 @@ -import std._uint; -import std._int; -import std._vec; - // FIXME: With recursive object types, we could implement binary methods like // union, intersection, and difference. At that point, we could write // an optimizing version of this module that produces a different obj diff --git a/src/lib/dbg.rs b/src/lib/dbg.rs index 774052dc..b63f363e 100644 --- a/src/lib/dbg.rs +++ b/src/lib/dbg.rs @@ -5,8 +5,6 @@ * logging. */ -import std._vec; - // FIXME: handle 64-bit case. const uint const_refcount = 0x7bad_face_u; diff --git a/src/lib/deque.rs b/src/lib/deque.rs index 16023457..776f82e9 100644 --- a/src/lib/deque.rs +++ b/src/lib/deque.rs @@ -2,10 +2,6 @@ * A deque, for fun. Untested as of yet. Likely buggy. */ -import std.option; -import std._vec; -import std._int; - type t[T] = obj { fn size() -> uint; diff --git a/src/lib/io.rs b/src/lib/io.rs index dbe6de7a..34c4a98d 100644 --- a/src/lib/io.rs +++ b/src/lib/io.rs @@ -1,7 +1,4 @@ -import std.os.libc; -import std._str; -import std._vec; - +import os.libc; type stdio_reader = state obj { fn getc() -> int; diff --git a/src/lib/list.rs b/src/lib/list.rs index c4661940..58c2cded 100644 --- a/src/lib/list.rs +++ b/src/lib/list.rs @@ -1,5 +1,3 @@ - -import std.option; import option.some; import option.none; diff --git a/src/lib/map.rs b/src/lib/map.rs index 7f760b65..29e9ba5d 100644 --- a/src/lib/map.rs +++ b/src/lib/map.rs @@ -3,12 +3,6 @@ * use, but useful as a stress test for rustboot. */ -import std._int; -import std.sys; -import std.option; -import std._vec; - - type hashfn[K] = fn(&K) -> uint; type eqfn[K] = fn(&K, &K) -> bool; diff --git a/src/lib/sha1.rs b/src/lib/sha1.rs index 2a6b74d4..a57ea894 100644 --- a/src/lib/sha1.rs +++ b/src/lib/sha1.rs @@ -4,9 +4,6 @@ * point this will want to be rewritten. */ -import std._vec; -import std._str; - export sha1; export mk_sha1; -- cgit v1.2.3 From bafcbb101c104b136ce781380ce6944c49b77691 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Wed, 9 Mar 2011 17:34:22 -0800 Subject: Fold exports. --- src/comp/middle/fold.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/comp/middle/fold.rs b/src/comp/middle/fold.rs index ccf3457b..d08b979a 100644 --- a/src/comp/middle/fold.rs +++ b/src/comp/middle/fold.rs @@ -254,6 +254,8 @@ type ast_fold[ENV] = (fn(&ENV e, &span sp, ident i, vec[ident] idents, def_id id, option.t[def]) -> @view_item) fold_view_item_import, + (fn(&ENV e, &span sp, ident i) -> @view_item) fold_view_item_export, + // Additional nodes. (fn(&ENV e, &span sp, &ast.block_) -> block) fold_block, @@ -852,6 +854,10 @@ fn fold_view_item[ENV](&ENV env, ast_fold[ENV] fld, @view_item vi) ret fld.fold_view_item_import(env_, vi.span, def_ident, idents, def_id, target_def); } + + case (ast.view_item_export(?def_ident)) { + ret fld.fold_view_item_export(env_, vi.span, def_ident); + } } fail; @@ -1339,6 +1345,11 @@ fn identity_fold_view_item_import[ENV](&ENV e, &span sp, ident i, ret @respan(sp, ast.view_item_import(i, is, id, target_def)); } +fn identity_fold_view_item_export[ENV](&ENV e, &span sp, ident i) + -> @view_item { + ret @respan(sp, ast.view_item_export(i)); +} + // Additional identities. fn identity_fold_block[ENV](&ENV e, &span sp, &ast.block_ blk) -> block { @@ -1516,6 +1527,8 @@ fn new_identity_fold[ENV]() -> ast_fold[ENV] { bind identity_fold_view_item_use[ENV](_,_,_,_,_), fold_view_item_import = bind identity_fold_view_item_import[ENV](_,_,_,_,_,_), + fold_view_item_export = + bind identity_fold_view_item_export[ENV](_,_,_), fold_block = bind identity_fold_block[ENV](_,_,_), fold_fn = bind identity_fold_fn[ENV](_,_,_,_), -- cgit v1.2.3 From 874e8e35055aff1bb7cb5b8afd9e1c27c8cf20de Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Wed, 9 Mar 2011 17:48:07 -0800 Subject: rustc: Have tag patterns use the type parameter information from the typechecker instead of trying to deduce it in trans. Un-XFAIL test/run-pass/generic-tag-values.rs. --- src/Makefile | 1 - src/comp/middle/trans.rs | 54 ++++++++++++++++++++++++++++++++++++++++------- src/comp/middle/typeck.rs | 5 +++-- 3 files changed, 49 insertions(+), 11 deletions(-) diff --git a/src/Makefile b/src/Makefile index 2c35d07f..70e2330e 100644 --- a/src/Makefile +++ b/src/Makefile @@ -453,7 +453,6 @@ TEST_XFAILS_RUSTC := $(addprefix test/run-pass/, \ foreach-put-structured.rs \ foreach-simple-outer-slot.rs \ generic-iter-frame.rs \ - generic-tag-values.rs \ iter-range.rs \ iter-ret.rs \ lazychan.rs \ diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 3c5253ff..00e7e6d8 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -1185,8 +1185,16 @@ fn GEP_tup_like(@block_ctxt cx, @ty.t t, // 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) +fn GEP_tag(@block_ctxt cx, + ValueRef llblobptr, + &ast.def_id tag_id, + &ast.def_id variant_id, + vec[@ty.t] ty_substs, + int ix) -> result { + auto ty_params = tag_ty_params(cx.fcx.ccx, tag_id); + auto variant = tag_variant_with_id(cx.fcx.ccx, tag_id, variant_id); + // 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); @@ -1194,9 +1202,10 @@ fn GEP_tag(@block_ctxt cx, ValueRef llblobptr, &ast.variant variant, int ix) auto i = 0; let vec[@ty.t] true_arg_tys = vec(); for (ty.arg a in arg_tys) { - true_arg_tys += vec(a.ty); + auto arg_ty = ty.substitute_ty_params(ty_params, ty_substs, a.ty); + true_arg_tys += vec(arg_ty); if (i == ix) { - elem_ty = a.ty; + elem_ty = arg_ty; } i += 1; @@ -2283,6 +2292,24 @@ fn node_ann_type(@crate_ctxt cx, &ast.ann a) -> @ty.t { } } +fn node_ann_ty_params(&ast.ann a) -> vec[@ty.t] { + alt (a) { + case (ast.ann_none) { + log "missing type annotation"; + fail; + } + case (ast.ann_type(_, ?tps_opt)) { + alt (tps_opt) { + case (none[vec[@ty.t]]) { + log "type annotation has no ty params"; + fail; + } + case (some[vec[@ty.t]](?tps)) { ret tps; } + } + } + } +} + fn node_type(@crate_ctxt cx, &ast.ann a) -> TypeRef { ret type_of(cx, node_ann_type(cx, a)); } @@ -2981,13 +3008,15 @@ fn trans_pat_match(@block_ctxt cx, @ast.pat pat, ValueRef llval, C_int(variant_tag)); cx.build.CondBr(lleq, matched_cx.llbb, next_cx.llbb); + auto ty_params = node_ann_ty_params(ann); + if (_vec.len[@ast.pat](subpats) > 0u) { auto llblobptr = matched_cx.build.GEP(lltagptr, vec(C_int(0), C_int(1))); auto i = 0; for (@ast.pat subpat in subpats) { - auto rslt = GEP_tag(matched_cx, llblobptr, variants.(i), - i); + auto rslt = GEP_tag(matched_cx, llblobptr, vdef._0, + vdef._1, ty_params, i); auto llsubvalptr = rslt.val; matched_cx = rslt.bcx; @@ -3025,7 +3054,7 @@ fn trans_pat_binding(@block_ctxt cx, @ast.pat pat, ValueRef llval) ret copy_ty(bcx, INIT, dst, llval, ty); } - case (ast.pat_tag(_, ?subpats, ?vdef_opt, _)) { + case (ast.pat_tag(_, ?subpats, ?vdef_opt, ?ann)) { if (_vec.len[@ast.pat](subpats) == 0u) { ret res(cx, llval); } // Get the appropriate variant for this tag. @@ -3036,10 +3065,13 @@ fn trans_pat_binding(@block_ctxt cx, @ast.pat pat, ValueRef llval) T_opaque_tag_ptr(cx.fcx.ccx.tn)); auto llblobptr = cx.build.GEP(lltagptr, vec(C_int(0), C_int(1))); + auto ty_param_substs = node_ann_ty_params(ann); + auto this_cx = cx; auto i = 0; for (@ast.pat subpat in subpats) { - auto rslt = GEP_tag(this_cx, llblobptr, variant, i); + auto rslt = GEP_tag(this_cx, llblobptr, vdef._0, vdef._1, + ty_param_substs, i); this_cx = rslt.bcx; auto llsubvalptr = rslt.val; @@ -4926,6 +4958,11 @@ fn trans_tag_variant(@crate_ctxt cx, ast.def_id tag_id, none[TypeRef], ret_ty_of_fn(variant.ann), fn_args, ty_params); + let vec[@ty.t] ty_param_substs = vec(); + for (ast.ty_param tp in ty_params) { + ty_param_substs += vec(plain_ty(ty.ty_param(tp.id))); + } + auto bcx = new_top_block_ctxt(fcx); auto arg_tys = arg_tys_of_fn(variant.ann); @@ -4944,7 +4981,8 @@ fn trans_tag_variant(@crate_ctxt cx, ast.def_id tag_id, i = 0u; for (ast.variant_arg va in variant.args) { - auto rslt = GEP_tag(bcx, llblobptr, variant, i as int); + auto rslt = GEP_tag(bcx, llblobptr, tag_id, variant.id, + ty_param_substs, i as int); bcx = rslt.bcx; auto lldestptr = rslt.val; diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index a0adf55a..7dfe918c 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -1085,6 +1085,7 @@ fn demand_pat(&@fn_ctxt fcx, @ty.t expected, @ast.pat pat) -> @ast.pat { fail; } } + auto tps_opt = some[vec[@ty.t]](ty_param_substs); // The type of the tag isn't enough; we also have to get the type // of the variant, which is either a tag type in the case of @@ -1100,7 +1101,7 @@ fn demand_pat(&@fn_ctxt fcx, @ty.t expected, @ast.pat pat) -> @ast.pat { // Nullary tag variant. check (subpats_len == 0u); p_1 = ast.pat_tag(id, subpats, vdef_opt, - ast.ann_type(t, none[vec[@ty.t]])); + ast.ann_type(t, tps_opt)); } case (ty.ty_fn(_, ?args, ?tag_ty)) { // N-ary tag variant. @@ -1115,7 +1116,7 @@ fn demand_pat(&@fn_ctxt fcx, @ty.t expected, @ast.pat pat) -> @ast.pat { i += 1u; } p_1 = ast.pat_tag(id, new_subpats, vdef_opt, - ast.ann_type(tag_ty, none[vec[@ty.t]])); + ast.ann_type(tag_ty, tps_opt)); } } } -- cgit v1.2.3 From fb246e4e478b487da3a0ad36583217b32f483116 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Wed, 9 Mar 2011 19:01:13 -0800 Subject: Un-XFAIL a couple export-related tests. --- src/Makefile | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Makefile b/src/Makefile index 70e2330e..209e1b90 100644 --- a/src/Makefile +++ b/src/Makefile @@ -447,7 +447,6 @@ TEST_XFAILS_RUSTC := $(addprefix test/run-pass/, \ constrained-type.rs \ destructor-ordering.rs \ drop-parametric-closure-with-bound-box.rs \ - export-non-interference.rs \ foreach-nested-2.rs \ foreach-nested.rs \ foreach-put-structured.rs \ @@ -507,7 +506,6 @@ TEST_XFAILS_RUSTC := $(addprefix test/run-pass/, \ threads.rs \ type-sizes.rs \ typestate-cfg-nesting.rs \ - use-import-export.rs \ user.rs \ utf8.rs \ vec-alloc-append.rs \ -- cgit v1.2.3 From 8e8c336f93becbc394b99e978cc3d8145e7e9d7c Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Wed, 9 Mar 2011 20:14:19 -0800 Subject: Implement deep structural comparison through boxes and sequences. --- src/Makefile | 2 + src/comp/middle/trans.rs | 205 ++++++++++++++++++++++++++------------- src/comp/middle/ty.rs | 8 ++ src/test/run-pass/box-compare.rs | 5 + src/test/run-pass/seq-compare.rs | 15 +++ 5 files changed, 167 insertions(+), 68 deletions(-) create mode 100644 src/test/run-pass/box-compare.rs create mode 100644 src/test/run-pass/seq-compare.rs diff --git a/src/Makefile b/src/Makefile index 209e1b90..0bddc0de 100644 --- a/src/Makefile +++ b/src/Makefile @@ -402,6 +402,7 @@ TEST_XFAILS_BOOT := $(TASK_XFAILS) \ $(NOMINAL_TAG_XFAILS) \ $(CONST_TAG_XFAILS) \ test/run-pass/arith-unsigned.rs \ + test/run-pass/box-compare.rs \ test/run-pass/child-outlives-parent.rs \ test/run-pass/clone-with-exterior.rs \ test/run-pass/constrained-type.rs \ @@ -416,6 +417,7 @@ TEST_XFAILS_BOOT := $(TASK_XFAILS) \ test/run-pass/lib-io.rs \ test/run-pass/mlist-cycle.rs \ test/run-pass/obj-as.rs \ + test/run-pass/seq-compare.rs \ test/run-pass/task-comm.rs \ test/run-pass/task-comm-3.rs \ test/run-pass/vec-slice.rs \ diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 00e7e6d8..172f731b 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -890,6 +890,11 @@ fn umax(@block_ctxt cx, ValueRef a, ValueRef b) -> ValueRef { ret cx.build.Select(cond, b, a); } +fn umin(@block_ctxt cx, ValueRef a, ValueRef b) -> ValueRef { + auto cond = cx.build.ICmp(lib.llvm.LLVMIntULT, a, b); + ret cx.build.Select(cond, a, b); +} + fn align_to(@block_ctxt cx, ValueRef off, ValueRef align) -> ValueRef { auto mask = cx.build.Sub(align, C_int(1)); auto bumped = cx.build.Add(off, mask); @@ -1774,7 +1779,7 @@ fn mk_plain_tag(ast.def_id tid) -> @ty.t { } -type val_fn = fn(@block_ctxt cx, ValueRef v) -> result; +type val_pair_fn = fn(@block_ctxt cx, ValueRef dst, ValueRef src) -> result; type val_and_ty_fn = fn(@block_ctxt cx, ValueRef v, @ty.t t) -> result; @@ -1987,13 +1992,15 @@ fn iter_structural_ty_full(@block_ctxt cx, // Iterates through a pointer range, until the src* hits the src_lim*. fn iter_sequence_raw(@block_ctxt cx, + ValueRef dst, // elt* ValueRef src, // elt* ValueRef src_lim, // elt* ValueRef elt_sz, - val_fn f) -> result { + val_pair_fn f) -> result { auto bcx = cx; + let ValueRef dst_int = vp2i(bcx, dst); let ValueRef src_int = vp2i(bcx, src); let ValueRef src_lim_int = vp2i(bcx, src_lim); @@ -2003,6 +2010,8 @@ fn iter_sequence_raw(@block_ctxt cx, bcx.build.Br(cond_cx.llbb); + let ValueRef dst_curr = cond_cx.build.Phi(T_int(), + vec(dst_int), vec(bcx.llbb)); let ValueRef src_curr = cond_cx.build.Phi(T_int(), vec(src_int), vec(bcx.llbb)); @@ -2011,14 +2020,18 @@ fn iter_sequence_raw(@block_ctxt cx, cond_cx.build.CondBr(end_test, body_cx.llbb, next_cx.llbb); + auto dst_curr_ptr = vi2p(body_cx, dst_curr, T_ptr(T_i8())); auto src_curr_ptr = vi2p(body_cx, src_curr, T_ptr(T_i8())); - auto body_res = f(body_cx, src_curr_ptr); + auto body_res = f(body_cx, dst_curr_ptr, src_curr_ptr); body_cx = body_res.bcx; + auto dst_next = body_cx.build.Add(dst_curr, elt_sz); auto src_next = body_cx.build.Add(src_curr, elt_sz); body_cx.build.Br(cond_cx.llbb); + cond_cx.build.AddIncomingToPhi(dst_curr, vec(dst_next), + vec(body_cx.llbb)); cond_cx.build.AddIncomingToPhi(src_curr, vec(src_next), vec(body_cx.llbb)); @@ -2034,15 +2047,16 @@ fn iter_sequence_inner(@block_ctxt cx, fn adaptor_fn(val_and_ty_fn f, @ty.t elt_ty, @block_ctxt cx, - ValueRef v) -> result { + ValueRef dst, + ValueRef src) -> result { auto llty = type_of(cx.fcx.ccx, elt_ty); - auto p = cx.build.PointerCast(v, T_ptr(llty)); + auto p = cx.build.PointerCast(src, T_ptr(llty)); ret f(cx, load_scalar_or_boxed(cx, p, elt_ty), elt_ty); } 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, _, _)); + be iter_sequence_raw(elt_sz.bcx, src, src, src_lim, elt_sz.val, + bind adaptor_fn(f, elt_ty, _, _, _)); } @@ -2378,13 +2392,27 @@ fn trans_unary(@block_ctxt cx, ast.unop op, fail; } -fn trans_compare(@block_ctxt cx, ast.binop op, @ty.t t, - ValueRef lhs, ValueRef rhs) -> result { +fn trans_compare(@block_ctxt cx0, ast.binop op, @ty.t t0, + ValueRef lhs0, ValueRef rhs0) -> result { + + auto cx = cx0; + + auto lhs_r = autoderef(cx, lhs0, t0); + auto lhs = lhs_r.val; + cx = lhs_r.bcx; + + auto rhs_r = autoderef(cx, rhs0, t0); + auto rhs = rhs_r.val; + cx = rhs_r.bcx; + + auto t = autoderefed_ty(t0); if (ty.type_is_scalar(t)) { ret res(cx, trans_scalar_compare(cx, op, t, lhs, rhs)); - } else if (ty.type_is_structural(t)) { + } else if (ty.type_is_structural(t) + || ty.type_is_sequence(t)) { + 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); @@ -2415,28 +2443,52 @@ fn trans_compare(@block_ctxt cx, ast.binop op, @ty.t t, auto flag = scx.build.Alloca(T_i1()); - 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); + if (ty.type_is_sequence(t)) { + + // If we hit == all the way through the minimum-shared-length + // section, default to judging the relative sequence lengths. + auto len_cmp = + trans_integral_compare(scx, op, plain_ty(ty.ty_uint), + vec_fill(scx, lhs), + vec_fill(scx, rhs)); + scx.build.Store(len_cmp, flag); + + } else { + auto T = C_integral(1, T_i1()); + auto F = C_integral(0, T_i1()); + + alt (op) { + // ==, <= and >= default to true if they find == all the way. + case (ast.eq) { scx.build.Store(T, flag); } + case (ast.le) { scx.build.Store(T, flag); } + case (ast.ge) { scx.build.Store(T, flag); } + case (_) { + // < > default to false if they find == all the way. + scx.build.Store(F, flag); + } + } } fn inner(@block_ctxt last_cx, + bool load_inner, ValueRef flag, ast.binop op, @block_ctxt cx, - ValueRef av, - ValueRef bv, + ValueRef av0, + ValueRef bv0, @ty.t t) -> result { auto cnt_cx = new_sub_block_ctxt(cx, "continue comparison"); auto stop_cx = new_sub_block_ctxt(cx, "stop comparison"); + auto av = av0; + auto bv = bv0; + if (load_inner) { + av = load_scalar_or_boxed(cx, av, t); + bv = load_scalar_or_boxed(cx, bv, t); + } + // 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); @@ -2448,16 +2500,32 @@ fn trans_compare(@block_ctxt cx, ast.binop op, @ty.t t, ret res(cnt_cx, C_nil()); } - auto r = iter_structural_ty_full(scx, lhs, rhs, t, - bind inner(next, flag, op, - _, _, _, _)); + auto r; + if (ty.type_is_structural(t)) { + r = iter_structural_ty_full(scx, lhs, rhs, t, + bind inner(next, false, flag, op, + _, _, _, _)); + } else { + auto lhs_p0 = vec_p0(scx, lhs); + auto rhs_p0 = vec_p0(scx, rhs); + auto min_len = umin(scx, vec_fill(scx, lhs), vec_fill(scx, rhs)); + auto rhs_lim = scx.build.GEP(rhs_p0, vec(min_len)); + auto elt_ty = ty.sequence_element_type(t); + auto elt_llsz_r = size_of(scx, elt_ty); + scx = elt_llsz_r.bcx; + r = iter_sequence_raw(scx, lhs, rhs, rhs_lim, + elt_llsz_r.val, + bind inner(next, true, flag, op, + _, _, _, elt_ty)); + } r.bcx.build.Br(next.llbb); auto v = next.build.Load(flag); ret res(next, v); + } else { - // FIXME: compare vec, str, box? + // FIXME: compare obj, fn by pointer? cx.fcx.ccx.sess.unimpl("type in trans_compare"); ret res(cx, C_bool(false)); } @@ -5670,6 +5738,45 @@ fn make_vec_append_glue(ModuleRef llmod, type_names tn) -> ValueRef { ret llfn; } + +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); +} + +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)); +} + fn trans_vec_append_glue(@crate_ctxt cx) { auto llfn = cx.glues.vec_append_glue; @@ -5700,45 +5807,6 @@ fn trans_vec_append_glue(@crate_ctxt cx) { // 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. - 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); - } - - 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", @@ -5780,16 +5848,17 @@ fn trans_vec_append_glue(@crate_ctxt cx) { C_int(abi.tydesc_field_size)))); fn take_one(ValueRef elt_tydesc, - @block_ctxt cx, ValueRef v) -> result { - call_tydesc_glue_full(cx, v, + @block_ctxt cx, + ValueRef dst, ValueRef src) -> result { + call_tydesc_glue_full(cx, src, elt_tydesc, abi.tydesc_field_take_glue_off); - ret res(cx, v); + ret res(cx, src); } - auto bcx = iter_sequence_raw(cx, src, src_lim, + auto bcx = iter_sequence_raw(cx, dst, src, src_lim, elt_llsz, bind take_one(elt_tydesc, - _, _)).bcx; + _, _, _)).bcx; ret call_memcpy(bcx, dst, src, n_bytes); } diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs index 958d0b78..bd3e3263 100644 --- a/src/comp/middle/ty.rs +++ b/src/comp/middle/ty.rs @@ -373,6 +373,14 @@ fn get_element_type(@t ty, uint i) -> @t { fail; } +fn type_is_box(@t ty) -> bool { + alt (ty.struct) { + case (ty_box(_)) { ret true; } + case (_) { ret false; } + } + fail; +} + fn type_is_boxed(@t ty) -> bool { alt (ty.struct) { case (ty_str) { ret true; } diff --git a/src/test/run-pass/box-compare.rs b/src/test/run-pass/box-compare.rs new file mode 100644 index 00000000..5115d510 --- /dev/null +++ b/src/test/run-pass/box-compare.rs @@ -0,0 +1,5 @@ +fn main() { + check (@1 < @3); + check (@@"hello " > @@"hello"); + check (@@@"hello" != @@@"there"); +} \ No newline at end of file diff --git a/src/test/run-pass/seq-compare.rs b/src/test/run-pass/seq-compare.rs new file mode 100644 index 00000000..b3fe5701 --- /dev/null +++ b/src/test/run-pass/seq-compare.rs @@ -0,0 +1,15 @@ +fn main() { + check ("hello" < "hellr"); + check ("hello " > "hello"); + check ("hello" != "there"); + + check (vec(1,2,3,4) > vec(1,2,3)); + check (vec(1,2,3) < vec(1,2,3,4)); + check (vec(1,2,4,4) > vec(1,2,3,4)); + check (vec(1,2,3,4) < vec(1,2,4,4)); + check (vec(1,2,3) <= vec(1,2,3)); + check (vec(1,2,3) <= vec(1,2,3,3)); + check (vec(1,2,3,4) > vec(1,2,3)); + check (vec(1,2,3) == vec(1,2,3)); + check (vec(1,2,3) != vec(1,1,3)); +} \ No newline at end of file -- cgit v1.2.3 From 0d3cec71a3282a090903a919d418c638a3b1ebe6 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 10 Mar 2011 10:17:10 -0800 Subject: Fix eval typo (caught by Martin Hock). --- src/comp/front/eval.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/comp/front/eval.rs b/src/comp/front/eval.rs index cae72b1e..ac4b704b 100644 --- a/src/comp/front/eval.rs +++ b/src/comp/front/eval.rs @@ -42,7 +42,7 @@ fn val_is_bool(val v) -> bool { fn val_is_int(val v) -> bool { alt (v) { - case (val_bool(_)) { ret true; } + case (val_int(_)) { ret true; } case (_) { } } ret false; -- cgit v1.2.3 From 7505c1fa2319adbd928847ca27f75f5a95eb7c3d Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Thu, 10 Mar 2011 11:27:51 -0800 Subject: rustc: Run cleanups on while expressions' condition blocks. Un-XFAIL while-prelude-drop.rs. --- src/Makefile | 1 - src/comp/middle/trans.rs | 6 +++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/Makefile b/src/Makefile index 0bddc0de..fa4ddd20 100644 --- a/src/Makefile +++ b/src/Makefile @@ -513,7 +513,6 @@ TEST_XFAILS_RUSTC := $(addprefix test/run-pass/, \ vec-alloc-append.rs \ vec-append.rs \ vec-slice.rs \ - while-prelude-drop.rs \ while-with-break.rs \ yield.rs \ yield2.rs \ diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 172f731b..ac3d78e7 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -3005,9 +3005,9 @@ fn trans_while(@block_ctxt cx, @ast.expr cond, auto cond_res = trans_expr(cond_cx, cond); body_res.bcx.build.Br(cond_cx.llbb); - cond_res.bcx.build.CondBr(cond_res.val, - body_cx.llbb, - next_cx.llbb); + + auto cond_bcx = trans_block_cleanups(cond_res.bcx, cond_cx); + cond_bcx.build.CondBr(cond_res.val, body_cx.llbb, next_cx.llbb); cx.build.Br(cond_cx.llbb); ret res(next_cx, C_nil()); -- cgit v1.2.3 From 36b81abf619171ccbdee8ca6471f340c5a4e0ed5 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Thu, 10 Mar 2011 10:40:44 -0800 Subject: rustc: Perform a cast in vector initialization due to changing layers of indirection. Keep test/run-pass/size-and-align.rs XFAIL'd due to a leak in rustboot. --- src/comp/middle/trans.rs | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index ac3d78e7..f69834d3 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -4050,7 +4050,27 @@ fn trans_vec(@block_ctxt cx, vec[@ast.expr] args, 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; + + // Cast the destination type to the source type. This is needed to + // make tags work, for a subtle combination of reasons: + // + // (1) "dst_res" above is derived from "body", which is in turn + // derived from "vec_val". + // (2) "vec_val" has the LLVM type "llty". + // (3) "llty" is the result of calling type_of() on a vector type. + // (4) For tags, type_of() returns a different type depending on + // on whether the tag is behind a box or not. Vector types are + // considered boxes. + // (5) "src_res" is derived from "unit_ty", which is not behind a box. + + auto dst_val; + if (!ty.type_has_dynamic_size(unit_ty)) { + dst_val = bcx.build.PointerCast(dst_res.val, T_ptr(llunit_ty)); + } else { + dst_val = dst_res.val; + } + + bcx = copy_ty(bcx, INIT, dst_val, src_res.val, unit_ty).bcx; i += 1; } auto fill = bcx.build.GEP(vec_val, -- cgit v1.2.3 From 5f29988a2cf9263631bf79b758d1f5d3e33dbb80 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 10 Mar 2011 14:15:02 -0800 Subject: Add failing test for tag-leaking case. --- src/Makefile | 1 + src/test/run-pass/leak-tag-copy.rs | 9 +++++++++ 2 files changed, 10 insertions(+) create mode 100644 src/test/run-pass/leak-tag-copy.rs diff --git a/src/Makefile b/src/Makefile index fa4ddd20..929be490 100644 --- a/src/Makefile +++ b/src/Makefile @@ -414,6 +414,7 @@ TEST_XFAILS_BOOT := $(TASK_XFAILS) \ test/run-pass/generic-fn-box.rs \ test/run-pass/generic-tup.rs \ test/run-pass/iter-ret.rs \ + test/run-pass/leak-tag-copy.rs \ test/run-pass/lib-io.rs \ test/run-pass/mlist-cycle.rs \ test/run-pass/obj-as.rs \ diff --git a/src/test/run-pass/leak-tag-copy.rs b/src/test/run-pass/leak-tag-copy.rs new file mode 100644 index 00000000..25d87c6e --- /dev/null +++ b/src/test/run-pass/leak-tag-copy.rs @@ -0,0 +1,9 @@ +tag t { + a; + b(@int); +} + +fn main() { + auto x = b(@10); + x = a; +} \ No newline at end of file -- cgit v1.2.3 From ab7b9b847acfd1151543fb6ad99967e71fddd870 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 10 Mar 2011 14:15:41 -0800 Subject: Fix seemingly un-noticed thinko in structural copying code in rustboot. --- src/boot/me/trans.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/boot/me/trans.ml b/src/boot/me/trans.ml index bbf49e83..d6b470f9 100644 --- a/src/boot/me/trans.ml +++ b/src/boot/me/trans.ml @@ -3914,7 +3914,7 @@ let trans_visitor then iter_ty_parts_full ty_params dst src ty (fun dst src ty -> - trans_copy_ty ty_params true + trans_copy_ty ty_params initializing dst ty src ty) else let initflag = Il.Reg (force_to_reg one) in -- cgit v1.2.3 From 4ca0259b20bfc2f33f23e8b82864908fbb3b8133 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20=C3=81vila=20de=20Esp=C3=ADndola?= Date: Thu, 10 Mar 2011 17:34:58 -0500 Subject: Update the current id when we create sub parsers. --- src/comp/driver/rustc.rs | 6 ++++-- src/comp/front/eval.rs | 7 +++++-- src/comp/front/parser.rs | 11 ++++++++--- 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/src/comp/driver/rustc.rs b/src/comp/driver/rustc.rs index 6366bcaf..f26dd02e 100644 --- a/src/comp/driver/rustc.rs +++ b/src/comp/driver/rustc.rs @@ -54,7 +54,8 @@ impure fn compile_input(session.session sess, eval.env env, str input, str output, bool shared) { - auto p = parser.new_parser(sess, env, 0, input); + auto def = tup(0, 0); + auto p = parser.new_parser(sess, env, def, input); auto crate = parse_input(sess, p, input); crate = resolve.resolve_crate(sess, crate); crate = typeck.check_crate(sess, crate); @@ -64,7 +65,8 @@ impure fn compile_input(session.session sess, impure fn pretty_print_input(session.session sess, eval.env env, str input) { - auto p = front.parser.new_parser(sess, env, 0, input); + auto def = tup(0, 0); + auto p = front.parser.new_parser(sess, env, def, input); auto crate = front.parser.parse_crate_from_source_file(p); pretty.pprust.print_ast(crate.node.module, std.io.stdout_writer()); } diff --git a/src/comp/front/eval.rs b/src/comp/front/eval.rs index ac4b704b..efa9aa0d 100644 --- a/src/comp/front/eval.rs +++ b/src/comp/front/eval.rs @@ -393,9 +393,12 @@ impure fn eval_crate_directive(parser p, auto full_path = prefix + std.os.path_sep() + file_path; - auto p0 = new_parser(p.get_session(), e, 0, full_path); + auto start_id = p.next_def_id(); + auto p0 = new_parser(p.get_session(), e, start_id, full_path); auto m0 = parse_mod_items(p0, token.EOF); - auto im = ast.item_mod(id, m0, p.next_def_id()); + auto next_id = p0.next_def_id(); + p.set_def(next_id._1); + auto im = ast.item_mod(id, m0, next_id); auto i = @spanned(cdir.span, cdir.span, im); ast.index_item(index, i); append[@ast.item](items, i); diff --git a/src/comp/front/parser.rs b/src/comp/front/parser.rs index 71e592ff..2836b120 100644 --- a/src/comp/front/parser.rs +++ b/src/comp/front/parser.rs @@ -35,12 +35,13 @@ state type parser = fn get_session() -> session.session; fn get_span() -> common.span; fn next_def_id() -> ast.def_id; + fn set_def(ast.def_num); fn get_prec_table() -> vec[op_spec]; }; impure fn new_parser(session.session sess, eval.env env, - ast.crate_num crate, + ast.def_id initial_def, str path) -> parser { state obj stdio_parser(session.session sess, eval.env env, @@ -94,6 +95,10 @@ impure fn new_parser(session.session sess, ret tup(crate, def); } + fn set_def(ast.def_num d) { + def = d; + } + fn get_file_type() -> file_type { ret ftype; } @@ -114,8 +119,8 @@ impure fn new_parser(session.session sess, auto rdr = lexer.new_reader(srdr, path); auto npos = rdr.get_curr_pos(); ret stdio_parser(sess, env, ftype, lexer.next_token(rdr), - npos, npos, 0, UNRESTRICTED, crate, rdr, - prec_table()); + npos, npos, initial_def._1, UNRESTRICTED, initial_def._0, + rdr, prec_table()); } impure fn unexpected(parser p, token.token t) { -- cgit v1.2.3 From 41d5094a8e0f58221b470a2676a9a1dae287102d Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Thu, 10 Mar 2011 14:31:15 -0800 Subject: rustc: Fix off-by-one error and logic error regarding type parameters in the translation of bind expressions. Un-XFAIL bind-obj-ctor.rs. --- src/Makefile | 1 - src/comp/middle/trans.rs | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Makefile b/src/Makefile index 929be490..f96ad040 100644 --- a/src/Makefile +++ b/src/Makefile @@ -443,7 +443,6 @@ TEST_XFAILS_RUSTC := $(addprefix test/run-pass/, \ basic-1.rs \ basic-2.rs \ basic.rs \ - bind-obj-ctor.rs \ child-outlives-parent.rs \ clone-with-exterior.rs \ comm.rs \ diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index f69834d3..51e8fb56 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -3526,7 +3526,7 @@ fn trans_bind_thunk(@crate_ctxt cx, i += 1u; } - let uint a = 2u + i; // retptr, task ptr, env come first + let uint a = 3u; // retptr, task ptr, env come first let int b = 0; let uint outgoing_arg_index = 0u; let vec[TypeRef] llout_arg_tys = -- cgit v1.2.3 From 185bcc62185c4ec8274ea94387629ddfae3c7f0e Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Thu, 10 Mar 2011 15:09:41 -0800 Subject: rustc: Increment the counter in trans_bind_thunk() --- src/comp/middle/trans.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 51e8fb56..f1f42ab5 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -3577,7 +3577,7 @@ fn trans_bind_thunk(@crate_ctxt cx, } } - outgoing_arg_index += 0u; + outgoing_arg_index += 1u; } // FIXME: turn this call + ret into a tail call. -- cgit v1.2.3 From 60f86354ad95802da4c861fb8df54abf95f1917b Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Thu, 10 Mar 2011 15:14:45 -0800 Subject: rustc: Use the generic info from the item in bind thunks just as calls do. Un-XFAIL drop-parametric-closure-with-bound-box.rs. --- src/Makefile | 1 - src/comp/middle/trans.rs | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Makefile b/src/Makefile index f96ad040..83dca299 100644 --- a/src/Makefile +++ b/src/Makefile @@ -448,7 +448,6 @@ TEST_XFAILS_RUSTC := $(addprefix test/run-pass/, \ comm.rs \ constrained-type.rs \ destructor-ordering.rs \ - drop-parametric-closure-with-bound-box.rs \ foreach-nested-2.rs \ foreach-nested.rs \ foreach-put-structured.rs \ diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index f1f42ab5..da048951 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -3750,6 +3750,8 @@ fn trans_bind(@block_ctxt cx, @ast.expr f, bcx.build.Store(td, ty_param_slot); i += 1; } + + outgoing_fty = ginfo.item_type; } } -- cgit v1.2.3 From 7454b534112e8cb7b0192d28c8b8685db31ed283 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Thu, 10 Mar 2011 16:49:00 -0800 Subject: rustc: Build up a list of upvars inside foreach bodies --- src/comp/front/ast.rs | 1 + src/comp/middle/trans.rs | 78 ++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 74 insertions(+), 5 deletions(-) diff --git a/src/comp/front/ast.rs b/src/comp/front/ast.rs index 56914800..584586f6 100644 --- a/src/comp/front/ast.rs +++ b/src/comp/front/ast.rs @@ -32,6 +32,7 @@ tag def { def_const(def_id); def_arg(def_id); def_local(def_id); + def_upvar(def_id); def_variant(def_id /* tag */, def_id /* variant */); def_ty(def_id); def_ty_arg(def_id); diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index da048951..32a12c23 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -98,6 +98,7 @@ state type fn_ctxt = rec(ValueRef llfn, hashmap[ast.def_id, ValueRef] llargs, hashmap[ast.def_id, ValueRef] llobjfields, hashmap[ast.def_id, ValueRef] lllocals, + hashmap[ast.def_id, ValueRef] llupvars, hashmap[ast.def_id, ValueRef] lltydescs, @crate_ctxt ccx); @@ -2897,6 +2898,62 @@ fn trans_for(@block_ctxt cx, bind inner(_, local, _, _, body)); } + +// Iterator translation + +// Searches through a block for all references to locals or upvars in this +// frame and returns the list of definition IDs thus found. +fn collect_upvars(@block_ctxt cx, &ast.block bloc, &ast.def_id initial_decl) + -> vec[ast.def_id] { + type env = @rec( + mutable vec[ast.def_id] refs, + hashmap[ast.def_id,()] decls + ); + + fn fold_expr_path(&env e, &common.span sp, &ast.path p, + &option.t[ast.def] d, ast.ann a) -> @ast.expr { + alt (option.get[ast.def](d)) { + case (ast.def_arg(?did)) { e.refs += vec(did); } + case (ast.def_local(?did)) { e.refs += vec(did); } + case (ast.def_upvar(?did)) { e.refs += vec(did); } + case (_) { /* ignore */ } + } + + ret @fold.respan[ast.expr_](sp, ast.expr_path(p, d, a)); + } + + fn fold_decl_local(&env e, &common.span sp, @ast.local local) + -> @ast.decl { + e.decls.insert(local.id, ()); + ret @fold.respan[ast.decl_](sp, ast.decl_local(local)); + } + + auto fep = fold_expr_path; + auto fdl = fold_decl_local; + auto fld = @rec( + fold_expr_path=fep, + fold_decl_local=fdl + with *fold.new_identity_fold[env]() + ); + + let vec[ast.def_id] refs = vec(); + let hashmap[ast.def_id,()] decls = new_def_hash[()](); + decls.insert(initial_decl, ()); + let env e = @rec(mutable refs=refs, decls=decls); + + fold.fold_block[env](e, fld, bloc); + + // Calculate (refs - decls). This is the set of captured upvars. + let vec[ast.def_id] result = vec(); + for (ast.def_id ref_id in e.refs) { + if (!decls.contains_key(ref_id)) { + result += vec(ref_id); + } + } + + ret result; +} + fn trans_for_each(@block_ctxt cx, @ast.decl decl, @ast.expr seq, @@ -2928,19 +2985,26 @@ 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_opaque_closure_ptr(cx.fcx.ccx.tn); - - - // Step 2: Declare foreach body function. - // FIXME: possibly support alias-mode here? auto decl_ty = plain_ty(ty.ty_nil); + auto decl_id; alt (decl.node) { case (ast.decl_local(?local)) { decl_ty = node_ann_type(cx.fcx.ccx, local.ann); + decl_id = local.id; } } + auto upvars = collect_upvars(cx, body, decl_id); + if (_vec.len[ast.def_id](upvars) > 0u) { + cx.fcx.ccx.sess.unimpl("upvars in for each"); + fail; + } + + auto env_ty = T_opaque_closure_ptr(cx.fcx.ccx.tn); + + // Step 2: Declare foreach body function. + let str s = cx.fcx.ccx.names.next("_rust_foreach") + sep() + cx.fcx.ccx.path; @@ -4624,6 +4688,7 @@ fn new_fn_ctxt(@crate_ctxt cx, let hashmap[ast.def_id, ValueRef] llargs = new_def_hash[ValueRef](); let hashmap[ast.def_id, ValueRef] llobjfields = new_def_hash[ValueRef](); let hashmap[ast.def_id, ValueRef] lllocals = new_def_hash[ValueRef](); + let hashmap[ast.def_id, ValueRef] llupvars = new_def_hash[ValueRef](); let hashmap[ast.def_id, ValueRef] lltydescs = new_def_hash[ValueRef](); ret @rec(llfn=llfndecl, @@ -4635,6 +4700,7 @@ fn new_fn_ctxt(@crate_ctxt cx, llargs=llargs, llobjfields=llobjfields, lllocals=lllocals, + llupvars=llupvars, lltydescs=lltydescs, ccx=cx); } @@ -5486,6 +5552,7 @@ fn trans_exit_task_glue(@crate_ctxt cx) { llargs=new_def_hash[ValueRef](), llobjfields=new_def_hash[ValueRef](), lllocals=new_def_hash[ValueRef](), + llupvars=new_def_hash[ValueRef](), lltydescs=new_def_hash[ValueRef](), ccx=cx); @@ -5819,6 +5886,7 @@ fn trans_vec_append_glue(@crate_ctxt cx) { llargs=new_def_hash[ValueRef](), llobjfields=new_def_hash[ValueRef](), lllocals=new_def_hash[ValueRef](), + llupvars=new_def_hash[ValueRef](), lltydescs=new_def_hash[ValueRef](), ccx=cx); -- cgit v1.2.3 From 3aac5059ee986126851cb4f8bd312f1fb5f9ddea Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 10 Mar 2011 17:25:11 -0800 Subject: Move the glue code to a .o file. This reduces how much asm we print in each "translation unit". Part of it is not repetitive and should probably be moved to a .ll file, but for now we autogen all of it. (Modified somewhat by graydon while integrating). --- src/Makefile | 29 ++++----- src/comp/driver/rustc.rs | 16 +++++ src/comp/middle/trans.rs | 150 +++++++++++++++++++++++++++++------------------ 3 files changed, 123 insertions(+), 72 deletions(-) diff --git a/src/Makefile b/src/Makefile index 83dca299..5d3057b5 100644 --- a/src/Makefile +++ b/src/Makefile @@ -86,7 +86,6 @@ ifdef CFG_WINDOWSY endif CFG_RUNTIME := rustrt.dll CFG_STDLIB := std.dll - CFG_OBJ_SUFFIX := .o CFG_EXE_SUFFIX := .exe CFG_BOOT := ./rustboot.exe CFG_RUSTC := ./rustc.exe @@ -101,7 +100,6 @@ ifdef CFG_UNIXY CFG_INFO := $(info cfg: unix-y environment) CFG_BOOT := ./rustboot CFG_RUSTC := ./rustc - CFG_OBJ_SUFFIX := .o CFG_RUN_TARG = LD_LIBRARY_PATH=. $(CFG_VALGRIND) $(1) CFG_GCC := 1 ifdef MINGW_CROSS @@ -114,7 +112,6 @@ ifdef CFG_UNIXY ifdef CFG_VALGRIND CFG_VALGRIND += wine endif - CFG_OBJ_SUFFIX := .o CFG_EXE_SUFFIX := .exe CFG_GCC_CFLAGS := -march=i686 CFG_GCC_LINK_FLAGS := -shared @@ -302,15 +299,15 @@ RUNTIME_HDR := rt/globals.h \ rt/test/rust_test_util.h RUNTIME_INCS := -Irt/isaac -Irt/uthash -RUNTIME_OBJS := $(RUNTIME_CS:.cpp=$(CFG_OBJ_SUFFIX)) +RUNTIME_OBJS := $(RUNTIME_CS:.cpp=.o) RUNTIME_LIBS := $(CFG_RUNTIME_LIBS) STDLIB_CRATE := lib/std.rc STDLIB_INPUTS := $(wildcard lib/*.rc lib/*.rs lib/*/*.rs) COMPILER_CRATE := comp/rustc.rc -COMPILER_INPUTS := $(wildcard comp/*.rc comp/*.rs comp/*/*.rs) +COMPILER_INPUTS := $(wildcard comp/rustc.rc comp/*.rs comp/*/*.rs) -GENERATED := boot/fe/lexer.ml boot/util/version.ml +GENERATED := boot/fe/lexer.ml boot/util/version.ml glue.o all: $(CFG_RUSTC) $(MKFILES) $(GENERATED) @@ -329,7 +326,7 @@ $(CFG_STDLIB): $(STDLIB_CRATE) $(CFG_BOOT) $(MKFILES) @$(call CFG_ECHO, compile: $<) $(BOOT) -shared -o $@ $(STDLIB_CRATE) -%$(CFG_OBJ_SUFFIX): %.cpp $(MKFILES) +%.o: %.cpp $(MKFILES) @$(call CFG_ECHO, compile: $<) $(CFG_QUIET)$(call CFG_COMPILE_C, $@, $(RUNTIME_INCS)) $< @@ -368,8 +365,12 @@ $(CFG_RUSTC): $(COMPILER_INPUTS) $(CFG_BOOT) $(CFG_RUNTIME) $(CFG_STDLIB) $(BOOT) -minimal -o $@ $< $(CFG_QUIET)chmod 0755 $@ +glue.bc: $(CFG_RUSTC) + @$(call CFG_ECHO, generate: $@) + $(RUSTC) -o $@ -glue + self: $(CFG_RUSTC) - @$(call CFG_ECHO, compile: $<) + @$(call CFG_ECHO, compile: $(COMPILER_CRATE)) $(RUSTC) $(COMPILER_CRATE) @@ -758,9 +759,9 @@ test/bench/shootout/%.boot$(CFG_EXE_SUFFIX): \ @$(call CFG_ECHO, assemble [llvm]: $<) $(CFG_QUIET)gcc $(CFG_GCC_CFLAGS) -o $@ -c $< -%.rustc$(CFG_EXE_SUFFIX): %.o $(CFG_RUNTIME) +%.rustc$(CFG_EXE_SUFFIX): %.o $(CFG_RUNTIME) glue.o @$(call CFG_ECHO, link [llvm]: $<) - $(CFG_QUIET)gcc $(CFG_GCC_CFLAGS) -o $@ $< -L. -lrustrt + $(CFG_QUIET)gcc $(CFG_GCC_CFLAGS) glue.o -o $@ $< -L. -lrustrt @# dsymutil sometimes fails or prints a warning, but the @# program still runs. Since it simplifies debugging other @# programs, I\'ll live with the noise. @@ -797,7 +798,7 @@ C_DEPFILES := $(RUNTIME_CS:%.cpp=%.d) %.d: %.cpp $(MKFILES) @$(call CFG_ECHO, dep: $<) $(CFG_QUIET)$(call CFG_DEPEND_C, $@ \ - $(patsubst %.cpp, %$(CFG_OBJ_SUFFIX), $<), \ + $(patsubst %.cpp, %.o, $<), \ $(RUNTIME_INCS)) $< $(CFG_PATH_MUNGE) >$@.tmp \ && mv $@.tmp $@ @@ -914,12 +915,12 @@ clean: $(CFG_QUIET)rm -f $(ML_DEPFILES:%.d=%.d.tmp) $(CFG_QUIET)rm -f $(C_DEPFILES:%.d=%.d.tmp) $(CFG_QUIET)rm -f $(CRATE_DEPFILES:%.d=%.d.tmp) - $(CFG_QUIET)rm -f $(GENERATED) + $(CFG_QUIET)rm -f $(GENERATED) glue.bc glue.s $(CFG_QUIET)rm -f $(CFG_BOOT) $(CFG_RUNTIME) $(CFG_STDLIB) $(CFG_QUIET)rm -Rf $(PKG_NAME)-*.tar.gz dist - $(CFG_QUIET)rm -f $(foreach ext,cmx cmi cmo cma o a d exe,\ + $(CFG_QUIET)rm -f $(foreach ext,cmx cmi cmo cma bc o a d exe,\ $(wildcard boot/*/*.$(ext) boot/*/*/*.$(ext))) - $(CFG_QUIET)rm -Rf $(foreach ext,out llvm x86 boot rustc o s exe dSYM,\ + $(CFG_QUIET)rm -Rf $(foreach ext,out llvm x86 boot rustc bc o s exe dSYM,\ $(wildcard test/*/*.$(ext))) diff --git a/src/comp/driver/rustc.rs b/src/comp/driver/rustc.rs index f26dd02e..00d41fff 100644 --- a/src/comp/driver/rustc.rs +++ b/src/comp/driver/rustc.rs @@ -84,6 +84,7 @@ fn usage(session.session sess, str argv0) { log ""; log " -o write output to "; log " -nowarn suppress wrong-compiler warning"; + log " -glue generate glue.bc file"; log " -shared compile a shared-library crate"; log " -pp pretty-print the input instead of compiling"; log " -h display this message"; @@ -113,6 +114,7 @@ impure fn main(vec[str] args) { let bool do_warn = true; let bool shared = false; let bool pretty = false; + let bool glue = false; auto i = 1u; auto len = _vec.len[str](args); @@ -123,6 +125,8 @@ impure fn main(vec[str] args) { if (_str.byte_len(arg) > 0u && arg.(0) == '-' as u8) { if (_str.eq(arg, "-nowarn")) { do_warn = false; + } else if (_str.eq(arg, "-glue")) { + glue = true; } else if (_str.eq(arg, "-shared")) { shared = true; } else if (_str.eq(arg, "-pp")) { @@ -159,6 +163,18 @@ impure fn main(vec[str] args) { warn_wrong_compiler(); } + if (glue) { + alt (output_file) { + case (none[str]) { + middle.trans.make_common_glue("glue.bc"); + } + case (some[str](?s)) { + middle.trans.make_common_glue(s); + } + } + ret; + } + alt (input_file) { case (none[str]) { usage(sess, args.(0)); diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 32a12c23..936a12f3 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -839,32 +839,44 @@ fn decl_upcall_glue(ModuleRef llmod, type_names tn, uint _n) -> ValueRef { ret decl_fastcall_fn(llmod, s, T_fn(args, T_int())); } -fn get_upcall(@crate_ctxt cx, str name, int n_args) -> ValueRef { - if (cx.upcalls.contains_key(name)) { - ret cx.upcalls.get(name); +fn get_upcall(&hashmap[str, ValueRef] upcalls, + type_names tn, ModuleRef llmod, + str name, int n_args) -> ValueRef { + if (upcalls.contains_key(name)) { + ret upcalls.get(name); } - auto inputs = vec(T_taskptr(cx.tn)); + auto inputs = vec(T_taskptr(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)); - cx.upcalls.insert(name, f); + auto f = decl_cdecl_fn(llmod, name, T_fn(inputs, output)); + upcalls.insert(name, f); ret f; } fn trans_upcall(@block_ctxt cx, str name, vec[ValueRef] args) -> result { + auto cxx = cx.fcx.ccx; + auto t = trans_upcall2(cx.build, cxx.glues, cx.fcx.lltaskptr, + cxx.upcalls, cxx.tn, cxx.llmod, name, args); + ret res(cx, t); +} + +fn trans_upcall2(builder b, @glue_fns glues, ValueRef lltaskptr, + &hashmap[str, ValueRef] upcalls, + type_names tn, ModuleRef llmod, str name, + vec[ValueRef] args) -> ValueRef { let int n = _vec.len[ValueRef](args) as int; - let ValueRef llupcall = get_upcall(cx.fcx.ccx, name, n); + let ValueRef llupcall = get_upcall(upcalls, tn, llmod, name, n); llupcall = llvm.LLVMConstPointerCast(llupcall, T_int()); - let ValueRef llglue = cx.fcx.ccx.glues.upcall_glues.(n); + let ValueRef llglue = glues.upcall_glues.(n); let vec[ValueRef] call_args = vec(llupcall); - call_args += cx.build.PtrToInt(cx.fcx.lltaskptr, T_int()); + call_args += b.PtrToInt(lltaskptr, T_int()); for (ValueRef a in args) { - call_args += cx.build.ZExtOrBitCast(a, T_int()); + call_args += b.ZExtOrBitCast(a, T_int()); } - ret res(cx, cx.build.FastCall(llglue, call_args)); + ret b.FastCall(llglue, call_args); } fn trans_non_gc_free(@block_ctxt cx, ValueRef v) -> result { @@ -5537,28 +5549,21 @@ fn i2p(ValueRef v, TypeRef t) -> ValueRef { ret llvm.LLVMConstIntToPtr(v, t); } -fn trans_exit_task_glue(@crate_ctxt cx) { +fn trans_exit_task_glue(@glue_fns glues, + &hashmap[str, ValueRef] upcalls, + type_names tn, ModuleRef llmod) { let vec[TypeRef] T_args = vec(); let vec[ValueRef] V_args = vec(); - auto llfn = cx.glues.exit_task_glue; + auto llfn = glues.exit_task_glue; let ValueRef lltaskptr = llvm.LLVMGetParam(llfn, 3u); - auto fcx = @rec(llfn=llfn, - lltaskptr=lltaskptr, - llenv=C_null(T_opaque_closure_ptr(cx.tn)), - 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](), - llupvars=new_def_hash[ValueRef](), - lltydescs=new_def_hash[ValueRef](), - ccx=cx); - auto bcx = new_top_block_ctxt(fcx); - trans_upcall(bcx, "upcall_exit", V_args); - bcx.build.RetVoid(); + auto entrybb = llvm.LLVMAppendBasicBlock(llfn, _str.buf("entry")); + auto build = new_builder(entrybb); + + trans_upcall2(build, glues, lltaskptr, + upcalls, tn, llmod, "upcall_exit", V_args); + build.RetVoid(); } fn create_typedefs(@crate_ctxt cx) { @@ -5567,22 +5572,22 @@ fn create_typedefs(@crate_ctxt cx) { llvm.LLVMAddTypeName(cx.llmod, _str.buf("tydesc"), T_tydesc(cx.tn)); } -fn create_crate_constant(@crate_ctxt cx) { +fn create_crate_constant(ValueRef crate_ptr, @glue_fns glues) { - let ValueRef crate_addr = p2i(cx.crate_ptr); + let ValueRef crate_addr = p2i(crate_ptr); let ValueRef activate_glue_off = - llvm.LLVMConstSub(p2i(cx.glues.activate_glue), crate_addr); + llvm.LLVMConstSub(p2i(glues.activate_glue), crate_addr); let ValueRef yield_glue_off = - llvm.LLVMConstSub(p2i(cx.glues.yield_glue), crate_addr); + llvm.LLVMConstSub(p2i(glues.yield_glue), crate_addr); let ValueRef exit_task_glue_off = - llvm.LLVMConstSub(p2i(cx.glues.exit_task_glue), crate_addr); + llvm.LLVMConstSub(p2i(glues.exit_task_glue), crate_addr); let ValueRef crate_val = C_struct(vec(C_null(T_int()), // ptrdiff_t image_base_off - p2i(cx.crate_ptr), // uintptr_t self_addr + p2i(crate_ptr), // uintptr_t self_addr C_null(T_int()), // ptrdiff_t debug_abbrev_off C_null(T_int()), // size_t debug_abbrev_sz C_null(T_int()), // ptrdiff_t debug_info_off @@ -5598,7 +5603,7 @@ fn create_crate_constant(@crate_ctxt cx) { C_int(abi.abi_x86_rustc_fastcall) // uintptr_t abi_tag )); - llvm.LLVMSetInitializer(cx.crate_ptr, crate_val); + llvm.LLVMSetInitializer(crate_ptr, crate_val); } fn find_main_fn(@crate_ctxt cx) -> ValueRef { @@ -5700,26 +5705,28 @@ 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, type_names tn) -> ValueRef { +fn decl_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); + ret decl_fastcall_fn(llmod, abi.no_op_type_glue_name(), ty); +} + +fn make_no_op_type_glue(ValueRef fun) { auto bb_name = _str.buf("_rust_no_op_type_glue_bb"); auto llbb = llvm.LLVMAppendBasicBlock(fun, bb_name); new_builder(llbb).RetVoid(); - ret fun; } -fn make_memcpy_glue(ModuleRef llmod) -> ValueRef { - - // We're not using the LLVM memcpy intrinsic. It appears to call through - // to the platform memcpy in some cases, which is not terribly safe to run - // on a rust stack. - +fn decl_memcpy_glue(ModuleRef llmod) -> ValueRef { auto p8 = T_ptr(T_i8()); auto ty = T_fn(vec(p8, p8, T_int()), T_void()); - auto fun = decl_fastcall_fn(llmod, abi.memcpy_glue_name(), ty); + ret decl_fastcall_fn(llmod, abi.memcpy_glue_name(), ty); +} +fn make_memcpy_glue(ValueRef fun) { + // We're not using the LLVM memcpy intrinsic. It appears to call through + // to the platform memcpy in some cases, which is not terribly safe to run + // on a rust stack. auto initbb = llvm.LLVMAppendBasicBlock(fun, _str.buf("init")); auto hdrbb = llvm.LLVMAppendBasicBlock(fun, _str.buf("hdr")); auto loopbb = llvm.LLVMAppendBasicBlock(fun, _str.buf("loop")); @@ -5751,18 +5758,18 @@ fn make_memcpy_glue(ModuleRef llmod) -> ValueRef { // End block auto eb = new_builder(endbb); eb.RetVoid(); - ret fun; } -fn make_bzero_glue(ModuleRef llmod) -> ValueRef { - - // We're not using the LLVM memset intrinsic. Same as with memcpy. - +fn decl_bzero_glue(ModuleRef llmod) -> ValueRef { auto p8 = T_ptr(T_i8()); auto ty = T_fn(vec(p8, T_int()), T_void()); - auto fun = decl_fastcall_fn(llmod, abi.bzero_glue_name(), ty); + ret decl_fastcall_fn(llmod, abi.bzero_glue_name(), ty); +} +fn make_bzero_glue(ModuleRef llmod) -> ValueRef { + // We're not using the LLVM memset intrinsic. Same as with memcpy. + auto fun = decl_bzero_glue(llmod); auto initbb = llvm.LLVMAppendBasicBlock(fun, _str.buf("init")); auto hdrbb = llvm.LLVMAppendBasicBlock(fun, _str.buf("hdr")); auto loopbb = llvm.LLVMAppendBasicBlock(fun, _str.buf("loop")); @@ -6008,14 +6015,16 @@ fn make_glues(ModuleRef llmod, type_names tn) -> @glue_fns { upcall_glues = _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, tn), - memcpy_glue = make_memcpy_glue(llmod), - bzero_glue = make_bzero_glue(llmod), + no_op_type_glue = decl_no_op_type_glue(llmod, tn), + memcpy_glue = decl_memcpy_glue(llmod), + bzero_glue = decl_bzero_glue(llmod), vec_append_glue = make_vec_append_glue(llmod, tn)); } -fn trans_crate(session.session sess, @ast.crate crate, str output, - bool shared) { +fn make_common_glue(str output) { + // FIXME: part of this is repetitive and is probably a good idea + // to autogen it, but things like the memcpy implementation are not + // and it might be better to just check in a .ll file. auto llmod = llvm.LLVMModuleCreateWithNameInContext(_str.buf("rust_out"), llvm.LLVMGetGlobalContext()); @@ -6027,8 +6036,35 @@ fn trans_crate(session.session sess, @ast.crate crate, str output, let ValueRef crate_ptr = llvm.LLVMAddGlobal(llmod, T_crate(tn), _str.buf("rust_crate")); + auto intrinsics = declare_intrinsics(llmod); + llvm.LLVMSetModuleInlineAsm(llmod, _str.buf(x86.get_module_asm())); + auto glues = make_glues(llmod, tn); + create_crate_constant(crate_ptr, glues); + make_memcpy_glue(glues.memcpy_glue); + + trans_exit_task_glue(glues, new_str_hash[ValueRef](), tn, llmod); + + check_module(llmod); + + llvm.LLVMWriteBitcodeToFile(llmod, _str.buf(output)); + llvm.LLVMDisposeModule(llmod); +} + +fn trans_crate(session.session sess, @ast.crate crate, str output, + bool shared) { + auto llmod = + llvm.LLVMModuleCreateWithNameInContext(_str.buf("rust_out"), + llvm.LLVMGetGlobalContext()); + + 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(tn), _str.buf("rust_crate")); + auto intrinsics = declare_intrinsics(llmod); auto glues = make_glues(llmod, tn); @@ -6069,9 +6105,7 @@ fn trans_crate(session.session sess, @ast.crate crate, str output, trans_constants(cx, crate); trans_mod(cx, crate.node.module); - trans_exit_task_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 bc5a8393e714f05d2dbb5abf1ebb7ff6267f48fe Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 10 Mar 2011 17:57:22 -0800 Subject: Help extinguish fires. --- src/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Makefile b/src/Makefile index 5d3057b5..21366b6b 100644 --- a/src/Makefile +++ b/src/Makefile @@ -365,7 +365,7 @@ $(CFG_RUSTC): $(COMPILER_INPUTS) $(CFG_BOOT) $(CFG_RUNTIME) $(CFG_STDLIB) $(BOOT) -minimal -o $@ $< $(CFG_QUIET)chmod 0755 $@ -glue.bc: $(CFG_RUSTC) +glue.bc: $(CFG_RUSTC) $(CFG_RUNTIME) $(CFG_STDLIB) @$(call CFG_ECHO, generate: $@) $(RUSTC) -o $@ -glue -- cgit v1.2.3 From 0117cf2fc27354e55bcb1c1f0ede97d9ac92f02d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20=C3=81vila=20de=20Esp=C3=ADndola?= Date: Thu, 10 Mar 2011 21:33:53 -0500 Subject: Handle resolving to native modules. --- src/comp/front/ast.rs | 1 + src/comp/middle/resolve.rs | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/src/comp/front/ast.rs b/src/comp/front/ast.rs index 584586f6..05daf5ee 100644 --- a/src/comp/front/ast.rs +++ b/src/comp/front/ast.rs @@ -29,6 +29,7 @@ tag def { def_obj(def_id); def_obj_field(def_id); def_mod(def_id); + def_native_mod(def_id); def_const(def_id); def_arg(def_id); def_local(def_id); diff --git a/src/comp/middle/resolve.rs b/src/comp/middle/resolve.rs index 5b6db631..7102e442 100644 --- a/src/comp/middle/resolve.rs +++ b/src/comp/middle/resolve.rs @@ -71,6 +71,13 @@ fn unwrap_def(def_wrap d) -> def { } } } + case (def_wrap_native_mod(?m)) { + alt (m.node) { + case (ast.item_native_mod(_, _, ?id)) { + ret ast.def_native_mod(id); + } + } + } case (def_wrap_other(?d)) { ret d; } -- cgit v1.2.3 From 336f22db61c6c582b4ef019fcfa739e813668fe1 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Fri, 11 Mar 2011 10:38:55 -0800 Subject: rustc: Resolve upvars as necessary --- src/comp/middle/trans.rs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 936a12f3..47bd63c8 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -3338,8 +3338,15 @@ fn trans_path(@block_ctxt cx, &ast.path p, &option.t[ast.def] dopt, ret lval_mem(cx, cx.fcx.llargs.get(did)); } case (ast.def_local(?did)) { - check (cx.fcx.lllocals.contains_key(did)); - ret lval_mem(cx, cx.fcx.lllocals.get(did)); + alt (cx.fcx.lllocals.find(did)) { + case (none[ValueRef]) { + check (cx.fcx.llupvars.contains_key(did)); + ret lval_mem(cx, cx.fcx.llupvars.get(did)); + } + case (some[ValueRef](?llval)) { + ret lval_mem(cx, llval); + } + } } case (ast.def_binding(?did)) { check (cx.fcx.lllocals.contains_key(did)); -- cgit v1.2.3 From 37007a4d01c487a4fbd21306796a118c125a8906 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Fri, 11 Mar 2011 12:02:51 -0800 Subject: rustc: Populate the upvar environment when calling iterator bodies. Un-XFAIL test/run-pass/iter-range.rs. --- src/Makefile | 1 - src/comp/middle/trans.rs | 76 ++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 71 insertions(+), 6 deletions(-) diff --git a/src/Makefile b/src/Makefile index 21366b6b..ccb09990 100644 --- a/src/Makefile +++ b/src/Makefile @@ -454,7 +454,6 @@ TEST_XFAILS_RUSTC := $(addprefix test/run-pass/, \ foreach-put-structured.rs \ foreach-simple-outer-slot.rs \ generic-iter-frame.rs \ - iter-range.rs \ iter-ret.rs \ lazychan.rs \ lib-bitv.rs \ diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 47bd63c8..17ec85c7 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -3008,12 +3008,49 @@ fn trans_for_each(@block_ctxt cx, } auto upvars = collect_upvars(cx, body, decl_id); - if (_vec.len[ast.def_id](upvars) > 0u) { - cx.fcx.ccx.sess.unimpl("upvars in for each"); - fail; + auto upvar_count = _vec.len[ast.def_id](upvars); + + auto llbindingsptr; + if (upvar_count > 0u) { + // Gather up the upvars. + let vec[ValueRef] llbindings = vec(); + let vec[TypeRef] llbindingtys = vec(); + for (ast.def_id did in upvars) { + auto llbinding; + alt (cx.fcx.lllocals.find(did)) { + case (none[ValueRef]) { + llbinding = cx.fcx.llupvars.get(did); + } + case (some[ValueRef](?llval)) { llbinding = llval; } + } + llbindings += vec(llbinding); + llbindingtys += vec(val_ty(llbinding)); + } + + // Create an array of bindings and copy in aliases to the upvars. + llbindingsptr = cx.build.Alloca(T_struct(llbindingtys)); + auto i = 0u; + while (i < upvar_count) { + auto llbindingptr = cx.build.GEP(llbindingsptr, + vec(C_int(0), C_int(i as int))); + cx.build.Store(llbindings.(i), llbindingptr); + i += 1u; + } + } else { + // Null bindings. + llbindingsptr = C_null(T_ptr(T_i8())); } - auto env_ty = T_opaque_closure_ptr(cx.fcx.ccx.tn); + // Create an environment and populate it with the bindings. + auto llenvptrty = T_closure_ptr(cx.fcx.ccx.tn, T_ptr(T_nil()), + val_ty(llbindingsptr), 0u); + auto llenvptr = cx.build.Alloca(llvm.LLVMGetElementType(llenvptrty)); + + auto llbindingsptrptr = cx.build.GEP(llenvptr, + vec(C_int(0), + C_int(abi.box_rc_field_body), + C_int(2))); + cx.build.Store(llbindingsptr, llbindingsptrptr); // Step 2: Declare foreach body function. @@ -3041,7 +3078,30 @@ fn trans_for_each(@block_ctxt cx, auto fcx = new_fn_ctxt(cx.fcx.ccx, lliterbody); auto bcx = new_top_block_ctxt(fcx); - // FIXME: populate lllocals from llenv here. + // Populate the upvars from the environment. + auto llremoteenvptr = bcx.build.PointerCast(fcx.llenv, llenvptrty); + auto llremotebindingsptrptr = bcx.build.GEP(llremoteenvptr, + vec(C_int(0), C_int(abi.box_rc_field_body), C_int(2))); + auto llremotebindingsptr = bcx.build.Load(llremotebindingsptrptr); + + auto i = 0u; + while (i < upvar_count) { + auto upvar_id = upvars.(i); + auto llupvarptrptr = bcx.build.GEP(llremotebindingsptr, + vec(C_int(0), C_int(i as int))); + auto llupvarptr = bcx.build.Load(llupvarptrptr); + fcx.llupvars.insert(upvar_id, llupvarptr); + + i += 1u; + } + + // Treat the loop variable as an upvar as well. We copy it to an alloca + // as usual. + auto lllvar = llvm.LLVMGetParam(fcx.llfn, 3u); + auto lllvarptr = bcx.build.Alloca(val_ty(lllvar)); + bcx.build.Store(lllvar, lllvarptr); + fcx.llupvars.insert(decl_id, lllvarptr); + auto res = trans_block(bcx, body); res.bcx.build.RetVoid(); @@ -3059,6 +3119,12 @@ fn trans_for_each(@block_ctxt cx, C_int(abi.fn_field_code))); cx.build.Store(lliterbody, code_cell); + auto env_cell = cx.build.GEP(pair, vec(C_int(0), + C_int(abi.fn_field_box))); + auto llenvblobptr = cx.build.PointerCast(llenvptr, + T_opaque_closure_ptr(cx.fcx.ccx.tn)); + cx.build.Store(llenvblobptr, env_cell); + // log "lliterbody: " + val_str(cx.fcx.ccx.tn, lliterbody); ret trans_call(cx, f, some[ValueRef](cx.build.Load(pair)), -- cgit v1.2.3 From a93ab2e1b1015ca8b0546ab0e706a9e2c1403318 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Fri, 11 Mar 2011 12:05:49 -0800 Subject: Un-XFAIL test/run-pass/foreach-nested.rs and test/run-pass/foreach-nested-2.rs --- src/Makefile | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Makefile b/src/Makefile index ccb09990..daf53dd0 100644 --- a/src/Makefile +++ b/src/Makefile @@ -449,8 +449,6 @@ TEST_XFAILS_RUSTC := $(addprefix test/run-pass/, \ comm.rs \ constrained-type.rs \ destructor-ordering.rs \ - foreach-nested-2.rs \ - foreach-nested.rs \ foreach-put-structured.rs \ foreach-simple-outer-slot.rs \ generic-iter-frame.rs \ -- cgit v1.2.3 From 2ef57287229218466f87ea99c20f9a16f889e1c7 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Fri, 11 Mar 2011 12:11:24 -0800 Subject: rustc: Un-XFAIL generic-iter-frame.rs --- src/Makefile | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Makefile b/src/Makefile index daf53dd0..e8cf5d19 100644 --- a/src/Makefile +++ b/src/Makefile @@ -451,7 +451,6 @@ TEST_XFAILS_RUSTC := $(addprefix test/run-pass/, \ destructor-ordering.rs \ foreach-put-structured.rs \ foreach-simple-outer-slot.rs \ - generic-iter-frame.rs \ iter-ret.rs \ lazychan.rs \ lib-bitv.rs \ -- cgit v1.2.3 From fc7cbe31f9639a1d37baf4a35df9719ad155aa2c Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Fri, 11 Mar 2011 13:44:13 -0800 Subject: Switch rustboot from element-wise copying to take+drop+memcpy. Un-XFAIL size-and-align.rs for rustc. --- src/Makefile | 1 - src/boot/be/abi.ml | 2 +- src/boot/me/semant.ml | 4 +- src/boot/me/trans.ml | 172 ++++++++++++++++++++++---------------------------- 4 files changed, 77 insertions(+), 102 deletions(-) diff --git a/src/Makefile b/src/Makefile index e8cf5d19..b0e2e9c7 100644 --- a/src/Makefile +++ b/src/Makefile @@ -475,7 +475,6 @@ TEST_XFAILS_RUSTC := $(addprefix test/run-pass/, \ pred.rs \ preempt.rs \ rt-circular-buffer.rs \ - size-and-align.rs \ spawn-fn.rs \ spawn-module-qualified.rs \ spawn.rs \ diff --git a/src/boot/be/abi.ml b/src/boot/be/abi.ml index 89e308bf..023e1e1d 100644 --- a/src/boot/be/abi.ml +++ b/src/boot/be/abi.ml @@ -80,7 +80,7 @@ let general_code_alignment = 16;; let tydesc_field_first_param = 0;; let tydesc_field_size = 1;; let tydesc_field_align = 2;; -let tydesc_field_copy_glue = 3;; +let tydesc_field_take_glue = 3;; let tydesc_field_drop_glue = 4;; let tydesc_field_free_glue = 5;; let tydesc_field_sever_glue = 6;; diff --git a/src/boot/me/semant.ml b/src/boot/me/semant.ml index 3ce5eba2..3419bb34 100644 --- a/src/boot/me/semant.ml +++ b/src/boot/me/semant.ml @@ -20,7 +20,7 @@ type glue = | GLUE_yield | GLUE_exit_main_task | GLUE_exit_task - | GLUE_copy of Ast.ty (* One-level copy. *) + | GLUE_take of Ast.ty (* One-level refcounts++. *) | GLUE_drop of Ast.ty (* De-initialize local memory. *) | GLUE_free of Ast.ty (* Drop body + free() box ptr. *) | GLUE_sever of Ast.ty (* Null all box state slots. *) @@ -2776,7 +2776,7 @@ let glue_str (cx:ctxt) (g:glue) : string = | GLUE_yield -> "glue$yield" | GLUE_exit_main_task -> "glue$exit_main_task" | GLUE_exit_task -> "glue$exit_task" - | GLUE_copy ty -> "glue$copy$" ^ (ty_str cx ty) + | GLUE_take ty -> "glue$take$" ^ (ty_str cx ty) | GLUE_drop ty -> "glue$drop$" ^ (ty_str cx ty) | GLUE_free ty -> "glue$free$" ^ (ty_str cx ty) | GLUE_sever ty -> "glue$sever$" ^ (ty_str cx ty) diff --git a/src/boot/me/trans.ml b/src/boot/me/trans.ml index d6b470f9..17dbe3ea 100644 --- a/src/boot/me/trans.ml +++ b/src/boot/me/trans.ml @@ -1355,7 +1355,7 @@ let trans_visitor Asm.WORD (word_ty_mach, Asm.IMM 0L); Asm.WORD (word_ty_mach, Asm.IMM sz); Asm.WORD (word_ty_mach, Asm.IMM align); - fix (get_copy_glue t); + fix (get_take_glue t); fix (get_drop_glue t); begin match ty_mem_ctrl cx t with @@ -2022,34 +2022,18 @@ let trans_visitor get_typed_mem_glue g fty inner - and get_copy_glue + and get_take_glue (ty:Ast.ty) : fixup = let ty = get_genericized_ty ty in let arg_ty_params_alias = 0 in let arg_src_alias = 1 in - let arg_initflag = 2 in - let g = GLUE_copy ty in - let inner (out_ptr:Il.cell) (args:Il.cell) = - let dst = deref out_ptr in + let g = GLUE_take ty in + let inner (_:Il.cell) (args:Il.cell) = let ty_params = deref (get_element_ptr args arg_ty_params_alias) in let src = deref (get_element_ptr args arg_src_alias) in - - (* Translate copy code for the dst-initializing and - * dst-non-initializing cases and branch accordingly. *) - let initflag = get_element_ptr args arg_initflag in - let jmps = trans_compare_simple Il.JNE (Il.Cell initflag) one in - - trans_copy_ty_full true ty_params true dst ty src ty; - - let skip_noninit_jmp = mark() in - emit (Il.jmp Il.JMP Il.CodeNone); - List.iter patch jmps; - - trans_copy_ty_full true ty_params false dst ty src ty; - - patch skip_noninit_jmp; + trans_take_ty true ty_params src ty; in let ty_params_ptr = ty_params_covering ty in let fty = @@ -2186,17 +2170,23 @@ let trans_visitor get_tydesc_params ty_params_cell elt_td_ptr_cell in - let initflag = Il.Reg (force_to_reg one) in - + (* Take all *) copy_loop dst_buf src_buf (Il.Cell fill) (Il.Cell elt_sz) begin - fun dptr sptr -> + fun _ sptr -> trans_call_dynamic_glue elt_td_ptr_cell - Abi.tydesc_field_copy_glue - (Some (deref dptr)) - [| ty_params_ptr; sptr; initflag |] + Abi.tydesc_field_take_glue None + [| ty_params_ptr; sptr |] + None; + end; + + (* Memcpy all *) + copy_loop dst_buf src_buf (Il.Cell fill) one + begin + fun dptr sptr -> + mov (deref dptr) (Il.Cell (deref sptr)) end; (* Set the new vec's fill to the original vec's fill *) @@ -3734,17 +3724,58 @@ let trans_visitor end tys - and trans_copy_ty + and trans_take_ty + (force_inline:bool) (ty_params:Il.cell) - (initializing:bool) - (dst:Il.cell) (dst_ty:Ast.ty) - (src:Il.cell) (src_ty:Ast.ty) + (v:Il.cell) + (ty:Ast.ty) : unit = - trans_copy_ty_full - false ty_params initializing dst dst_ty src src_ty + let ty = strip_mutable_or_constrained_ty ty in + match ty_mem_ctrl cx ty with + MEM_rc_opaque | MEM_gc | MEM_rc_struct -> incr_refcount v + | _ -> + begin + match ty with + Ast.TY_fn _ + | Ast.TY_obj _ -> + let binding = + get_element_ptr v Abi.binding_field_bound_data + in + let null_jmp = null_check binding in + incr_refcount binding; + patch null_jmp - and trans_copy_ty_full - (force_inline:bool) + | Ast.TY_param (i, _) -> + aliasing false v + begin + fun v -> + let td = get_ty_param ty_params i in + let ty_params_ptr = get_tydesc_params ty_params td in + trans_call_dynamic_glue + td Abi.tydesc_field_take_glue + None + [| ty_params_ptr; v; |] + None + end + + | Ast.TY_rec _ + | Ast.TY_tag _ + | Ast.TY_tup _ -> + if force_inline + then + iter_ty_parts ty_params v ty + (trans_take_ty force_inline ty_params) + else + trans_call_static_glue + (code_fixup_to_ptr_operand (get_take_glue ty)) + None + [| alias ty_params; alias v; |] + None + + | _ -> () + end + + and trans_copy_ty (ty_params:Il.cell) (initializing:bool) (dst:Il.cell) (dst_ty:Ast.ty) @@ -3789,7 +3820,7 @@ let trans_visitor | _ -> (* Heavyweight copy: duplicate 1 level of the referent. *) anno "heavy"; - trans_copy_ty_heavy force_inline ty_params initializing + trans_copy_ty_heavy ty_params initializing dst dst_ty src src_ty end @@ -3821,7 +3852,6 @@ let trans_visitor *) and trans_copy_ty_heavy - (force_inline:bool) (ty_params:Il.cell) (initializing:bool) (dst:Il.cell) (dst_ty:Ast.ty) @@ -3863,68 +3893,14 @@ let trans_visitor (ty_sz cx ty))); mov dst (Il.Cell src) - | Ast.TY_param (i, _) -> - iflog - (fun _ -> annotate - (Printf.sprintf "copy_ty: parametric copy %#d" i)); - let initflag = Il.Reg (force_to_reg one) in - aliasing false src - begin - fun src -> - let td = get_ty_param ty_params i in - let ty_params_ptr = get_tydesc_params ty_params td in - trans_call_dynamic_glue - td Abi.tydesc_field_copy_glue - (Some dst) - [| ty_params_ptr; src; initflag |] - None - end - - | Ast.TY_fn _ - | Ast.TY_obj _ -> - begin - let src_item = - get_element_ptr src Abi.binding_field_dispatch - in - let dst_item = - get_element_ptr dst Abi.binding_field_dispatch - in - let src_binding = - get_element_ptr src Abi.binding_field_bound_data - in - let dst_binding = - get_element_ptr dst Abi.binding_field_bound_data - in - mov dst_item (Il.Cell src_item); - mov dst_binding zero; - let null_jmp = null_check src_binding in - (* Copy if we have a src binding. *) - (* FIXME (issue #58): this is completely wrong, call - * through to the binding's self-copy fptr. For now - * this only works by accident. - *) - trans_copy_ty ty_params true - dst_binding (Ast.TY_box Ast.TY_int) - src_binding (Ast.TY_box Ast.TY_int); - patch null_jmp - end - | _ -> - if force_inline || should_inline_structure_helpers ty - then - iter_ty_parts_full ty_params dst src ty - (fun dst src ty -> - trans_copy_ty ty_params initializing - dst ty src ty) - else - let initflag = Il.Reg (force_to_reg one) in - trans_call_static_glue - (code_fixup_to_ptr_operand (get_copy_glue ty)) - (Some dst) - [| alias ty_params; - alias src; - initflag |] - None + trans_take_ty false ty_params src ty; + if not initializing + then drop_ty ty_params dst ty; + let sz = ty_sz_with_ty_params ty_params ty in + copy_loop dst src sz (imm 1L) + (fun dptr sptr -> + mov (deref dptr) (Il.Cell (deref sptr))) and trans_copy -- cgit v1.2.3 From 5c21f039903311a9403b7fe7cfa0d2e455a7c4f0 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Fri, 11 Mar 2011 13:48:00 -0800 Subject: rustc: Un-XFAIL test/run-pass/foreach-simple-outer-slot.rs --- src/Makefile | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Makefile b/src/Makefile index b0e2e9c7..e06bb386 100644 --- a/src/Makefile +++ b/src/Makefile @@ -450,7 +450,6 @@ TEST_XFAILS_RUSTC := $(addprefix test/run-pass/, \ constrained-type.rs \ destructor-ordering.rs \ foreach-put-structured.rs \ - foreach-simple-outer-slot.rs \ iter-ret.rs \ lazychan.rs \ lib-bitv.rs \ -- cgit v1.2.3 From 28d51e3fd2cccdb9fefab71b476fd868a2363ac9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20=C3=81vila=20de=20Esp=C3=ADndola?= Date: Fri, 11 Mar 2011 17:10:11 -0500 Subject: Add support for indexing tags in blocks. --- src/comp/front/ast.rs | 8 +++++++- src/comp/front/parser.rs | 24 ++++++++++++++---------- src/comp/middle/resolve.rs | 44 ++++++++++++++++++++++++++++++++++++-------- 3 files changed, 57 insertions(+), 19 deletions(-) diff --git a/src/comp/front/ast.rs b/src/comp/front/ast.rs index 05daf5ee..c17eddee 100644 --- a/src/comp/front/ast.rs +++ b/src/comp/front/ast.rs @@ -66,9 +66,15 @@ type meta_item = spanned[meta_item_]; type meta_item_ = rec(ident name, str value); type block = spanned[block_]; +type block_index = hashmap[ident, block_index_entry]; +tag block_index_entry { + bie_item(@item); + bie_local(@local); + bie_tag_variant(@item /* tag item */, uint /* variant index */); +} type block_ = rec(vec[@stmt] stmts, option.t[@expr] expr, - hashmap[ident,uint] index); + hashmap[ident,block_index_entry] index); type variant_def = tup(def_id /* tag */, def_id /* variant */); diff --git a/src/comp/front/parser.rs b/src/comp/front/parser.rs index 2836b120..58cbac00 100644 --- a/src/comp/front/parser.rs +++ b/src/comp/front/parser.rs @@ -1478,31 +1478,36 @@ impure fn parse_source_stmt(parser p) -> @ast.stmt { } fn index_block(vec[@ast.stmt] stmts, option.t[@ast.expr] expr) -> ast.block_ { - auto index = new_str_hash[uint](); - auto u = 0u; + auto index = new_str_hash[ast.block_index_entry](); for (@ast.stmt s in stmts) { alt (s.node) { case (ast.stmt_decl(?d)) { alt (d.node) { case (ast.decl_local(?loc)) { - index.insert(loc.ident, u); + index.insert(loc.ident, ast.bie_local(loc)); } case (ast.decl_item(?it)) { alt (it.node) { case (ast.item_fn(?i, _, _, _, _)) { - index.insert(i, u); + index.insert(i, ast.bie_item(it)); } case (ast.item_mod(?i, _, _)) { - index.insert(i, u); + index.insert(i, ast.bie_item(it)); } case (ast.item_ty(?i, _, _, _, _)) { - index.insert(i, u); + index.insert(i, ast.bie_item(it)); } - case (ast.item_tag(?i, _, _, _)) { - index.insert(i, u); + case (ast.item_tag(?i, ?variants, _, _)) { + index.insert(i, ast.bie_item(it)); + let uint vid = 0u; + for (ast.variant v in variants) { + auto t = ast.bie_tag_variant(it, vid); + index.insert(v.name, t); + vid += 1u; + } } case (ast.item_obj(?i, _, _, _, _)) { - index.insert(i, u); + index.insert(i, ast.bie_item(it)); } } } @@ -1510,7 +1515,6 @@ fn index_block(vec[@ast.stmt] stmts, option.t[@ast.expr] expr) -> ast.block_ { } case (_) { /* fall through */ } } - u += 1u; } ret rec(stmts=stmts, expr=expr, index=index); } diff --git a/src/comp/middle/resolve.rs b/src/comp/middle/resolve.rs index 7102e442..1079489e 100644 --- a/src/comp/middle/resolve.rs +++ b/src/comp/middle/resolve.rs @@ -342,6 +342,40 @@ fn lookup_name_wrapped(&env e, ast.ident i) -> option.t[tup(@env, def_wrap)] { ret none[def_wrap]; } + fn found_tag(@ast.item item, uint variant_idx) -> def_wrap { + alt (item.node) { + case (ast.item_tag(_, ?variants, _, ?tid)) { + auto vid = variants.(variant_idx).id; + auto t = ast.def_variant(tid, vid); + ret def_wrap_other(t); + } + case (_) { + log "tag item not actually a tag"; + fail; + } + } + } + + fn check_block(ast.ident i, &ast.block_ b) -> option.t[def_wrap] { + alt (b.index.find(i)) { + case (some[ast.block_index_entry](?ix)) { + alt(ix) { + case (ast.bie_item(?it)) { + ret some(found_def_item(it)); + } + case (ast.bie_local(?l)) { + auto t = ast.def_local(l.id); + ret some(def_wrap_other(t)); + } + case (ast.bie_tag_variant(?item, ?variant_idx)) { + ret some(found_tag(item, variant_idx)); + } + } + } + case (_) { ret none[def_wrap]; } + } + } + fn in_scope(ast.ident i, &scope s) -> option.t[def_wrap] { alt (s) { @@ -368,7 +402,7 @@ fn lookup_name_wrapped(&env e, ast.ident i) -> option.t[tup(@env, def_wrap)] { } } } - case (ast.item_tag(_, _, ?ty_params, _)) { + case (ast.item_tag(_, ?variants, ?ty_params, ?tag_id)) { for (ast.ty_param tp in ty_params) { if (_str.eq(tp.ident, i)) { auto t = ast.def_ty_arg(tp.id); @@ -414,13 +448,7 @@ fn lookup_name_wrapped(&env e, ast.ident i) -> option.t[tup(@env, def_wrap)] { } case (scope_block(?b)) { - alt (b.node.index.find(i)) { - case (some[uint](?ix)) { - auto x = found_decl_stmt(b.node.stmts.(ix)); - ret some(x); - } - case (_) { /* fall through */ } - } + ret check_block(i, b.node); } case (scope_arm(?a)) { -- cgit v1.2.3 From 6392bd16811f20b71693df62909c465203d4f8d7 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Fri, 11 Mar 2011 14:28:49 -0800 Subject: rustc: Load structural loop variables in iterators. Un-XFAIL foreach-put-structured.rs. --- src/Makefile | 1 - src/comp/middle/trans.rs | 11 ++++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/Makefile b/src/Makefile index e06bb386..a407f206 100644 --- a/src/Makefile +++ b/src/Makefile @@ -449,7 +449,6 @@ TEST_XFAILS_RUSTC := $(addprefix test/run-pass/, \ comm.rs \ constrained-type.rs \ destructor-ordering.rs \ - foreach-put-structured.rs \ iter-ret.rs \ lazychan.rs \ lib-bitv.rs \ diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 17ec85c7..9d6e867e 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -4512,10 +4512,19 @@ fn trans_put(@block_ctxt cx, &option.t[@ast.expr] e) -> result { case (none[@ast.expr]) { } case (some[@ast.expr](?x)) { auto r = trans_expr(bcx, x); - llargs += r.val; + + auto llarg = r.val; bcx = r.bcx; + if (ty.type_is_structural(ty.expr_ty(x))) { + // Until here we've been treating structures by pointer; we + // are now passing it as an arg, so need to load it. + llarg = bcx.build.Load(llarg); + } + + llargs += llarg; } } + ret res(bcx, bcx.build.FastCall(llcallee, llargs)); } -- cgit v1.2.3 From 1feaf8ffb54ab2288d83a36391f94b437aa0ec35 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Fri, 11 Mar 2011 14:33:54 -0800 Subject: Re-XFAIL size-and-align.rs to put out burning tinderbox --- src/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Makefile b/src/Makefile index a407f206..4b449254 100644 --- a/src/Makefile +++ b/src/Makefile @@ -473,6 +473,7 @@ TEST_XFAILS_RUSTC := $(addprefix test/run-pass/, \ pred.rs \ preempt.rs \ rt-circular-buffer.rs \ + size-and-align.rs \ spawn-fn.rs \ spawn-module-qualified.rs \ spawn.rs \ -- cgit v1.2.3 From 74d891517be8f6299b0626c26400dd54dd1aac6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20=C3=81vila=20de=20Esp=C3=ADndola?= Date: Fri, 11 Mar 2011 17:29:53 -0500 Subject: reindex the block index. --- src/comp/front/ast.rs | 38 ++++++++++++++++++++++++++++++++++++++ src/comp/front/parser.rs | 36 +----------------------------------- src/comp/middle/fold.rs | 8 +++++--- 3 files changed, 44 insertions(+), 38 deletions(-) diff --git a/src/comp/front/ast.rs b/src/comp/front/ast.rs index c17eddee..b39f3d4c 100644 --- a/src/comp/front/ast.rs +++ b/src/comp/front/ast.rs @@ -435,6 +435,44 @@ fn index_native_view_item(native_mod_index index, @view_item it) { } } +fn index_stmt(block_index index, @stmt s) { + alt (s.node) { + case (ast.stmt_decl(?d)) { + alt (d.node) { + case (ast.decl_local(?loc)) { + index.insert(loc.ident, ast.bie_local(loc)); + } + case (ast.decl_item(?it)) { + alt (it.node) { + case (ast.item_fn(?i, _, _, _, _)) { + index.insert(i, ast.bie_item(it)); + } + case (ast.item_mod(?i, _, _)) { + index.insert(i, ast.bie_item(it)); + } + case (ast.item_ty(?i, _, _, _, _)) { + index.insert(i, ast.bie_item(it)); + } + case (ast.item_tag(?i, ?variants, _, _)) { + index.insert(i, ast.bie_item(it)); + let uint vid = 0u; + for (ast.variant v in variants) { + auto t = ast.bie_tag_variant(it, vid); + index.insert(v.name, t); + vid += 1u; + } + } + case (ast.item_obj(?i, _, _, _, _)) { + index.insert(i, ast.bie_item(it)); + } + } + } + } + } + case (_) { /* fall through */ } + } +} + fn is_call_expr(@expr e) -> bool { alt (e.node) { case (expr_call(_, _, _)) { diff --git a/src/comp/front/parser.rs b/src/comp/front/parser.rs index 58cbac00..cdd65539 100644 --- a/src/comp/front/parser.rs +++ b/src/comp/front/parser.rs @@ -1480,41 +1480,7 @@ impure fn parse_source_stmt(parser p) -> @ast.stmt { fn index_block(vec[@ast.stmt] stmts, option.t[@ast.expr] expr) -> ast.block_ { auto index = new_str_hash[ast.block_index_entry](); for (@ast.stmt s in stmts) { - alt (s.node) { - case (ast.stmt_decl(?d)) { - alt (d.node) { - case (ast.decl_local(?loc)) { - index.insert(loc.ident, ast.bie_local(loc)); - } - case (ast.decl_item(?it)) { - alt (it.node) { - case (ast.item_fn(?i, _, _, _, _)) { - index.insert(i, ast.bie_item(it)); - } - case (ast.item_mod(?i, _, _)) { - index.insert(i, ast.bie_item(it)); - } - case (ast.item_ty(?i, _, _, _, _)) { - index.insert(i, ast.bie_item(it)); - } - case (ast.item_tag(?i, ?variants, _, _)) { - index.insert(i, ast.bie_item(it)); - let uint vid = 0u; - for (ast.variant v in variants) { - auto t = ast.bie_tag_variant(it, vid); - index.insert(v.name, t); - vid += 1u; - } - } - case (ast.item_obj(?i, _, _, _, _)) { - index.insert(i, ast.bie_item(it)); - } - } - } - } - } - case (_) { /* fall through */ } - } + ast.index_stmt(index, s); } ret rec(stmts=stmts, expr=expr, index=index); } diff --git a/src/comp/middle/fold.rs b/src/comp/middle/fold.rs index d08b979a..37ae2c23 100644 --- a/src/comp/middle/fold.rs +++ b/src/comp/middle/fold.rs @@ -734,6 +734,7 @@ fn fold_stmt[ENV](&ENV env, ast_fold[ENV] fld, &@stmt s) -> @stmt { fn fold_block[ENV](&ENV env, ast_fold[ENV] fld, &block blk) -> block { + auto index = new_str_hash[ast.block_index_entry](); let ENV env_ = fld.update_env_for_block(env, blk); if (!fld.keep_going(env_)) { @@ -742,7 +743,9 @@ fn fold_block[ENV](&ENV env, ast_fold[ENV] fld, &block blk) -> block { let vec[@ast.stmt] stmts = vec(); for (@ast.stmt s in blk.node.stmts) { - append[@ast.stmt](stmts, fold_stmt[ENV](env_, fld, s)); + auto new_stmt = fold_stmt[ENV](env_, fld, s); + append[@ast.stmt](stmts, new_stmt); + ast.index_stmt(index, new_stmt); } auto expr = none[@ast.expr]; @@ -755,8 +758,7 @@ fn fold_block[ENV](&ENV env, ast_fold[ENV] fld, &block blk) -> block { } } - // FIXME: should we reindex? - ret respan(blk.span, rec(stmts=stmts, expr=expr, index=blk.node.index)); + ret respan(blk.span, rec(stmts=stmts, expr=expr, index=index)); } fn fold_arm[ENV](&ENV env, ast_fold[ENV] fld, &arm a) -> arm { -- cgit v1.2.3 From 9b3db0ed445de1b513742770420ba4b60a025219 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Fri, 11 Mar 2011 15:35:20 -0800 Subject: rustc: Add some stub metadata to each crate --- src/comp/back/x86.rs | 10 ++++++++++ src/comp/middle/metadata.rs | 29 +++++++++++++++++++++++++++++ src/comp/middle/trans.rs | 3 +++ src/comp/rustc.rc | 2 ++ 4 files changed, 44 insertions(+) create mode 100644 src/comp/middle/metadata.rs diff --git a/src/comp/back/x86.rs b/src/comp/back/x86.rs index b9ba24c6..0ed79db4 100644 --- a/src/comp/back/x86.rs +++ b/src/comp/back/x86.rs @@ -273,6 +273,16 @@ fn get_module_asm() -> str { ret _str.connect(glues, "\n\n"); } +fn get_meta_sect_name() -> str { + if (_str.eq(target_os(), "macos")) { + ret "__DATA,__note.rustc"; + } + if (_str.eq(target_os(), "win32")) { + ret ".note.rustc"; + } + ret ".note.rustc"; +} + fn get_data_layout() -> str { if (_str.eq(target_os(), "macos")) { ret "e-p:32:32-f64:32:64-i64:32:64-f80:128:128-n8:16:32"; diff --git a/src/comp/middle/metadata.rs b/src/comp/middle/metadata.rs new file mode 100644 index 00000000..433d7147 --- /dev/null +++ b/src/comp/middle/metadata.rs @@ -0,0 +1,29 @@ +import std._str; +import front.ast; +import middle.trans; +import back.x86; + +import lib.llvm.llvm; +import lib.llvm.llvm.ValueRef; +import lib.llvm.False; + +// Returns a Plain Old LLVM String. +fn C_postr(str s) -> ValueRef { + ret llvm.LLVMConstString(_str.buf(s), _str.byte_len(s), False); +} + +fn collect_meta_directives(@trans.crate_ctxt cx, @ast.crate crate) + -> ValueRef { + ret C_postr("Hello world!"); // TODO +} + +fn write_metadata(@trans.crate_ctxt cx, @ast.crate crate) { + auto llmeta = collect_meta_directives(cx, crate); + + auto llconst = trans.C_struct(vec(llmeta)); + auto llglobal = llvm.LLVMAddGlobal(cx.llmod, trans.val_ty(llconst), + _str.buf("rust_metadata")); + llvm.LLVMSetInitializer(llglobal, llconst); + llvm.LLVMSetSection(llglobal, _str.buf(x86.get_meta_sect_name())); +} + diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 9d6e867e..64850542 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -6192,6 +6192,9 @@ fn trans_crate(session.session sess, @ast.crate crate, str output, trans_main_fn(cx, cx.crate_ptr); } + // Translate the metadata. + middle.metadata.write_metadata(cx, crate); + check_module(llmod); llvm.LLVMWriteBitcodeToFile(llmod, _str.buf(output)); diff --git a/src/comp/rustc.rc b/src/comp/rustc.rc index c7d3ff6b..006aca62 100644 --- a/src/comp/rustc.rc +++ b/src/comp/rustc.rc @@ -14,6 +14,7 @@ mod front { mod middle { mod fold; + mod metadata; mod resolve; mod trans; mod ty; @@ -40,6 +41,7 @@ mod util { } auth driver.rustc.main = impure; +auth middle.metadata = unsafe; auth middle.trans = unsafe; auth middle.trans.copy_args_to_allocas = impure; auth middle.trans.trans_block = impure; -- cgit v1.2.3 From d24acf733a6fcc22ec53c241311240b950db0b11 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Fri, 11 Mar 2011 15:49:03 -0800 Subject: Remove redundant entry from Makefile --- src/Makefile | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Makefile b/src/Makefile index 4b449254..dc6a9b7c 100644 --- a/src/Makefile +++ b/src/Makefile @@ -300,7 +300,6 @@ RUNTIME_HDR := rt/globals.h \ RUNTIME_INCS := -Irt/isaac -Irt/uthash RUNTIME_OBJS := $(RUNTIME_CS:.cpp=.o) -RUNTIME_LIBS := $(CFG_RUNTIME_LIBS) STDLIB_CRATE := lib/std.rc STDLIB_INPUTS := $(wildcard lib/*.rc lib/*.rs lib/*/*.rs) -- cgit v1.2.3 From ec7e84ae0d9d04c52a8456c16dd846efe6390340 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Fri, 11 Mar 2011 15:49:48 -0800 Subject: Preserve crate directives in the parsed crate. --- src/comp/front/ast.rs | 3 ++- src/comp/front/parser.rs | 11 +++++------ src/comp/middle/fold.rs | 14 ++++++++++---- 3 files changed, 17 insertions(+), 11 deletions(-) diff --git a/src/comp/front/ast.rs b/src/comp/front/ast.rs index b39f3d4c..5999388e 100644 --- a/src/comp/front/ast.rs +++ b/src/comp/front/ast.rs @@ -44,7 +44,8 @@ tag def { } type crate = spanned[crate_]; -type crate_ = rec(_mod module); +type crate_ = rec(vec[@crate_directive] directives, + _mod module); tag crate_directive_ { cdir_expr(@expr); diff --git a/src/comp/front/parser.rs b/src/comp/front/parser.rs index cdd65539..45cec0c0 100644 --- a/src/comp/front/parser.rs +++ b/src/comp/front/parser.rs @@ -2244,7 +2244,9 @@ impure fn parse_crate_from_source_file(parser p) -> @ast.crate { auto lo = p.get_span(); auto hi = lo; auto m = parse_mod_items(p, token.EOF); - ret @spanned(lo, hi, rec(module=m)); + let vec[@ast.crate_directive] cdirs = vec(); + ret @spanned(lo, hi, rec(directives=cdirs, + module=m)); } // Logic for parsing crate files (.rc) @@ -2259,8 +2261,6 @@ impure fn parse_crate_directive(parser p) -> ast.crate_directive auto hi = lo; alt (p.peek()) { case (token.AUTH) { - // FIXME: currently dropping auth clauses on the floor, - // as there is no effect-checking pass. p.bump(); auto n = parse_path(p, GREEDY); expect(p, token.EQ); @@ -2271,8 +2271,6 @@ impure fn parse_crate_directive(parser p) -> ast.crate_directive } case (token.META) { - // FIXME: currently dropping meta clauses on the floor, - // as there is no crate metadata system p.bump(); auto mis = parse_meta(p); hi = p.get_span(); @@ -2381,7 +2379,8 @@ impure fn parse_crate_from_crate_file(parser p) -> @ast.crate { cdirs, prefix); hi = p.get_span(); expect(p, token.EOF); - ret @spanned(lo, hi, rec(module=m)); + ret @spanned(lo, hi, rec(directives=cdirs, + module=m)); } diff --git a/src/comp/middle/fold.rs b/src/comp/middle/fold.rs index 37ae2c23..17a2a2ca 100644 --- a/src/comp/middle/fold.rs +++ b/src/comp/middle/fold.rs @@ -273,6 +273,7 @@ type ast_fold[ENV] = (fn(&ENV e, &ast.native_mod m) -> ast.native_mod) fold_native_mod, (fn(&ENV e, &span sp, + vec[@ast.crate_directive] cdirs, &ast._mod m) -> @ast.crate) fold_crate, (fn(&ENV e, @@ -991,9 +992,12 @@ fn fold_native_mod[ENV](&ENV e, ast_fold[ENV] fld, } fn fold_crate[ENV](&ENV env, ast_fold[ENV] fld, @ast.crate c) -> @ast.crate { + // FIXME: possibly fold the directives so you process any expressions + // within them? Not clear. After front/eval.rs, nothing else should look + // at crate directives. let ENV env_ = fld.update_env_for_crate(env, c); let ast._mod m = fold_mod[ENV](env_, fld, c.node.module); - ret fld.fold_crate(env_, c.span, m); + ret fld.fold_crate(env_, c.span, c.node.directives, m); } //// Identity folds. @@ -1381,8 +1385,10 @@ fn identity_fold_native_mod[ENV](&ENV e, ret m; } -fn identity_fold_crate[ENV](&ENV e, &span sp, &ast._mod m) -> @ast.crate { - ret @respan(sp, rec(module=m)); +fn identity_fold_crate[ENV](&ENV e, &span sp, + vec[@ast.crate_directive] cdirs, + &ast._mod m) -> @ast.crate { + ret @respan(sp, rec(directives=cdirs, module=m)); } fn identity_fold_obj[ENV](&ENV e, @@ -1537,7 +1543,7 @@ fn new_identity_fold[ENV]() -> ast_fold[ENV] { fold_fn_decl = bind identity_fold_fn_decl[ENV](_,_,_,_), fold_mod = bind identity_fold_mod[ENV](_,_), fold_native_mod = bind identity_fold_native_mod[ENV](_,_), - fold_crate = bind identity_fold_crate[ENV](_,_,_), + fold_crate = bind identity_fold_crate[ENV](_,_,_,_), fold_obj = bind identity_fold_obj[ENV](_,_,_,_), update_env_for_crate = bind identity_update_env_for_crate[ENV](_,_), -- cgit v1.2.3 From a8fbb53d643eada0264aae902adc7f6f453c53b0 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Fri, 11 Mar 2011 16:16:35 -0800 Subject: Include glob in crate depfile deps, to handle file-add events with cached depfiles. Closes #269. --- src/Makefile | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Makefile b/src/Makefile index dc6a9b7c..bceef7ff 100644 --- a/src/Makefile +++ b/src/Makefile @@ -814,9 +814,15 @@ RUSTBOOT_PROBE := $(wildcard $(CFG_BOOT)) ifneq ($(RUSTBOOT_PROBE),) CFG_INFO := $(info cfg: using built $(CFG_BOOT) for rust deps) STDLIB_DEPFILE := $(CFG_STDLIB).d +RUSTC_DEPFILE := $(CFG_RUSTC).d CRATE_DEPFILES := $(ALL_TEST_CRATES:%.rc=%.d) $(STDLIB_DEPFILE) -$(STDLIB_DEPFILE): $(STDLIB_CRATE) $(MKFILES) $(CFG_BOOT) +$(STDLIB_DEPFILE): $(STDLIB_CRATE) $(MKFILES) $(CFG_BOOT) $(STDLIB_INPUTS) + @$(call CFG_ECHO, dep: $<) + $(BOOT) -shared -rdeps $< $(CFG_PATH_MUNGE) >$@.tmp \ + && mv $@.tmp $@ + +$(RUSTC_DEPFILE): $(STDLIB_CRATE) $(MKFILES) $(CFG_BOOT) $(COMPILER_INPUTS) @$(call CFG_ECHO, dep: $<) $(BOOT) -shared -rdeps $< $(CFG_PATH_MUNGE) >$@.tmp \ && mv $@.tmp $@ -- cgit v1.2.3 From d34e1ff89e067a57921091fbdffe8c13fa38341c Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Fri, 11 Mar 2011 18:02:09 -0800 Subject: rustc: Add a binding to LLVM's object file reader. Until it's sent upstream, add an explicit "support" library for our LLVM extensions. --- src/Makefile | 34 +++++++++++++++-- src/support/Object.cpp | 55 +++++++++++++++++++++++++++ src/support/README | 3 ++ src/support/include/llvm-c/Object.h | 75 +++++++++++++++++++++++++++++++++++++ 4 files changed, 164 insertions(+), 3 deletions(-) create mode 100644 src/support/Object.cpp create mode 100644 src/support/README create mode 100644 src/support/include/llvm-c/Object.h diff --git a/src/Makefile b/src/Makefile index bceef7ff..dc6a78a5 100644 --- a/src/Makefile +++ b/src/Makefile @@ -34,6 +34,7 @@ DSYMUTIL := true ifeq ($(CFG_OSTYPE), FreeBSD) CFG_RUNTIME := librustrt.so + CFG_SUPPORT := librustsupport.so CFG_STDLIB := libstd.so CFG_GCC_CFLAGS += -fPIC -march=i686 -I/usr/local/include CFG_GCC_LINK_FLAGS += -shared -fPIC -lpthread -lrt @@ -47,6 +48,7 @@ endif ifeq ($(CFG_OSTYPE), Linux) CFG_RUNTIME := librustrt.so + CFG_SUPPORT := librustsupport.so CFG_STDLIB := libstd.so CFG_GCC_CFLAGS += -fPIC -march=i686 CFG_GCC_LINK_FLAGS += -shared -fPIC -ldl -lpthread -lrt @@ -60,6 +62,7 @@ endif ifeq ($(CFG_OSTYPE), Darwin) CFG_RUNTIME := librustrt.dylib + CFG_SUPPORT := librustsupport.dylib CFG_STDLIB := libstd.dylib CFG_UNIXY := 1 CFG_GCC_LINK_FLAGS += -dynamiclib -lpthread @@ -85,6 +88,7 @@ ifdef CFG_WINDOWSY CFG_NATIVE := 1 endif CFG_RUNTIME := rustrt.dll + CFG_SUPPORT := rustsupport.dll CFG_STDLIB := std.dll CFG_EXE_SUFFIX := .exe CFG_BOOT := ./rustboot.exe @@ -107,6 +111,7 @@ ifdef CFG_UNIXY CFG_GCC_CROSS := i586-mingw32msvc- CFG_BOOT_FLAGS += -t win32-x86-pe CFG_RUNTIME := rustrt.dll + CFG_SUPPORT := rustsupport.dll CFG_STDLIB := std.dll CFG_RUSTC := ./rustc.exe ifdef CFG_VALGRIND @@ -179,7 +184,7 @@ endif ifneq ($(CFG_LLVM_CONFIG),) CFG_LLVM_VERSION := $(shell $(CFG_LLVM_CONFIG) --version) $(info cfg: found llvm-config at $(CFG_LLVM_CONFIG)) - CFG_LLVM_ALLOWED_VERSIONS := 2.8svn 2.8 2.9svn + CFG_LLVM_ALLOWED_VERSIONS := 2.8svn 2.8 2.9svn 3.0svn ifneq ($(findstring $(CFG_LLVM_VERSION),$(CFG_LLVM_ALLOWED_VERSIONS)),) $(info cfg: using LLVM version $(CFG_LLVM_VERSION)) else @@ -193,6 +198,10 @@ ifdef CFG_LLVM_CONFIG LLC := "$(shell $(CFG_LLVM_CONFIG) --bindir)/llc" CFG_LLC_CFLAGS := -march=x86 LLVM-DIS := "$(shell $(CFG_LLVM_CONFIG) --bindir)/llvm-dis" + CFG_LLVM_INCDIR := $(shell $(CFG_LLVM_CONFIG) --includedir) + CFG_LLVM_CXXFLAGS := $(shell $(CFG_LLVM_CONFIG) --cxxflags) + CFG_LLVM_LDFLAGS := $(shell $(CFG_LLVM_CONFIG) --ldflags) + CFG_LLVM_LIBS := $(shell $(CFG_LLVM_CONFIG) --libs) endif MKFILES := Makefile @@ -301,6 +310,14 @@ RUNTIME_HDR := rt/globals.h \ RUNTIME_INCS := -Irt/isaac -Irt/uthash RUNTIME_OBJS := $(RUNTIME_CS:.cpp=.o) +SUPPORT_CS := support/Object.cpp + +SUPPORT_HDR := support/include/llvm-c/Object.h + +SUPPORT_INCS := -iquote $(CFG_LLVM_INCDIR) +SUPPORT_OBJS := $(SUPPORT_CS:.cpp=.o) +SUPPORT_LIBS := $(CFG_LLVM_LDFLAGS) $(CFG_LLVM_LIBS) + STDLIB_CRATE := lib/std.rc STDLIB_INPUTS := $(wildcard lib/*.rc lib/*.rs lib/*/*.rs) COMPILER_CRATE := comp/rustc.rc @@ -321,14 +338,24 @@ $(CFG_RUNTIME): $(RUNTIME_OBJS) $(MKFILES) $(RUNTIME_HDR) @$(call CFG_ECHO, compile: $<) $(CFG_QUIET)$(call CFG_LINK_C, $@) $(RUNTIME_OBJS) +$(CFG_SUPPORT): $(SUPPORT_OBJS) $(MKFILES) $(SUPPORT_HDR) + @$(call CFG_ECHO, compile: $<) + $(CFG_QUIET)$(call CFG_LINK_C, $@ $(CFG_LLVM_LDFLAGS) $(CFG_LLVM_LIBS)) \ + $(SUPPORT_OBJS) + $(CFG_STDLIB): $(STDLIB_CRATE) $(CFG_BOOT) $(MKFILES) @$(call CFG_ECHO, compile: $<) $(BOOT) -shared -o $@ $(STDLIB_CRATE) -%.o: %.cpp $(MKFILES) +rt/%.o: rt/%.cpp $(MKFILES) @$(call CFG_ECHO, compile: $<) $(CFG_QUIET)$(call CFG_COMPILE_C, $@, $(RUNTIME_INCS)) $< +support/%.o: support/%.cpp $(MKFILES) + @$(call CFG_ECHO, compile: $<) + $(CFG_QUIET)$(call CFG_COMPILE_C, $@, $(CFG_LLVM_CXXFLAGS) \ + $(SUPPORT_INCS)) $< + ifdef CFG_NATIVE $(CFG_BOOT): $(BOOT_CMXS) $(MKFILES) @$(call CFG_ECHO, compile: $<) @@ -359,7 +386,8 @@ endif # Main compiler targets and rules ###################################################################### -$(CFG_RUSTC): $(COMPILER_INPUTS) $(CFG_BOOT) $(CFG_RUNTIME) $(CFG_STDLIB) +$(CFG_RUSTC): $(COMPILER_INPUTS) $(CFG_BOOT) $(CFG_RUNTIME) $(CFG_STDLIB) \ + $(CFG_SUPPORT) @$(call CFG_ECHO, compile: $<) $(BOOT) -minimal -o $@ $< $(CFG_QUIET)chmod 0755 $@ diff --git a/src/support/Object.cpp b/src/support/Object.cpp new file mode 100644 index 00000000..f390870f --- /dev/null +++ b/src/support/Object.cpp @@ -0,0 +1,55 @@ +//===- Object.cpp - C bindings to the object file library--------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the C bindings to the file-format-independent object +// library. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Object/ObjectFile.h" +#include "llvm-c/Object.h" + +using namespace llvm; +using namespace object; + +LLVMObjectFileRef LLVMCreateObjectFile(const char *ObjectPath) { + StringRef SR(ObjectPath); + return wrap(ObjectFile::createObjectFile(SR)); +} + +void LLVMDisposeObjectFile(LLVMObjectFileRef ObjectFile) { + delete unwrap(ObjectFile); +} + +LLVMSectionIteratorRef LLVMGetSections(LLVMObjectFileRef ObjectFile) { + ObjectFile::section_iterator SI = unwrap(ObjectFile)->begin_sections(); + return wrap(new ObjectFile::section_iterator(SI)); +} + +void LLVMDisposeSectionIterator(LLVMSectionIteratorRef SI) { + delete unwrap(SI); +} + +void LLVMMoveToNextSection(LLVMSectionIteratorRef SI) { + ObjectFile::section_iterator UnwrappedSI = *unwrap(SI); + ++UnwrappedSI; +} + +const char *LLVMGetSectionName(LLVMSectionIteratorRef SI) { + return (*unwrap(SI))->getName().data(); +} + +uint64_t LLVMGetSectionSize(LLVMSectionIteratorRef SI) { + return (*unwrap(SI))->getSize(); +} + +const char *LLVMGetSectionContents(LLVMSectionIteratorRef SI) { + return (*unwrap(SI))->getContents().data(); +} + diff --git a/src/support/README b/src/support/README new file mode 100644 index 00000000..31495f22 --- /dev/null +++ b/src/support/README @@ -0,0 +1,3 @@ +This directory currently contains some LLVM support code. This will generally +be sent upstream to LLVM in time; for now it lives here. + diff --git a/src/support/include/llvm-c/Object.h b/src/support/include/llvm-c/Object.h new file mode 100644 index 00000000..a65a2352 --- /dev/null +++ b/src/support/include/llvm-c/Object.h @@ -0,0 +1,75 @@ +/*===-- llvm-c/Object.h - Object Lib C Iface --------------------*- C++ -*-===*/ +/* */ +/* The LLVM Compiler Infrastructure */ +/* */ +/* This file is distributed under the University of Illinois Open Source */ +/* License. See LICENSE.TXT for details. */ +/* */ +/*===----------------------------------------------------------------------===*/ +/* */ +/* This header declares the C interface to libLLVMObject.a, which */ +/* implements object file reading and writing. */ +/* */ +/* Many exotic languages can interoperate with C code but have a harder time */ +/* with C++ due to name mangling. So in addition to C, this interface enables */ +/* tools written in such languages. */ +/* */ +/*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_C_OBJECT_H +#define LLVM_C_OBJECT_H + +#include "llvm-c/Core.h" +#include "llvm/Config/llvm-config.h" + +#ifdef __cplusplus +#include "llvm/Object/ObjectFile.h" + +extern "C" { +#endif + + +typedef struct LLVMOpaqueObjectFile *LLVMObjectFileRef; + +typedef struct LLVMOpaqueSectionIterator *LLVMSectionIteratorRef; + +LLVMObjectFileRef LLVMCreateObjectFile(const char *ObjectPath); +void LLVMDisposeObjectFile(LLVMObjectFileRef ObjectFile); + +LLVMSectionIteratorRef LLVMGetSections(LLVMObjectFileRef ObjectFile); +void LLVMDisposeSectionIterator(LLVMSectionIteratorRef SI); +void LLVMMoveToNextSection(LLVMSectionIteratorRef SI); +const char *LLVMGetSectionName(LLVMSectionIteratorRef SI); +uint64_t LLVMGetSectionSize(LLVMSectionIteratorRef SI); +const char *LLVMGetSectionContents(LLVMSectionIteratorRef SI); + + +#ifdef __cplusplus +} + +namespace llvm { + namespace object { + inline ObjectFile *unwrap(LLVMObjectFileRef OF) { + return reinterpret_cast(OF); + } + + inline LLVMObjectFileRef wrap(const ObjectFile *OF) { + return reinterpret_cast(const_cast(OF)); + } + + inline ObjectFile::section_iterator *unwrap(LLVMSectionIteratorRef SI) { + return reinterpret_cast(SI); + } + + inline LLVMSectionIteratorRef + wrap(const ObjectFile::section_iterator *SI) { + return reinterpret_cast + (const_cast(SI)); + } + } +} + +#endif /* defined(__cplusplus) */ + +#endif + -- cgit v1.2.3 From 57c2fa9d11f45618e25798eb2065c1b14b847264 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Fri, 11 Mar 2011 18:17:57 -0800 Subject: Rename libsupport to librustllvm --- src/Makefile | 16 ++++---- src/llvmext/Object.cpp | 55 +++++++++++++++++++++++++++ src/llvmext/README | 3 ++ src/llvmext/include/llvm-c/Object.h | 75 +++++++++++++++++++++++++++++++++++++ src/support/Object.cpp | 55 --------------------------- src/support/README | 3 -- src/support/include/llvm-c/Object.h | 75 ------------------------------------- 7 files changed, 141 insertions(+), 141 deletions(-) create mode 100644 src/llvmext/Object.cpp create mode 100644 src/llvmext/README create mode 100644 src/llvmext/include/llvm-c/Object.h delete mode 100644 src/support/Object.cpp delete mode 100644 src/support/README delete mode 100644 src/support/include/llvm-c/Object.h diff --git a/src/Makefile b/src/Makefile index dc6a78a5..47365a7c 100644 --- a/src/Makefile +++ b/src/Makefile @@ -34,7 +34,7 @@ DSYMUTIL := true ifeq ($(CFG_OSTYPE), FreeBSD) CFG_RUNTIME := librustrt.so - CFG_SUPPORT := librustsupport.so + CFG_SUPPORT := librustllvm.so CFG_STDLIB := libstd.so CFG_GCC_CFLAGS += -fPIC -march=i686 -I/usr/local/include CFG_GCC_LINK_FLAGS += -shared -fPIC -lpthread -lrt @@ -48,7 +48,7 @@ endif ifeq ($(CFG_OSTYPE), Linux) CFG_RUNTIME := librustrt.so - CFG_SUPPORT := librustsupport.so + CFG_SUPPORT := librustllvm.so CFG_STDLIB := libstd.so CFG_GCC_CFLAGS += -fPIC -march=i686 CFG_GCC_LINK_FLAGS += -shared -fPIC -ldl -lpthread -lrt @@ -62,7 +62,7 @@ endif ifeq ($(CFG_OSTYPE), Darwin) CFG_RUNTIME := librustrt.dylib - CFG_SUPPORT := librustsupport.dylib + CFG_SUPPORT := librustllvm.dylib CFG_STDLIB := libstd.dylib CFG_UNIXY := 1 CFG_GCC_LINK_FLAGS += -dynamiclib -lpthread @@ -88,7 +88,7 @@ ifdef CFG_WINDOWSY CFG_NATIVE := 1 endif CFG_RUNTIME := rustrt.dll - CFG_SUPPORT := rustsupport.dll + CFG_SUPPORT := rustllvm.dll CFG_STDLIB := std.dll CFG_EXE_SUFFIX := .exe CFG_BOOT := ./rustboot.exe @@ -111,7 +111,7 @@ ifdef CFG_UNIXY CFG_GCC_CROSS := i586-mingw32msvc- CFG_BOOT_FLAGS += -t win32-x86-pe CFG_RUNTIME := rustrt.dll - CFG_SUPPORT := rustsupport.dll + CFG_SUPPORT := rustllvm.dll CFG_STDLIB := std.dll CFG_RUSTC := ./rustc.exe ifdef CFG_VALGRIND @@ -310,9 +310,9 @@ RUNTIME_HDR := rt/globals.h \ RUNTIME_INCS := -Irt/isaac -Irt/uthash RUNTIME_OBJS := $(RUNTIME_CS:.cpp=.o) -SUPPORT_CS := support/Object.cpp +SUPPORT_CS := llvmext/Object.cpp -SUPPORT_HDR := support/include/llvm-c/Object.h +SUPPORT_HDR := llvmext/include/llvm-c/Object.h SUPPORT_INCS := -iquote $(CFG_LLVM_INCDIR) SUPPORT_OBJS := $(SUPPORT_CS:.cpp=.o) @@ -351,7 +351,7 @@ rt/%.o: rt/%.cpp $(MKFILES) @$(call CFG_ECHO, compile: $<) $(CFG_QUIET)$(call CFG_COMPILE_C, $@, $(RUNTIME_INCS)) $< -support/%.o: support/%.cpp $(MKFILES) +llvmext/%.o: llvmext/%.cpp $(MKFILES) @$(call CFG_ECHO, compile: $<) $(CFG_QUIET)$(call CFG_COMPILE_C, $@, $(CFG_LLVM_CXXFLAGS) \ $(SUPPORT_INCS)) $< diff --git a/src/llvmext/Object.cpp b/src/llvmext/Object.cpp new file mode 100644 index 00000000..f390870f --- /dev/null +++ b/src/llvmext/Object.cpp @@ -0,0 +1,55 @@ +//===- Object.cpp - C bindings to the object file library--------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the C bindings to the file-format-independent object +// library. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Object/ObjectFile.h" +#include "llvm-c/Object.h" + +using namespace llvm; +using namespace object; + +LLVMObjectFileRef LLVMCreateObjectFile(const char *ObjectPath) { + StringRef SR(ObjectPath); + return wrap(ObjectFile::createObjectFile(SR)); +} + +void LLVMDisposeObjectFile(LLVMObjectFileRef ObjectFile) { + delete unwrap(ObjectFile); +} + +LLVMSectionIteratorRef LLVMGetSections(LLVMObjectFileRef ObjectFile) { + ObjectFile::section_iterator SI = unwrap(ObjectFile)->begin_sections(); + return wrap(new ObjectFile::section_iterator(SI)); +} + +void LLVMDisposeSectionIterator(LLVMSectionIteratorRef SI) { + delete unwrap(SI); +} + +void LLVMMoveToNextSection(LLVMSectionIteratorRef SI) { + ObjectFile::section_iterator UnwrappedSI = *unwrap(SI); + ++UnwrappedSI; +} + +const char *LLVMGetSectionName(LLVMSectionIteratorRef SI) { + return (*unwrap(SI))->getName().data(); +} + +uint64_t LLVMGetSectionSize(LLVMSectionIteratorRef SI) { + return (*unwrap(SI))->getSize(); +} + +const char *LLVMGetSectionContents(LLVMSectionIteratorRef SI) { + return (*unwrap(SI))->getContents().data(); +} + diff --git a/src/llvmext/README b/src/llvmext/README new file mode 100644 index 00000000..31495f22 --- /dev/null +++ b/src/llvmext/README @@ -0,0 +1,3 @@ +This directory currently contains some LLVM support code. This will generally +be sent upstream to LLVM in time; for now it lives here. + diff --git a/src/llvmext/include/llvm-c/Object.h b/src/llvmext/include/llvm-c/Object.h new file mode 100644 index 00000000..a65a2352 --- /dev/null +++ b/src/llvmext/include/llvm-c/Object.h @@ -0,0 +1,75 @@ +/*===-- llvm-c/Object.h - Object Lib C Iface --------------------*- C++ -*-===*/ +/* */ +/* The LLVM Compiler Infrastructure */ +/* */ +/* This file is distributed under the University of Illinois Open Source */ +/* License. See LICENSE.TXT for details. */ +/* */ +/*===----------------------------------------------------------------------===*/ +/* */ +/* This header declares the C interface to libLLVMObject.a, which */ +/* implements object file reading and writing. */ +/* */ +/* Many exotic languages can interoperate with C code but have a harder time */ +/* with C++ due to name mangling. So in addition to C, this interface enables */ +/* tools written in such languages. */ +/* */ +/*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_C_OBJECT_H +#define LLVM_C_OBJECT_H + +#include "llvm-c/Core.h" +#include "llvm/Config/llvm-config.h" + +#ifdef __cplusplus +#include "llvm/Object/ObjectFile.h" + +extern "C" { +#endif + + +typedef struct LLVMOpaqueObjectFile *LLVMObjectFileRef; + +typedef struct LLVMOpaqueSectionIterator *LLVMSectionIteratorRef; + +LLVMObjectFileRef LLVMCreateObjectFile(const char *ObjectPath); +void LLVMDisposeObjectFile(LLVMObjectFileRef ObjectFile); + +LLVMSectionIteratorRef LLVMGetSections(LLVMObjectFileRef ObjectFile); +void LLVMDisposeSectionIterator(LLVMSectionIteratorRef SI); +void LLVMMoveToNextSection(LLVMSectionIteratorRef SI); +const char *LLVMGetSectionName(LLVMSectionIteratorRef SI); +uint64_t LLVMGetSectionSize(LLVMSectionIteratorRef SI); +const char *LLVMGetSectionContents(LLVMSectionIteratorRef SI); + + +#ifdef __cplusplus +} + +namespace llvm { + namespace object { + inline ObjectFile *unwrap(LLVMObjectFileRef OF) { + return reinterpret_cast(OF); + } + + inline LLVMObjectFileRef wrap(const ObjectFile *OF) { + return reinterpret_cast(const_cast(OF)); + } + + inline ObjectFile::section_iterator *unwrap(LLVMSectionIteratorRef SI) { + return reinterpret_cast(SI); + } + + inline LLVMSectionIteratorRef + wrap(const ObjectFile::section_iterator *SI) { + return reinterpret_cast + (const_cast(SI)); + } + } +} + +#endif /* defined(__cplusplus) */ + +#endif + diff --git a/src/support/Object.cpp b/src/support/Object.cpp deleted file mode 100644 index f390870f..00000000 --- a/src/support/Object.cpp +++ /dev/null @@ -1,55 +0,0 @@ -//===- Object.cpp - C bindings to the object file library--------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines the C bindings to the file-format-independent object -// library. -// -//===----------------------------------------------------------------------===// - -#include "llvm/Object/ObjectFile.h" -#include "llvm-c/Object.h" - -using namespace llvm; -using namespace object; - -LLVMObjectFileRef LLVMCreateObjectFile(const char *ObjectPath) { - StringRef SR(ObjectPath); - return wrap(ObjectFile::createObjectFile(SR)); -} - -void LLVMDisposeObjectFile(LLVMObjectFileRef ObjectFile) { - delete unwrap(ObjectFile); -} - -LLVMSectionIteratorRef LLVMGetSections(LLVMObjectFileRef ObjectFile) { - ObjectFile::section_iterator SI = unwrap(ObjectFile)->begin_sections(); - return wrap(new ObjectFile::section_iterator(SI)); -} - -void LLVMDisposeSectionIterator(LLVMSectionIteratorRef SI) { - delete unwrap(SI); -} - -void LLVMMoveToNextSection(LLVMSectionIteratorRef SI) { - ObjectFile::section_iterator UnwrappedSI = *unwrap(SI); - ++UnwrappedSI; -} - -const char *LLVMGetSectionName(LLVMSectionIteratorRef SI) { - return (*unwrap(SI))->getName().data(); -} - -uint64_t LLVMGetSectionSize(LLVMSectionIteratorRef SI) { - return (*unwrap(SI))->getSize(); -} - -const char *LLVMGetSectionContents(LLVMSectionIteratorRef SI) { - return (*unwrap(SI))->getContents().data(); -} - diff --git a/src/support/README b/src/support/README deleted file mode 100644 index 31495f22..00000000 --- a/src/support/README +++ /dev/null @@ -1,3 +0,0 @@ -This directory currently contains some LLVM support code. This will generally -be sent upstream to LLVM in time; for now it lives here. - diff --git a/src/support/include/llvm-c/Object.h b/src/support/include/llvm-c/Object.h deleted file mode 100644 index a65a2352..00000000 --- a/src/support/include/llvm-c/Object.h +++ /dev/null @@ -1,75 +0,0 @@ -/*===-- llvm-c/Object.h - Object Lib C Iface --------------------*- C++ -*-===*/ -/* */ -/* The LLVM Compiler Infrastructure */ -/* */ -/* This file is distributed under the University of Illinois Open Source */ -/* License. See LICENSE.TXT for details. */ -/* */ -/*===----------------------------------------------------------------------===*/ -/* */ -/* This header declares the C interface to libLLVMObject.a, which */ -/* implements object file reading and writing. */ -/* */ -/* Many exotic languages can interoperate with C code but have a harder time */ -/* with C++ due to name mangling. So in addition to C, this interface enables */ -/* tools written in such languages. */ -/* */ -/*===----------------------------------------------------------------------===*/ - -#ifndef LLVM_C_OBJECT_H -#define LLVM_C_OBJECT_H - -#include "llvm-c/Core.h" -#include "llvm/Config/llvm-config.h" - -#ifdef __cplusplus -#include "llvm/Object/ObjectFile.h" - -extern "C" { -#endif - - -typedef struct LLVMOpaqueObjectFile *LLVMObjectFileRef; - -typedef struct LLVMOpaqueSectionIterator *LLVMSectionIteratorRef; - -LLVMObjectFileRef LLVMCreateObjectFile(const char *ObjectPath); -void LLVMDisposeObjectFile(LLVMObjectFileRef ObjectFile); - -LLVMSectionIteratorRef LLVMGetSections(LLVMObjectFileRef ObjectFile); -void LLVMDisposeSectionIterator(LLVMSectionIteratorRef SI); -void LLVMMoveToNextSection(LLVMSectionIteratorRef SI); -const char *LLVMGetSectionName(LLVMSectionIteratorRef SI); -uint64_t LLVMGetSectionSize(LLVMSectionIteratorRef SI); -const char *LLVMGetSectionContents(LLVMSectionIteratorRef SI); - - -#ifdef __cplusplus -} - -namespace llvm { - namespace object { - inline ObjectFile *unwrap(LLVMObjectFileRef OF) { - return reinterpret_cast(OF); - } - - inline LLVMObjectFileRef wrap(const ObjectFile *OF) { - return reinterpret_cast(const_cast(OF)); - } - - inline ObjectFile::section_iterator *unwrap(LLVMSectionIteratorRef SI) { - return reinterpret_cast(SI); - } - - inline LLVMSectionIteratorRef - wrap(const ObjectFile::section_iterator *SI) { - return reinterpret_cast - (const_cast(SI)); - } - } -} - -#endif /* defined(__cplusplus) */ - -#endif - -- cgit v1.2.3 From fdc22ef1a1cef77dedb9c0429c746a81688a5979 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Fri, 11 Mar 2011 18:20:13 -0800 Subject: Add llvmext/include to the list of include directories to hopefully put out the burning tinderbox --- src/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Makefile b/src/Makefile index 47365a7c..43b66193 100644 --- a/src/Makefile +++ b/src/Makefile @@ -314,7 +314,7 @@ SUPPORT_CS := llvmext/Object.cpp SUPPORT_HDR := llvmext/include/llvm-c/Object.h -SUPPORT_INCS := -iquote $(CFG_LLVM_INCDIR) +SUPPORT_INCS := -iquote $(CFG_LLVM_INCDIR) -iquote llvmext/include SUPPORT_OBJS := $(SUPPORT_CS:.cpp=.o) SUPPORT_LIBS := $(CFG_LLVM_LDFLAGS) $(CFG_LLVM_LIBS) -- cgit v1.2.3