parse: typeck: enabling trivial casts of tail-call return values
introduces ctypes::m_* machine type aliases for int, uint, float depending on cfg(target_arch) that are used in tests
This commit is contained in:
parent
29f7cdffa4
commit
4ba3158e4f
9 changed files with 124 additions and 47 deletions
|
|
@ -4088,10 +4088,8 @@ fn trans_expr(bcx: @block_ctxt, e: @ast::expr, dest: dest) -> @block_ctxt {
|
|||
}
|
||||
ast::expr_cast(val, _) {
|
||||
alt tcx.cast_map.find(e.id) {
|
||||
option::none. { ret trans_cast(bcx, val, e.id, dest); }
|
||||
some { alt option::get(some) {
|
||||
ty::triv_cast. { ret trans_expr(bcx, val, dest); }
|
||||
} }
|
||||
some(ty::triv_cast.) { ret trans_expr(bcx, val, dest); }
|
||||
_ { ret trans_cast(bcx, val, e.id, dest); }
|
||||
}
|
||||
}
|
||||
ast::expr_anon_obj(anon_obj) {
|
||||
|
|
@ -4122,7 +4120,7 @@ fn trans_expr(bcx: @block_ctxt, e: @ast::expr, dest: dest) -> @block_ctxt {
|
|||
// that is_call_expr(ex) -- but we don't support that
|
||||
// yet
|
||||
// FIXME
|
||||
check (ast_util::is_call_expr(ex));
|
||||
check (ast_util::is_tail_call_expr(ex));
|
||||
ret trans_be(bcx, ex);
|
||||
}
|
||||
ast::expr_fail(expr) {
|
||||
|
|
@ -4455,7 +4453,8 @@ fn trans_ret(bcx: @block_ctxt, e: option::t<@ast::expr>) -> @block_ctxt {
|
|||
fn build_return(bcx: @block_ctxt) { Br(bcx, bcx_fcx(bcx).llreturn); }
|
||||
|
||||
// fn trans_be(cx: &@block_ctxt, e: &@ast::expr) -> result {
|
||||
fn trans_be(cx: @block_ctxt, e: @ast::expr) : ast_util::is_call_expr(e) ->
|
||||
fn trans_be(cx: @block_ctxt, e: @ast::expr) :
|
||||
ast_util::is_tail_call_expr(e) ->
|
||||
@block_ctxt {
|
||||
// FIXME: Turn this into a real tail call once
|
||||
// calling convention issues are settled
|
||||
|
|
|
|||
|
|
@ -1501,7 +1501,7 @@ fn eq_ty(&&a: t, &&b: t) -> bool { ret a == b; }
|
|||
// Convert type to machine type
|
||||
// (i.e. replace uint, int, float with target architecture machine types)
|
||||
//
|
||||
// Somewhat expensive but casts that need this should be rare
|
||||
// FIXME somewhat expensive but this should only be called rarely
|
||||
fn ty_to_machine_ty(cx: ctxt, ty: t) -> t {
|
||||
fn sub_fn(cx: ctxt, uint_ty: t, int_ty: t, float_ty: t, in: t) -> t {
|
||||
alt struct(cx, in) {
|
||||
|
|
@ -1525,12 +1525,9 @@ fn ty_to_machine_ty(cx: ctxt, ty: t) -> t {
|
|||
// equal or if they are equal after substituting all occurences of
|
||||
// machine independent primitive types by their machine type equivalents
|
||||
// for the current target architecture
|
||||
//
|
||||
// Somewhat expensive but casts that need this should be rare
|
||||
fn triv_eq_ty(cx: ctxt, &&a: t, &&b: t) -> bool {
|
||||
let mach_a = ty_to_machine_ty(cx, a);
|
||||
let mach_b = ty_to_machine_ty(cx, b );
|
||||
ret eq_ty(a, b) || eq_ty(mach_a, mach_b);
|
||||
ret eq_ty(a, b)
|
||||
|| eq_ty(ty_to_machine_ty(cx, a), ty_to_machine_ty(cx, b));
|
||||
}
|
||||
|
||||
// Type lookups
|
||||
|
|
|
|||
|
|
@ -1846,8 +1846,21 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
|
|||
}
|
||||
ast::expr_be(e) {
|
||||
// FIXME: prove instead of assert
|
||||
assert (ast_util::is_call_expr(e));
|
||||
assert (ast_util::is_tail_call_expr(e));
|
||||
check_expr_with(fcx, e, fcx.ret_ty);
|
||||
|
||||
alt e.node {
|
||||
ast::expr_cast(_, _) {
|
||||
alt tcx.cast_map.find(e.id) {
|
||||
option::some(ty::triv_cast.) { }
|
||||
_ { tcx.sess.span_err(expr.span,
|
||||
"non-trivial cast of tail-call return value");
|
||||
}
|
||||
}
|
||||
}
|
||||
_ { /* regular tail call */ }
|
||||
}
|
||||
|
||||
bot = true;
|
||||
write::nil_ty(tcx, id);
|
||||
}
|
||||
|
|
@ -2112,8 +2125,10 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
|
|||
ty_to_str(tcx, t_1));
|
||||
}
|
||||
|
||||
// mark as triv_cast for later dropping in trans
|
||||
if ty::triv_eq_ty(tcx, t_1, t_e)
|
||||
{ tcx.cast_map.insert(expr.id, ty::triv_cast); }
|
||||
|
||||
write::ty_only_fixup(fcx, id, t_1);
|
||||
}
|
||||
ast::expr_vec(args, mut) {
|
||||
|
|
|
|||
|
|
@ -175,6 +175,14 @@ pure fn is_call_expr(e: @expr) -> bool {
|
|||
alt e.node { expr_call(_, _, _) { true } _ { false } }
|
||||
}
|
||||
|
||||
pure fn is_tail_call_expr(e: @expr) -> bool {
|
||||
alt e.node {
|
||||
expr_call(_, _, _) { true }
|
||||
expr_cast(inner_e, _) { is_call_expr(inner_e) }
|
||||
_ { false }
|
||||
}
|
||||
}
|
||||
|
||||
fn is_constraint_arg(e: @expr) -> bool {
|
||||
alt e.node {
|
||||
expr_lit(_) { ret true; }
|
||||
|
|
|
|||
|
|
@ -962,7 +962,7 @@ fn parse_bottom_expr(p: parser) -> @ast::expr {
|
|||
let e = parse_expr(p);
|
||||
|
||||
// FIXME: Is this the right place for this check?
|
||||
if /*check*/ast_util::is_call_expr(e) {
|
||||
if /*check*/ ast_util::is_tail_call_expr(e) {
|
||||
hi = e.span.hi;
|
||||
ex = ast::expr_be(e);
|
||||
} else { p.fatal("Non-call expression in tail call"); }
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue