mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-29 02:03:53 +00:00
Implement an initial version of placement new.
This commit is contained in:
parent
ba39e277e2
commit
cfcbec3cc3
@ -434,8 +434,8 @@ fn for_each_package(c: cargo, b: fn(source, package)) {
|
|||||||
|
|
||||||
// Runs all programs in directory <buildpath>
|
// Runs all programs in directory <buildpath>
|
||||||
fn run_programs(buildpath: str) {
|
fn run_programs(buildpath: str) {
|
||||||
let new = os::list_dir(buildpath);
|
let newv = os::list_dir(buildpath);
|
||||||
for ct: str in new {
|
for ct: str in newv {
|
||||||
run::run_program(ct, []);
|
run::run_program(ct, []);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -471,9 +471,9 @@ fn install_one_crate(c: cargo, path: str, cf: str) {
|
|||||||
none { ret; }
|
none { ret; }
|
||||||
some(bp) { bp }
|
some(bp) { bp }
|
||||||
};
|
};
|
||||||
let new = os::list_dir(buildpath);
|
let newv = os::list_dir(buildpath);
|
||||||
let exec_suffix = os::exe_suffix();
|
let exec_suffix = os::exe_suffix();
|
||||||
for ct: str in new {
|
for ct: str in newv {
|
||||||
if (exec_suffix != "" && str::ends_with(ct, exec_suffix)) ||
|
if (exec_suffix != "" && str::ends_with(ct, exec_suffix)) ||
|
||||||
(exec_suffix == "" && !str::starts_with(path::basename(ct),
|
(exec_suffix == "" && !str::starts_with(path::basename(ct),
|
||||||
"lib")) {
|
"lib")) {
|
||||||
|
@ -488,23 +488,23 @@ fn file_might_not_converge(filename: str) -> bool {
|
|||||||
fn check_roundtrip_convergence(code: @str, maxIters: uint) {
|
fn check_roundtrip_convergence(code: @str, maxIters: uint) {
|
||||||
|
|
||||||
let i = 0u;
|
let i = 0u;
|
||||||
let new = code;
|
let newv = code;
|
||||||
let old = code;
|
let oldv = code;
|
||||||
|
|
||||||
while i < maxIters {
|
while i < maxIters {
|
||||||
old = new;
|
oldv = newv;
|
||||||
if content_might_not_converge(*old) { ret; }
|
if content_might_not_converge(*oldv) { ret; }
|
||||||
new = @parse_and_print(old);
|
newv = @parse_and_print(oldv);
|
||||||
if old == new { break; }
|
if oldv == newv { break; }
|
||||||
i += 1u;
|
i += 1u;
|
||||||
}
|
}
|
||||||
|
|
||||||
if old == new {
|
if oldv == newv {
|
||||||
#error("Converged after %u iterations", i);
|
#error("Converged after %u iterations", i);
|
||||||
} else {
|
} else {
|
||||||
#error("Did not converge after %u iterations!", i);
|
#error("Did not converge after %u iterations!", i);
|
||||||
write_file("round-trip-a.rs", *old);
|
write_file("round-trip-a.rs", *oldv);
|
||||||
write_file("round-trip-b.rs", *new);
|
write_file("round-trip-b.rs", *newv);
|
||||||
run::run_program("diff",
|
run::run_program("diff",
|
||||||
["-w", "-u", "round-trip-a.rs",
|
["-w", "-u", "round-trip-a.rs",
|
||||||
"round-trip-b.rs"]);
|
"round-trip-b.rs"]);
|
||||||
|
@ -266,30 +266,30 @@ fn normalize(p: path) -> path {
|
|||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
#[cfg(target_os = "freebsd")]
|
#[cfg(target_os = "freebsd")]
|
||||||
fn reabsolute(orig: path, new: path) -> path {
|
fn reabsolute(orig: path, n: path) -> path {
|
||||||
if path_is_absolute(orig) {
|
if path_is_absolute(orig) {
|
||||||
path_sep() + new
|
path_sep() + n
|
||||||
} else {
|
} else {
|
||||||
new
|
n
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_os = "win32")]
|
#[cfg(target_os = "win32")]
|
||||||
fn reabsolute(orig: path, new: path) -> path {
|
fn reabsolute(orig: path, newp: path) -> path {
|
||||||
if path_is_absolute(orig) && orig[0] == consts::path_sep as u8 {
|
if path_is_absolute(orig) && orig[0] == consts::path_sep as u8 {
|
||||||
str::from_char(consts::path_sep) + new
|
str::from_char(consts::path_sep) + newp
|
||||||
} else {
|
} else {
|
||||||
new
|
newp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reterminate(orig: path, new: path) -> path {
|
fn reterminate(orig: path, newp: path) -> path {
|
||||||
let last = orig[str::len(orig) - 1u];
|
let last = orig[str::len(orig) - 1u];
|
||||||
if last == consts::path_sep as u8
|
if last == consts::path_sep as u8
|
||||||
|| last == consts::path_sep as u8 {
|
|| last == consts::path_sep as u8 {
|
||||||
ret new + path_sep();
|
ret newp + path_sep();
|
||||||
} else {
|
} else {
|
||||||
ret new;
|
ret newp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -468,22 +468,22 @@ Concatenate a vector of vectors.
|
|||||||
Flattens a vector of vectors of T into a single vector of T.
|
Flattens a vector of vectors of T into a single vector of T.
|
||||||
"]
|
"]
|
||||||
fn concat<T: copy>(v: [const [const T]]) -> [T] {
|
fn concat<T: copy>(v: [const [const T]]) -> [T] {
|
||||||
let mut new: [T] = [];
|
let mut r: [T] = [];
|
||||||
for inner: [T] in v { new += inner; }
|
for inner: [T] in v { r += inner; }
|
||||||
ret new;
|
ret r;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[doc = "
|
#[doc = "
|
||||||
Concatenate a vector of vectors, placing a given separator between each
|
Concatenate a vector of vectors, placing a given separator between each
|
||||||
"]
|
"]
|
||||||
fn connect<T: copy>(v: [const [const T]], sep: T) -> [T] {
|
fn connect<T: copy>(v: [const [const T]], sep: T) -> [T] {
|
||||||
let mut new: [T] = [];
|
let mut r: [T] = [];
|
||||||
let mut first = true;
|
let mut first = true;
|
||||||
for inner: [T] in v {
|
for inner: [T] in v {
|
||||||
if first { first = false; } else { push(new, sep); }
|
if first { first = false; } else { push(r, sep); }
|
||||||
new += inner;
|
r += inner;
|
||||||
}
|
}
|
||||||
ret new;
|
ret r;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[doc = "Reduce a vector from left to right"]
|
#[doc = "Reduce a vector from left to right"]
|
||||||
|
@ -2308,6 +2308,9 @@ fn resolve_impl_in_expr(e: @env, x: @ast::expr, sc: iscopes, v: vt<iscopes>) {
|
|||||||
ast::expr_assign_op(_, _, _) | ast::expr_index(_, _) {
|
ast::expr_assign_op(_, _, _) | ast::expr_index(_, _) {
|
||||||
e.impl_map.insert(x.id, sc);
|
e.impl_map.insert(x.id, sc);
|
||||||
}
|
}
|
||||||
|
ast::expr_new(p, _, _) {
|
||||||
|
e.impl_map.insert(p.id, sc);
|
||||||
|
}
|
||||||
_ {}
|
_ {}
|
||||||
}
|
}
|
||||||
visit::visit_expr(x, sc, v);
|
visit::visit_expr(x, sc, v);
|
||||||
|
@ -1261,9 +1261,9 @@ fn trans_unary(bcx: block, op: ast::unop, e: @ast::expr,
|
|||||||
some(origin) {
|
some(origin) {
|
||||||
let callee_id = ast_util::op_expr_callee_id(un_expr);
|
let callee_id = ast_util::op_expr_callee_id(un_expr);
|
||||||
let fty = node_id_type(bcx, callee_id);
|
let fty = node_id_type(bcx, callee_id);
|
||||||
ret trans_call_inner(bcx, fty, {|bcx|
|
ret trans_call_inner(bcx, fty, expr_ty(bcx, un_expr), {|bcx|
|
||||||
impl::trans_method_callee(bcx, callee_id, e, origin)
|
impl::trans_method_callee(bcx, callee_id, e, origin)
|
||||||
}, [], un_expr.id, dest);
|
}, arg_exprs([]), dest);
|
||||||
}
|
}
|
||||||
_ {}
|
_ {}
|
||||||
}
|
}
|
||||||
@ -1450,10 +1450,10 @@ fn trans_assign_op(bcx: block, ex: @ast::expr, op: ast::binop,
|
|||||||
some(origin) {
|
some(origin) {
|
||||||
let callee_id = ast_util::op_expr_callee_id(ex);
|
let callee_id = ast_util::op_expr_callee_id(ex);
|
||||||
let fty = node_id_type(bcx, callee_id);
|
let fty = node_id_type(bcx, callee_id);
|
||||||
ret trans_call_inner(bcx, fty, {|bcx|
|
ret trans_call_inner(bcx, fty, expr_ty(bcx, ex), {|bcx|
|
||||||
// FIXME provide the already-computed address, not the expr
|
// FIXME provide the already-computed address, not the expr
|
||||||
impl::trans_method_callee(bcx, callee_id, dst, origin)
|
impl::trans_method_callee(bcx, callee_id, dst, origin)
|
||||||
}, [src], ex.id, save_in(lhs_res.val));
|
}, arg_exprs([src]), save_in(lhs_res.val));
|
||||||
}
|
}
|
||||||
_ {}
|
_ {}
|
||||||
}
|
}
|
||||||
@ -1561,9 +1561,9 @@ fn trans_binary(bcx: block, op: ast::binop, lhs: @ast::expr,
|
|||||||
some(origin) {
|
some(origin) {
|
||||||
let callee_id = ast_util::op_expr_callee_id(ex);
|
let callee_id = ast_util::op_expr_callee_id(ex);
|
||||||
let fty = node_id_type(bcx, callee_id);
|
let fty = node_id_type(bcx, callee_id);
|
||||||
ret trans_call_inner(bcx, fty, {|bcx|
|
ret trans_call_inner(bcx, fty, expr_ty(bcx, ex), {|bcx|
|
||||||
impl::trans_method_callee(bcx, callee_id, lhs, origin)
|
impl::trans_method_callee(bcx, callee_id, lhs, origin)
|
||||||
}, [rhs], ex.id, dest);
|
}, arg_exprs([rhs]), dest);
|
||||||
}
|
}
|
||||||
_ {}
|
_ {}
|
||||||
}
|
}
|
||||||
@ -2498,6 +2498,10 @@ fn trans_arg_expr(cx: block, arg: ty::arg, lldestty: TypeRef, e: @ast::expr,
|
|||||||
ret rslt(bcx, val);
|
ret rslt(bcx, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum call_args {
|
||||||
|
arg_exprs([@ast::expr]),
|
||||||
|
arg_vals([ValueRef])
|
||||||
|
}
|
||||||
|
|
||||||
// NB: must keep 4 fns in sync:
|
// NB: must keep 4 fns in sync:
|
||||||
//
|
//
|
||||||
@ -2505,12 +2509,12 @@ fn trans_arg_expr(cx: block, arg: ty::arg, lldestty: TypeRef, e: @ast::expr,
|
|||||||
// - create_llargs_for_fn_args.
|
// - create_llargs_for_fn_args.
|
||||||
// - new_fn_ctxt
|
// - new_fn_ctxt
|
||||||
// - trans_args
|
// - trans_args
|
||||||
fn trans_args(cx: block, llenv: ValueRef, es: [@ast::expr], fn_ty: ty::t,
|
fn trans_args(cx: block, llenv: ValueRef, args: call_args, fn_ty: ty::t,
|
||||||
dest: dest, generic_intrinsic: bool)
|
dest: dest, generic_intrinsic: bool)
|
||||||
-> {bcx: block, args: [ValueRef], retslot: ValueRef} {
|
-> {bcx: block, args: [ValueRef], retslot: ValueRef} {
|
||||||
|
|
||||||
let temp_cleanups = [];
|
let temp_cleanups = [];
|
||||||
let args = ty::ty_fn_args(fn_ty);
|
let arg_tys = ty::ty_fn_args(fn_ty);
|
||||||
let llargs: [ValueRef] = [];
|
let llargs: [ValueRef] = [];
|
||||||
|
|
||||||
let ccx = cx.ccx();
|
let ccx = cx.ccx();
|
||||||
@ -2546,13 +2550,21 @@ fn trans_args(cx: block, llenv: ValueRef, es: [@ast::expr], fn_ty: ty::t,
|
|||||||
// First we figure out the caller's view of the types of the arguments.
|
// First we figure out the caller's view of the types of the arguments.
|
||||||
// This will be needed if this is a generic call, because the callee has
|
// This will be needed if this is a generic call, because the callee has
|
||||||
// to cast her view of the arguments to the caller's view.
|
// to cast her view of the arguments to the caller's view.
|
||||||
let arg_tys = type_of_explicit_args(ccx, args);
|
alt args {
|
||||||
let i = 0u;
|
arg_exprs(es) {
|
||||||
for e: @ast::expr in es {
|
let llarg_tys = type_of_explicit_args(ccx, arg_tys);
|
||||||
let r = trans_arg_expr(bcx, args[i], arg_tys[i], e, temp_cleanups);
|
let i = 0u;
|
||||||
bcx = r.bcx;
|
for e: @ast::expr in es {
|
||||||
llargs += [r.val];
|
let r = trans_arg_expr(bcx, arg_tys[i], llarg_tys[i],
|
||||||
i += 1u;
|
e, temp_cleanups);
|
||||||
|
bcx = r.bcx;
|
||||||
|
llargs += [r.val];
|
||||||
|
i += 1u;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
arg_vals(vs) {
|
||||||
|
llargs += vs;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// now that all arguments have been successfully built, we can revoke any
|
// now that all arguments have been successfully built, we can revoke any
|
||||||
@ -2568,15 +2580,15 @@ fn trans_args(cx: block, llenv: ValueRef, es: [@ast::expr], fn_ty: ty::t,
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn trans_call(in_cx: block, f: @ast::expr,
|
fn trans_call(in_cx: block, f: @ast::expr,
|
||||||
args: [@ast::expr], id: ast::node_id, dest: dest)
|
args: call_args, id: ast::node_id, dest: dest)
|
||||||
-> block {
|
-> block {
|
||||||
trans_call_inner(in_cx, expr_ty(in_cx, f),
|
trans_call_inner(in_cx, expr_ty(in_cx, f), node_id_type(in_cx, id),
|
||||||
{|cx| trans_callee(cx, f)}, args, id, dest)
|
{|cx| trans_callee(cx, f)}, args, dest)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn trans_call_inner(in_cx: block, fn_expr_ty: ty::t,
|
fn trans_call_inner(in_cx: block, fn_expr_ty: ty::t, ret_ty: ty::t,
|
||||||
get_callee: fn(block) -> lval_maybe_callee,
|
get_callee: fn(block) -> lval_maybe_callee,
|
||||||
args: [@ast::expr], id: ast::node_id, dest: dest)
|
args: call_args, dest: dest)
|
||||||
-> block {
|
-> block {
|
||||||
with_scope(in_cx, "call") {|cx|
|
with_scope(in_cx, "call") {|cx|
|
||||||
let f_res = get_callee(cx);
|
let f_res = get_callee(cx);
|
||||||
@ -2603,9 +2615,10 @@ fn trans_call_inner(in_cx: block, fn_expr_ty: ty::t,
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let ret_ty = node_id_type(bcx, id);
|
let args_res = {
|
||||||
let args_res = trans_args(bcx, llenv, args, fn_expr_ty, dest,
|
trans_args(bcx, llenv, args, fn_expr_ty, dest,
|
||||||
option::is_some(f_res.tds));
|
option::is_some(f_res.tds))
|
||||||
|
};
|
||||||
bcx = args_res.bcx;
|
bcx = args_res.bcx;
|
||||||
let llargs = args_res.args;
|
let llargs = args_res.args;
|
||||||
option::may(f_res.tds) {|vals|
|
option::may(f_res.tds) {|vals|
|
||||||
@ -2923,7 +2936,7 @@ fn trans_expr(bcx: block, e: @ast::expr, dest: dest) -> block {
|
|||||||
}
|
}
|
||||||
ast::expr_cast(val, _) { ret trans_cast(bcx, val, e.id, dest); }
|
ast::expr_cast(val, _) { ret trans_cast(bcx, val, e.id, dest); }
|
||||||
ast::expr_call(f, args, _) {
|
ast::expr_call(f, args, _) {
|
||||||
ret trans_call(bcx, f, args, e.id, dest);
|
ret trans_call(bcx, f, arg_exprs(args), e.id, dest);
|
||||||
}
|
}
|
||||||
ast::expr_field(base, _, _) {
|
ast::expr_field(base, _, _) {
|
||||||
if dest == ignore { ret trans_expr(bcx, base, ignore); }
|
if dest == ignore { ret trans_expr(bcx, base, ignore); }
|
||||||
@ -2937,9 +2950,9 @@ fn trans_expr(bcx: block, e: @ast::expr, dest: dest) -> block {
|
|||||||
let origin = bcx.ccx().maps.method_map.get(e.id);
|
let origin = bcx.ccx().maps.method_map.get(e.id);
|
||||||
let callee_id = ast_util::op_expr_callee_id(e);
|
let callee_id = ast_util::op_expr_callee_id(e);
|
||||||
let fty = node_id_type(bcx, callee_id);
|
let fty = node_id_type(bcx, callee_id);
|
||||||
ret trans_call_inner(bcx, fty, {|bcx|
|
ret trans_call_inner(bcx, fty, expr_ty(bcx, e), {|bcx|
|
||||||
impl::trans_method_callee(bcx, callee_id, base, origin)
|
impl::trans_method_callee(bcx, callee_id, base, origin)
|
||||||
}, [idx], e.id, dest);
|
}, arg_exprs([idx]), dest);
|
||||||
}
|
}
|
||||||
|
|
||||||
// These return nothing
|
// These return nothing
|
||||||
@ -3037,6 +3050,45 @@ fn trans_expr(bcx: block, e: @ast::expr, dest: dest) -> block {
|
|||||||
assert dest == ignore;
|
assert dest == ignore;
|
||||||
ret trans_assign_op(bcx, e, op, dst, src);
|
ret trans_assign_op(bcx, e, op, dst, src);
|
||||||
}
|
}
|
||||||
|
ast::expr_new(pool, alloc_id, val) {
|
||||||
|
// First, call pool->alloc(sz, align) to get back a void*. Then, cast
|
||||||
|
// this memory to the required type and evaluate value into it.
|
||||||
|
let ccx = bcx.ccx();
|
||||||
|
|
||||||
|
// Allocate space for the ptr that will be returned from
|
||||||
|
// `pool.alloc()`:
|
||||||
|
let ptr_ty = expr_ty(bcx, e);
|
||||||
|
let {bcx, val: ptr_ptr_val} = alloc_ty(bcx, ptr_ty);
|
||||||
|
|
||||||
|
#debug["ptr_ty = %s", ty_to_str(tcx, ptr_ty)];
|
||||||
|
#debug["ptr_ptr_val = %s", val_str(ccx.tn, ptr_ptr_val)];
|
||||||
|
|
||||||
|
let void_ty = ty::mk_ptr(tcx, {ty: ty::mk_nil(tcx),
|
||||||
|
mutbl: ast::m_imm});
|
||||||
|
let voidval = {
|
||||||
|
let llvoid_ty = type_of(ccx, void_ty);
|
||||||
|
PointerCast(bcx, ptr_ptr_val, T_ptr(llvoid_ty))
|
||||||
|
};
|
||||||
|
|
||||||
|
#debug["voidval = %s", val_str(ccx.tn, voidval)];
|
||||||
|
|
||||||
|
let llval_ty = type_of(ccx, expr_ty(bcx, val));
|
||||||
|
let args = [llsize_of(ccx, llval_ty), llalign_of(ccx, llval_ty)];
|
||||||
|
let origin = bcx.ccx().maps.method_map.get(alloc_id);
|
||||||
|
let bcx = trans_call_inner(
|
||||||
|
bcx,
|
||||||
|
node_id_type(bcx, alloc_id),
|
||||||
|
void_ty,
|
||||||
|
{|bcx| impl::trans_method_callee(bcx, alloc_id, pool, origin) },
|
||||||
|
arg_vals(args),
|
||||||
|
save_in(voidval));
|
||||||
|
|
||||||
|
#debug["dest = %s", dest_str(ccx, dest)];
|
||||||
|
let ptr_val = Load(bcx, ptr_ptr_val);
|
||||||
|
#debug["ptr_val = %s", val_str(ccx.tn, ptr_val)];
|
||||||
|
let bcx = trans_expr(bcx, val, save_in(ptr_val));
|
||||||
|
store_in_dest(bcx, ptr_val, dest)
|
||||||
|
}
|
||||||
_ { bcx.tcx().sess.span_bug(e.span, "trans_expr reached \
|
_ { bcx.tcx().sess.span_bug(e.span, "trans_expr reached \
|
||||||
fall-through case"); }
|
fall-through case"); }
|
||||||
|
|
||||||
|
@ -111,27 +111,28 @@ fn classify_ty(ty: TypeRef) -> [x86_64_reg_class] {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn unify(cls: [mut x86_64_reg_class], i: uint,
|
fn unify(cls: [mut x86_64_reg_class],
|
||||||
new: x86_64_reg_class) {
|
i: uint,
|
||||||
if cls[i] == new {
|
newv: x86_64_reg_class) {
|
||||||
|
if cls[i] == newv {
|
||||||
ret;
|
ret;
|
||||||
} else if cls[i] == no_class {
|
} else if cls[i] == no_class {
|
||||||
cls[i] = new;
|
cls[i] = newv;
|
||||||
} else if new == no_class {
|
} else if newv == no_class {
|
||||||
ret;
|
ret;
|
||||||
} else if cls[i] == memory_class || new == memory_class {
|
} else if cls[i] == memory_class || newv == memory_class {
|
||||||
cls[i] = memory_class;
|
cls[i] = memory_class;
|
||||||
} else if cls[i] == integer_class || new == integer_class {
|
} else if cls[i] == integer_class || newv == integer_class {
|
||||||
cls[i] = integer_class;
|
cls[i] = integer_class;
|
||||||
} else if cls[i] == x87_class ||
|
} else if cls[i] == x87_class ||
|
||||||
cls[i] == x87up_class ||
|
cls[i] == x87up_class ||
|
||||||
cls[i] == complex_x87_class ||
|
cls[i] == complex_x87_class ||
|
||||||
new == x87_class ||
|
newv == x87_class ||
|
||||||
new == x87up_class ||
|
newv == x87up_class ||
|
||||||
new == complex_x87_class {
|
newv == complex_x87_class {
|
||||||
cls[i] = memory_class;
|
cls[i] = memory_class;
|
||||||
} else {
|
} else {
|
||||||
cls[i] = new;
|
cls[i] = newv;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -168,6 +168,9 @@ fn mark_for_expr(cx: ctx, e: @expr) {
|
|||||||
expr_log(_, _, val) {
|
expr_log(_, _, val) {
|
||||||
node_type_needs(cx, use_tydesc, val.id);
|
node_type_needs(cx, use_tydesc, val.id);
|
||||||
}
|
}
|
||||||
|
expr_new(_, _, v) {
|
||||||
|
node_type_needs(cx, use_repr, v.id);
|
||||||
|
}
|
||||||
expr_for(_, _, _) | expr_do_while(_, _) | expr_alt(_, _, _) |
|
expr_for(_, _, _) | expr_do_while(_, _) | expr_alt(_, _, _) |
|
||||||
expr_block(_) | expr_if(_, _, _) | expr_while(_, _) |
|
expr_block(_) | expr_if(_, _, _) | expr_while(_, _) |
|
||||||
expr_fail(_) | expr_break | expr_cont | expr_unary(_, _) |
|
expr_fail(_) | expr_break | expr_cont | expr_unary(_, _) |
|
||||||
|
@ -183,14 +183,14 @@ fn set_poststate(a: ts_ann, p: poststate) -> bool {
|
|||||||
|
|
||||||
|
|
||||||
// Set all the bits in p that are set in new
|
// Set all the bits in p that are set in new
|
||||||
fn extend_prestate(p: prestate, new: poststate) -> bool {
|
fn extend_prestate(p: prestate, newv: poststate) -> bool {
|
||||||
ret tritv_union(p, new);
|
ret tritv_union(p, newv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Set all the bits in p that are set in new
|
// Set all the bits in p that are set in new
|
||||||
fn extend_poststate(p: poststate, new: poststate) -> bool {
|
fn extend_poststate(p: poststate, newv: poststate) -> bool {
|
||||||
ret tritv_union(p, new);
|
ret tritv_union(p, newv);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sets the given bit in p to "don't care"
|
// Sets the given bit in p to "don't care"
|
||||||
|
@ -709,8 +709,8 @@ fn find_instances(_fcx: fn_ctxt, subst: subst, c: constraint) ->
|
|||||||
for d: pred_args in *descs {
|
for d: pred_args in *descs {
|
||||||
if args_mention(d.node.args, find_in_subst_bool, subst) {
|
if args_mention(d.node.args, find_in_subst_bool, subst) {
|
||||||
let old_bit_num = d.node.bit_num;
|
let old_bit_num = d.node.bit_num;
|
||||||
let new = replace(subst, d);
|
let newv = replace(subst, d);
|
||||||
alt find_instance_(new, *descs) {
|
alt find_instance_(newv, *descs) {
|
||||||
some(d1) { rslt += [{from: old_bit_num, to: d1}]; }
|
some(d1) { rslt += [{from: old_bit_num, to: d1}]; }
|
||||||
_ { }
|
_ { }
|
||||||
}
|
}
|
||||||
@ -753,7 +753,7 @@ fn replace(subst: subst, d: pred_args) -> [constr_arg_general_<inst>] {
|
|||||||
alt c.node {
|
alt c.node {
|
||||||
carg_ident(p) {
|
carg_ident(p) {
|
||||||
alt find_in_subst(p.node, subst) {
|
alt find_in_subst(p.node, subst) {
|
||||||
some(new) { rslt += [carg_ident(new)]; }
|
some(newv) { rslt += [carg_ident(newv)]; }
|
||||||
_ { rslt += [c.node]; }
|
_ { rslt += [c.node]; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -325,6 +325,9 @@ fn find_pre_post_expr(fcx: fn_ctxt, e: @expr) {
|
|||||||
clear_pp(rslt);
|
clear_pp(rslt);
|
||||||
handle_var(fcx, rslt, e.id, path_to_ident(p));
|
handle_var(fcx, rslt, e.id, path_to_ident(p));
|
||||||
}
|
}
|
||||||
|
expr_new(p, _, v) {
|
||||||
|
find_pre_post_exprs(fcx, [p, v], e.id);
|
||||||
|
}
|
||||||
expr_log(_, lvl, arg) {
|
expr_log(_, lvl, arg) {
|
||||||
find_pre_post_exprs(fcx, [lvl, arg], e.id);
|
find_pre_post_exprs(fcx, [lvl, arg], e.id);
|
||||||
}
|
}
|
||||||
|
@ -355,6 +355,9 @@ fn find_pre_post_state_expr(fcx: fn_ctxt, pres: prestate, e: @expr) -> bool {
|
|||||||
let num_constrs = num_constraints(fcx.enclosing);
|
let num_constrs = num_constraints(fcx.enclosing);
|
||||||
|
|
||||||
alt e.node {
|
alt e.node {
|
||||||
|
expr_new(p, _, v) {
|
||||||
|
ret find_pre_post_state_two(fcx, pres, p, v, e.id, oper_pure);
|
||||||
|
}
|
||||||
expr_vec(elts, _) {
|
expr_vec(elts, _) {
|
||||||
ret find_pre_post_state_exprs(fcx, pres, e.id,
|
ret find_pre_post_state_exprs(fcx, pres, e.id,
|
||||||
vec::from_elem(vec::len(elts),
|
vec::from_elem(vec::len(elts),
|
||||||
|
@ -155,8 +155,8 @@ fn trit_and(a: trit, b: trit) -> trit {
|
|||||||
// a and b were both dont_care
|
// a and b were both dont_care
|
||||||
}
|
}
|
||||||
|
|
||||||
fn change(changed: bool, old: trit, new: trit) -> bool {
|
fn change(changed: bool, old: trit, newv: trit) -> bool {
|
||||||
changed || new != old
|
changed || newv != old
|
||||||
}
|
}
|
||||||
|
|
||||||
fn tritv_difference(p1: t, p2: t) -> bool {
|
fn tritv_difference(p1: t, p2: t) -> bool {
|
||||||
@ -166,9 +166,9 @@ fn tritv_difference(p1: t, p2: t) -> bool {
|
|||||||
let changed = false;
|
let changed = false;
|
||||||
while i < sz {
|
while i < sz {
|
||||||
let old = tritv_get(p1, i);
|
let old = tritv_get(p1, i);
|
||||||
let new = trit_minus(old, tritv_get(p2, i));
|
let newv = trit_minus(old, tritv_get(p2, i));
|
||||||
changed = change(changed, old, new);
|
changed = change(changed, old, newv);
|
||||||
tritv_set(i, p1, new);
|
tritv_set(i, p1, newv);
|
||||||
i += 1u;
|
i += 1u;
|
||||||
}
|
}
|
||||||
ret changed;
|
ret changed;
|
||||||
@ -181,9 +181,9 @@ fn tritv_union(p1: t, p2: t) -> bool {
|
|||||||
let changed = false;
|
let changed = false;
|
||||||
while i < sz {
|
while i < sz {
|
||||||
let old = tritv_get(p1, i);
|
let old = tritv_get(p1, i);
|
||||||
let new = trit_or(old, tritv_get(p2, i));
|
let newv = trit_or(old, tritv_get(p2, i));
|
||||||
changed = change(changed, old, new);
|
changed = change(changed, old, newv);
|
||||||
tritv_set(i, p1, new);
|
tritv_set(i, p1, newv);
|
||||||
i += 1u;
|
i += 1u;
|
||||||
}
|
}
|
||||||
ret changed;
|
ret changed;
|
||||||
@ -196,9 +196,9 @@ fn tritv_intersect(p1: t, p2: t) -> bool {
|
|||||||
let changed = false;
|
let changed = false;
|
||||||
while i < sz {
|
while i < sz {
|
||||||
let old = tritv_get(p1, i);
|
let old = tritv_get(p1, i);
|
||||||
let new = trit_and(old, tritv_get(p2, i));
|
let newv = trit_and(old, tritv_get(p2, i));
|
||||||
changed = change(changed, old, new);
|
changed = change(changed, old, newv);
|
||||||
tritv_set(i, p1, new);
|
tritv_set(i, p1, newv);
|
||||||
i += 1u;
|
i += 1u;
|
||||||
}
|
}
|
||||||
ret changed;
|
ret changed;
|
||||||
|
@ -1888,6 +1888,12 @@ fn lookup_method_inner(fcx: @fn_ctxt, expr: @ast::expr,
|
|||||||
origin: method_origin,
|
origin: method_origin,
|
||||||
self_sub: option<self_subst>}> {
|
self_sub: option<self_subst>}> {
|
||||||
let tcx = fcx.ccx.tcx;
|
let tcx = fcx.ccx.tcx;
|
||||||
|
|
||||||
|
#debug["lookup_method_inner: expr=%s name=%s ty=%s",
|
||||||
|
expr_to_str(expr),
|
||||||
|
name,
|
||||||
|
ty_to_str(fcx.ccx.tcx, ty)];
|
||||||
|
|
||||||
// First, see whether this is an interface-bounded parameter
|
// First, see whether this is an interface-bounded parameter
|
||||||
alt ty::get(ty).struct {
|
alt ty::get(ty).struct {
|
||||||
ty::ty_param(n, did) {
|
ty::ty_param(n, did) {
|
||||||
@ -2870,6 +2876,51 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ast::expr_new(p, alloc_id, v) {
|
||||||
|
bot |= check_expr(fcx, p);
|
||||||
|
bot |= check_expr(fcx, v);
|
||||||
|
|
||||||
|
let p_ty = expr_ty(tcx, p);
|
||||||
|
|
||||||
|
alt lookup_method(fcx, p, alloc_id, "alloc", p_ty, []) {
|
||||||
|
some(origin) {
|
||||||
|
fcx.ccx.method_map.insert(alloc_id, origin);
|
||||||
|
|
||||||
|
// Check that the alloc() method has the expected type, which
|
||||||
|
// should be fn(sz: uint, align: uint) -> *().
|
||||||
|
let expected_ty = {
|
||||||
|
let ty_uint = ty::mk_uint(tcx);
|
||||||
|
let ty_nilp = ty::mk_ptr(tcx, {ty: ty::mk_nil(tcx),
|
||||||
|
mutbl: ast::m_imm});
|
||||||
|
let m = ast::expl(ty::default_arg_mode_for_ty(ty_uint));
|
||||||
|
ty::mk_fn(tcx, {proto: ast::proto_any,
|
||||||
|
inputs: [{mode: m, ty: ty_uint},
|
||||||
|
{mode: m, ty: ty_uint}],
|
||||||
|
output: ty_nilp,
|
||||||
|
ret_style: ast::return_val,
|
||||||
|
constraints: []})
|
||||||
|
};
|
||||||
|
|
||||||
|
demand::simple(fcx, expr.span,
|
||||||
|
expected_ty, node_id_to_type(tcx, alloc_id));
|
||||||
|
}
|
||||||
|
|
||||||
|
none {
|
||||||
|
let t_err = resolve_type_vars_if_possible(fcx, p_ty);
|
||||||
|
let msg = #fmt["no `alloc()` method found for type `%s`",
|
||||||
|
ty_to_str(tcx, t_err)];
|
||||||
|
tcx.sess.span_err(expr.span, msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The region value must have a type like &r.T. The resulting
|
||||||
|
// memory will be allocated into the region `r`.
|
||||||
|
let pool_region = region_of(fcx, p);
|
||||||
|
let v_ty = expr_ty(tcx, v);
|
||||||
|
let res_ty = ty::mk_rptr(tcx, pool_region, {ty: v_ty,
|
||||||
|
mutbl: ast::m_imm});
|
||||||
|
write_ty(tcx, expr.id, res_ty);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if bot { write_ty(tcx, expr.id, ty::mk_bot(tcx)); }
|
if bot { write_ty(tcx, expr.id, ty::mk_bot(tcx)); }
|
||||||
|
|
||||||
|
@ -325,6 +325,10 @@ enum expr_ {
|
|||||||
expr_be(@expr),
|
expr_be(@expr),
|
||||||
expr_log(int, @expr, @expr),
|
expr_log(int, @expr, @expr),
|
||||||
|
|
||||||
|
expr_new(/* arena */ @expr,
|
||||||
|
/* id for the alloc() call */ node_id,
|
||||||
|
/* value */ @expr),
|
||||||
|
|
||||||
/* just an assert, no significance to typestate */
|
/* just an assert, no significance to typestate */
|
||||||
expr_assert(@expr),
|
expr_assert(@expr),
|
||||||
|
|
||||||
|
@ -382,6 +382,11 @@ fn noop_fold_expr(e: expr_, fld: ast_fold) -> expr_ {
|
|||||||
let fold_mac = bind fold_mac_(_, fld);
|
let fold_mac = bind fold_mac_(_, fld);
|
||||||
|
|
||||||
ret alt e {
|
ret alt e {
|
||||||
|
expr_new(p, i, v) {
|
||||||
|
expr_new(fld.fold_expr(p),
|
||||||
|
fld.new_id(i),
|
||||||
|
fld.fold_expr(v))
|
||||||
|
}
|
||||||
expr_vec(exprs, mutt) {
|
expr_vec(exprs, mutt) {
|
||||||
expr_vec(fld.map_exprs(fld.fold_expr, exprs), mutt)
|
expr_vec(fld.map_exprs(fld.fold_expr, exprs), mutt)
|
||||||
}
|
}
|
||||||
|
@ -150,7 +150,7 @@ fn bad_expr_word_table() -> hashmap<str, ()> {
|
|||||||
"enum", "export", "fail", "fn", "for", "if", "iface",
|
"enum", "export", "fail", "fn", "for", "if", "iface",
|
||||||
"impl", "import", "let", "log", "loop", "mod", "mut",
|
"impl", "import", "let", "log", "loop", "mod", "mut",
|
||||||
"mutable", "native", "pure", "resource", "ret", "trait",
|
"mutable", "native", "pure", "resource", "ret", "trait",
|
||||||
"type", "unchecked", "unsafe", "while"] {
|
"type", "unchecked", "unsafe", "while", "new"] {
|
||||||
words.insert(word, ());
|
words.insert(word, ());
|
||||||
}
|
}
|
||||||
words
|
words
|
||||||
@ -852,6 +852,13 @@ fn parse_bottom_expr(p: parser) -> pexpr {
|
|||||||
let blk = parse_block_tail(p, lo, ast::default_blk);
|
let blk = parse_block_tail(p, lo, ast::default_blk);
|
||||||
ret mk_pexpr(p, blk.span.lo, blk.span.hi, ast::expr_block(blk));
|
ret mk_pexpr(p, blk.span.lo, blk.span.hi, ast::expr_block(blk));
|
||||||
}
|
}
|
||||||
|
} else if eat_word(p, "new") {
|
||||||
|
expect(p, token::LPAREN);
|
||||||
|
let r = parse_expr(p);
|
||||||
|
expect(p, token::RPAREN);
|
||||||
|
let v = parse_expr(p);
|
||||||
|
ret mk_pexpr(p, lo, p.span.hi,
|
||||||
|
ast::expr_new(r, p.get_id(), v));
|
||||||
} else if eat_word(p, "if") {
|
} else if eat_word(p, "if") {
|
||||||
ret pexpr(parse_if_expr(p));
|
ret pexpr(parse_if_expr(p));
|
||||||
} else if eat_word(p, "for") {
|
} else if eat_word(p, "for") {
|
||||||
|
@ -1089,6 +1089,13 @@ fn print_expr(s: ps, &&expr: @ast::expr) {
|
|||||||
word_nbsp(s, "assert");
|
word_nbsp(s, "assert");
|
||||||
print_expr(s, expr);
|
print_expr(s, expr);
|
||||||
}
|
}
|
||||||
|
ast::expr_new(p, _, v) {
|
||||||
|
word_nbsp(s, "new");
|
||||||
|
popen(s);
|
||||||
|
print_expr(s, p);
|
||||||
|
pclose(s);
|
||||||
|
print_expr(s, v);
|
||||||
|
}
|
||||||
ast::expr_mac(m) { print_mac(s, m); }
|
ast::expr_mac(m) { print_mac(s, m); }
|
||||||
}
|
}
|
||||||
s.ann.post(ann_node);
|
s.ann.post(ann_node);
|
||||||
|
@ -315,6 +315,10 @@ fn visit_mac<E>(m: mac, e: E, v: vt<E>) {
|
|||||||
|
|
||||||
fn visit_expr<E>(ex: @expr, e: E, v: vt<E>) {
|
fn visit_expr<E>(ex: @expr, e: E, v: vt<E>) {
|
||||||
alt ex.node {
|
alt ex.node {
|
||||||
|
expr_new(pool, _, val) {
|
||||||
|
v.visit_expr(pool, e, v);
|
||||||
|
v.visit_expr(val, e, v);
|
||||||
|
}
|
||||||
expr_vec(es, _) { visit_exprs(es, e, v); }
|
expr_vec(es, _) { visit_exprs(es, e, v); }
|
||||||
expr_rec(flds, base) {
|
expr_rec(flds, base) {
|
||||||
for f: field in flds { v.visit_expr(f.node.expr, e, v); }
|
for f: field in flds { v.visit_expr(f.node.expr, e, v); }
|
||||||
|
15
src/test/compile-fail/placement-new-bad-method-type.rs
Normal file
15
src/test/compile-fail/placement-new-bad-method-type.rs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import libc, unsafe;
|
||||||
|
|
||||||
|
enum malloc_pool = ();
|
||||||
|
|
||||||
|
impl methods for malloc_pool {
|
||||||
|
fn alloc(sz: int, align: int) -> *() {
|
||||||
|
fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let p = &malloc_pool(());
|
||||||
|
let x = new(*p) 4u;
|
||||||
|
//!^ ERROR mismatched types: expected `fn(uint, uint) -> *()`
|
||||||
|
}
|
@ -21,7 +21,7 @@ fn request_task(c: chan<ctx>) {
|
|||||||
req = recv(p);
|
req = recv(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new() -> ctx {
|
fn new_cx() -> ctx {
|
||||||
let p = port();
|
let p = port();
|
||||||
let ch = chan(p);
|
let ch = chan(p);
|
||||||
let t = task::spawn {|| request_task(ch); };
|
let t = task::spawn {|| request_task(ch); };
|
||||||
@ -31,7 +31,7 @@ fn new() -> ctx {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let cx = new();
|
let cx = new_cx();
|
||||||
|
|
||||||
let p = port::<bool>();
|
let p = port::<bool>();
|
||||||
send(cx, close(chan(p)));
|
send(cx, close(chan(p)));
|
||||||
|
21
src/test/run-pass/placement-new-leaky.rs
Normal file
21
src/test/run-pass/placement-new-leaky.rs
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import libc, unsafe;
|
||||||
|
|
||||||
|
enum malloc_pool = ();
|
||||||
|
|
||||||
|
impl methods for malloc_pool {
|
||||||
|
fn alloc(sz: uint, align: uint) -> *() {
|
||||||
|
unsafe {
|
||||||
|
unsafe::reinterpret_cast(libc::malloc(sz))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let p = &malloc_pool(());
|
||||||
|
let x = new(*p) 4u;
|
||||||
|
io::print(#fmt["%u", *x]);
|
||||||
|
assert *x == 4u;
|
||||||
|
unsafe {
|
||||||
|
libc::free(unsafe::reinterpret_cast(x));
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user