* # fn make_a_sandwich() {};
* let mut delayed_fib = extra::future::spawn (|| fib(5000) );
* make_a_sandwich();
- * println(fmt!("fib(5000) = %?", delayed_fib.get()))
+ * printfln!("fib(5000) = %?", delayed_fib.get())
* ~~~
*/
#[test]
fn test_interface_unwrap() {
- let mut f = from_value(~"fail");
+ let f = from_value(~"fail");
assert_eq!(f.unwrap(), ~"fail");
}
* }
*
* fn print_usage(program: &str, _opts: &[Opt]) {
- * println(fmt!("Usage: %s [options]", program));
+ * printfln!("Usage: %s [options]", program);
* println("-o\t\tOutput");
* println("-h --help\tUsage");
* }
let vals = opt_vals(mm, nm);
if vals.is_empty() { return None::<~str>; }
return match vals[0] { Val(ref s) => Some::<~str>((*s).clone()),
- _ => Some::<~str>(str::to_owned(def)) }
+ _ => Some::<~str>(def.to_owned()) }
}
#[deriving(Eq)]
desc: &str, hint: &str) -> OptGroup {
let len = short_name.len();
assert!(len == 1 || len == 0);
- return OptGroup { short_name: str::to_owned(short_name),
- long_name: str::to_owned(long_name),
- hint: str::to_owned(hint),
- desc: str::to_owned(desc),
+ return OptGroup { short_name: short_name.to_owned(),
+ long_name: long_name.to_owned(),
+ hint: hint.to_owned(),
+ desc: desc.to_owned(),
hasarg: Yes,
occur: Req};
}
desc: &str, hint: &str) -> OptGroup {
let len = short_name.len();
assert!(len == 1 || len == 0);
- return OptGroup {short_name: str::to_owned(short_name),
- long_name: str::to_owned(long_name),
- hint: str::to_owned(hint),
- desc: str::to_owned(desc),
+ return OptGroup {short_name: short_name.to_owned(),
+ long_name: long_name.to_owned(),
+ hint: hint.to_owned(),
+ desc: desc.to_owned(),
hasarg: Yes,
occur: Optional};
}
desc: &str) -> OptGroup {
let len = short_name.len();
assert!(len == 1 || len == 0);
- return OptGroup {short_name: str::to_owned(short_name),
- long_name: str::to_owned(long_name),
+ return OptGroup {short_name: short_name.to_owned(),
+ long_name: long_name.to_owned(),
hint: ~"",
- desc: str::to_owned(desc),
+ desc: desc.to_owned(),
hasarg: No,
occur: Optional};
}
desc: &str, hint: &str) -> OptGroup {
let len = short_name.len();
assert!(len == 1 || len == 0);
- return OptGroup {short_name: str::to_owned(short_name),
- long_name: str::to_owned(long_name),
- hint: str::to_owned(hint),
- desc: str::to_owned(desc),
+ return OptGroup {short_name: short_name.to_owned(),
+ long_name: long_name.to_owned(),
+ hint: hint.to_owned(),
+ desc: desc.to_owned(),
hasarg: Maybe,
occur: Optional};
}
desc: &str, hint: &str) -> OptGroup {
let len = short_name.len();
assert!(len == 1 || len == 0);
- return OptGroup {short_name: str::to_owned(short_name),
- long_name: str::to_owned(long_name),
- hint: str::to_owned(hint),
- desc: str::to_owned(desc),
+ return OptGroup {short_name: short_name.to_owned(),
+ long_name: long_name.to_owned(),
+ hint: hint.to_owned(),
+ desc: desc.to_owned(),
hasarg: Yes,
occur: Multi};
}
row
});
- return str::to_owned(brief) +
+ return brief.to_owned() +
"\n\nOptions:\n" +
rows.collect::<~[~str]>().connect("\n") +
"\n\n";
// option. This file may not be copied, modified, or distributed
// except according to those terms.
- use std::str;
use std::io;
use driver::session::{OptLevel, No, Less, Aggressive};
}
pub fn create_pass(name:&str) -> Option<PassRef> {
- do str::as_c_str(name) |s| {
+ do name.as_c_str |s| {
unsafe {
let p = llvm::LLVMCreatePass(s);
if p.is_null() {
io::println("\nAnalysis Passes:");
for analysis_passes.iter().advance |&(name, desc)| {
- io::println(fmt!(" %-30s -- %s", name, desc));
+ printfln!(" %-30s -- %s", name, desc);
}
io::println("\nTransformation Passes:");
for transform_passes.iter().advance |&(name, desc)| {
- io::println(fmt!(" %-30s -- %s", name, desc));
+ printfln!(" %-30s -- %s", name, desc);
}
io::println("\nUtility Passes:");
for utility_passes.iter().advance |&(name, desc)| {
- io::println(fmt!(" %-30s -- %s", name, desc));
+ printfln!(" %-30s -- %s", name, desc);
}
}
if failed.len() > 0 {
io::println("Some passes don't exist:");
for failed.iter().advance |&n| {
- io::println(fmt!(" %s", n));
+ printfln!(" %s", n);
}
fail!();
}
use middle::trans::type_::Type;
- use std::str;
use syntax::ast;
// Take an inline assembly expression and splat it out via LLVM
-pub fn trans_inline_asm(bcx: block, ia: &ast::inline_asm) -> block {
+pub fn trans_inline_asm(bcx: @mut Block, ia: &ast::inline_asm) -> @mut Block {
let mut bcx = bcx;
let mut constraints = ~[];
ast::asm_intel => lib::llvm::AD_Intel
};
- let r = do str::as_c_str(ia.asm) |a| {
- do str::as_c_str(constraints) |c| {
+ let r = do ia.asm.as_c_str |a| {
+ do constraints.as_c_str |c| {
InlineAsmCall(bcx, a, c, inputs, output, ia.volatile, ia.alignstack, dialect)
}
};
use std::int;
use std::io;
use std::libc::c_uint;
- use std::str;
use std::uint;
use std::vec;
use std::local_data;
_InsnCtxt { _x: () }
}
-fn fcx_has_nonzero_span(fcx: fn_ctxt) -> bool {
+fn fcx_has_nonzero_span(fcx: &FunctionContext) -> bool {
match fcx.span {
None => true,
Some(span) => *span.lo != 0 || *span.hi != 0
return c;
}
}
-pub fn umax(cx: block, a: ValueRef, b: ValueRef) -> ValueRef {
+pub fn umax(cx: @mut Block, a: ValueRef, b: ValueRef) -> ValueRef {
let _icx = push_ctxt("umax");
let cond = ICmp(cx, lib::llvm::IntULT, a, b);
return Select(cx, cond, b, a);
}
-pub fn umin(cx: block, a: ValueRef, b: ValueRef) -> ValueRef {
+pub fn umin(cx: @mut Block, a: ValueRef, b: ValueRef) -> ValueRef {
let _icx = push_ctxt("umin");
let cond = ICmp(cx, lib::llvm::IntULT, a, b);
return Select(cx, cond, a, b);
// Given a pointer p, returns a pointer sz(p) (i.e., inc'd by sz bytes).
// The type of the returned pointer is always i8*. If you care about the
// return type, use bump_ptr().
-pub fn ptr_offs(bcx: block, base: ValueRef, sz: ValueRef) -> ValueRef {
+pub fn ptr_offs(bcx: @mut Block, base: ValueRef, sz: ValueRef) -> ValueRef {
let _icx = push_ctxt("ptr_offs");
let raw = PointerCast(bcx, base, Type::i8p());
InBoundsGEP(bcx, raw, [sz])
// Increment a pointer by a given amount and then cast it to be a pointer
// to a given type.
-pub fn bump_ptr(bcx: block, t: ty::t, base: ValueRef, sz: ValueRef) ->
+pub fn bump_ptr(bcx: @mut Block, t: ty::t, base: ValueRef, sz: ValueRef) ->
ValueRef {
let _icx = push_ctxt("bump_ptr");
let ccx = bcx.ccx();
// known.
//
// The runtime equivalent is box_body() in "rust_internal.h".
-pub fn opaque_box_body(bcx: block,
+pub fn opaque_box_body(bcx: @mut Block,
body_t: ty::t,
boxptr: ValueRef) -> ValueRef {
let _icx = push_ctxt("opaque_box_body");
// malloc_raw_dyn: allocates a box to contain a given type, but with a
// potentially dynamic size.
-pub fn malloc_raw_dyn(bcx: block,
+pub fn malloc_raw_dyn(bcx: @mut Block,
t: ty::t,
heap: heap,
size: ValueRef) -> Result {
let _icx = push_ctxt("malloc_raw");
let ccx = bcx.ccx();
- fn require_alloc_fn(bcx: block, t: ty::t, it: LangItem) -> ast::def_id {
+ fn require_alloc_fn(bcx: @mut Block, t: ty::t, it: LangItem) -> ast::def_id {
let li = &bcx.tcx().lang_items;
match li.require(it) {
Ok(id) => id,
// malloc_raw: expects an unboxed type and returns a pointer to
// enough space for a box of that type. This includes a rust_opaque_box
// header.
-pub fn malloc_raw(bcx: block, t: ty::t, heap: heap) -> Result {
+pub fn malloc_raw(bcx: @mut Block, t: ty::t, heap: heap) -> Result {
let ty = type_of(bcx.ccx(), t);
let size = llsize_of(bcx.ccx(), ty);
malloc_raw_dyn(bcx, t, heap, size)
}
pub struct MallocResult {
- bcx: block,
+ bcx: @mut Block,
box: ValueRef,
body: ValueRef
}
// malloc_general_dyn: usefully wraps malloc_raw_dyn; allocates a box,
// and pulls out the body
-pub fn malloc_general_dyn(bcx: block, t: ty::t, heap: heap, size: ValueRef)
+pub fn malloc_general_dyn(bcx: @mut Block, t: ty::t, heap: heap, size: ValueRef)
-> MallocResult {
assert!(heap != heap_exchange);
let _icx = push_ctxt("malloc_general");
MallocResult { bcx: bcx, box: llbox, body: body }
}
-pub fn malloc_general(bcx: block, t: ty::t, heap: heap) -> MallocResult {
+pub fn malloc_general(bcx: @mut Block, t: ty::t, heap: heap) -> MallocResult {
let ty = type_of(bcx.ccx(), t);
assert!(heap != heap_exchange);
malloc_general_dyn(bcx, t, heap, llsize_of(bcx.ccx(), ty))
}
-pub fn malloc_boxed(bcx: block, t: ty::t)
+pub fn malloc_boxed(bcx: @mut Block, t: ty::t)
-> MallocResult {
malloc_general(bcx, t, heap_managed)
}
-pub fn heap_for_unique(bcx: block, t: ty::t) -> heap {
+pub fn heap_for_unique(bcx: @mut Block, t: ty::t) -> heap {
if ty::type_contents(bcx.tcx(), t).contains_managed() {
heap_managed_unique
} else {
}
}
-pub fn maybe_set_managed_unique_rc(bcx: block, bx: ValueRef, heap: heap) {
+pub fn maybe_set_managed_unique_rc(bcx: @mut Block, bx: ValueRef, heap: heap) {
assert!(heap != heap_exchange);
if heap == heap_managed_unique {
// In cases where we are looking at a unique-typed allocation in the
// Structural comparison: a rather involved form of glue.
pub fn maybe_name_value(cx: &CrateContext, v: ValueRef, s: &str) {
if cx.sess.opts.save_temps {
- let _: () = str::as_c_str(s, |buf| {
+ do s.as_c_str |buf| {
unsafe {
llvm::LLVMSetValueName(v, buf)
}
- });
+ }
}
}
pub enum scalar_type { nil_type, signed_int, unsigned_int, floating_point, }
// NB: This produces an i1, not a Rust bool (i8).
-pub fn compare_scalar_types(cx: block,
+pub fn compare_scalar_types(cx: @mut Block,
lhs: ValueRef,
rhs: ValueRef,
t: ty::t,
// A helper function to do the actual comparison of scalar values.
-pub fn compare_scalar_values(cx: block,
+pub fn compare_scalar_values(cx: @mut Block,
lhs: ValueRef,
rhs: ValueRef,
nt: scalar_type,
op: ast::binop)
-> ValueRef {
let _icx = push_ctxt("compare_scalar_values");
- fn die(cx: block) -> ! {
+ fn die(cx: @mut Block) -> ! {
cx.tcx().sess.bug("compare_scalar_values: must be a\
comparison operator");
}
}
}
-pub type val_and_ty_fn<'self> = &'self fn(block, ValueRef, ty::t) -> block;
+pub type val_and_ty_fn<'self> = &'self fn(@mut Block, ValueRef, ty::t) -> @mut Block;
-pub fn load_inbounds(cx: block, p: ValueRef, idxs: &[uint]) -> ValueRef {
+pub fn load_inbounds(cx: @mut Block, p: ValueRef, idxs: &[uint]) -> ValueRef {
return Load(cx, GEPi(cx, p, idxs));
}
-pub fn store_inbounds(cx: block, v: ValueRef, p: ValueRef, idxs: &[uint]) {
+pub fn store_inbounds(cx: @mut Block, v: ValueRef, p: ValueRef, idxs: &[uint]) {
Store(cx, v, GEPi(cx, p, idxs));
}
// Iterates through the elements of a structural type.
-pub fn iter_structural_ty(cx: block, av: ValueRef, t: ty::t,
- f: val_and_ty_fn) -> block {
+pub fn iter_structural_ty(cx: @mut Block, av: ValueRef, t: ty::t,
+ f: val_and_ty_fn) -> @mut Block {
let _icx = push_ctxt("iter_structural_ty");
- fn iter_variant(cx: block, repr: &adt::Repr, av: ValueRef,
+ fn iter_variant(cx: @mut Block, repr: &adt::Repr, av: ValueRef,
variant: @ty::VariantInfo,
- tps: &[ty::t], f: val_and_ty_fn) -> block {
+ tps: &[ty::t], f: val_and_ty_fn) -> @mut Block {
let _icx = push_ctxt("iter_variant");
let tcx = cx.tcx();
let mut cx = cx;
return cx;
}
-pub fn cast_shift_expr_rhs(cx: block, op: ast::binop,
+pub fn cast_shift_expr_rhs(cx: @mut Block, op: ast::binop,
lhs: ValueRef, rhs: ValueRef) -> ValueRef {
cast_shift_rhs(op, lhs, rhs,
|a,b| Trunc(cx, a, b),
}
}
-pub fn fail_if_zero(cx: block, span: span, divrem: ast::binop,
- rhs: ValueRef, rhs_t: ty::t) -> block {
+pub fn fail_if_zero(cx: @mut Block, span: span, divrem: ast::binop,
+ rhs: ValueRef, rhs_t: ty::t) -> @mut Block {
let text = if divrem == ast::div {
@"attempted to divide by zero"
} else {
}
}
-pub fn null_env_ptr(bcx: block) -> ValueRef {
+pub fn null_env_ptr(bcx: @mut Block) -> ValueRef {
C_null(Type::opaque_box(bcx.ccx()).ptr_to())
}
};
}
-pub fn invoke(bcx: block, llfn: ValueRef, llargs: ~[ValueRef])
- -> (ValueRef, block) {
+pub fn invoke(bcx: @mut Block, llfn: ValueRef, llargs: ~[ValueRef])
+ -> (ValueRef, @mut Block) {
let _icx = push_ctxt("invoke_");
if bcx.unreachable {
return (C_null(Type::i8()), bcx);
}
}
-pub fn need_invoke(bcx: block) -> bool {
+pub fn need_invoke(bcx: @mut Block) -> bool {
if (bcx.ccx().sess.opts.debugging_opts & session::no_landing_pads != 0) {
return false;
}
}
}
-pub fn have_cached_lpad(bcx: block) -> bool {
+pub fn have_cached_lpad(bcx: @mut Block) -> bool {
let mut res = false;
do in_lpad_scope_cx(bcx) |inf| {
match inf.landing_pad {
return res;
}
-pub fn in_lpad_scope_cx(bcx: block, f: &fn(si: &mut scope_info)) {
+pub fn in_lpad_scope_cx(bcx: @mut Block, f: &fn(si: &mut ScopeInfo)) {
let mut bcx = bcx;
let mut cur_scope = bcx.scope;
loop {
}
}
-pub fn get_landing_pad(bcx: block) -> BasicBlockRef {
+pub fn get_landing_pad(bcx: @mut Block) -> BasicBlockRef {
let _icx = push_ctxt("get_landing_pad");
let mut cached = None;
return pad_bcx.llbb;
}
-pub fn find_bcx_for_scope(bcx: block, scope_id: ast::node_id) -> block {
+pub fn find_bcx_for_scope(bcx: @mut Block, scope_id: ast::node_id) -> @mut Block {
let mut bcx_sid = bcx;
let mut cur_scope = bcx_sid.scope;
loop {
}
-pub fn do_spill(bcx: block, v: ValueRef, t: ty::t) -> ValueRef {
+pub fn do_spill(bcx: @mut Block, v: ValueRef, t: ty::t) -> ValueRef {
if ty::type_is_bot(t) {
return C_null(Type::i8p());
}
// Since this function does *not* root, it is the caller's responsibility to
// ensure that the referent is pointed to by a root.
-pub fn do_spill_noroot(cx: block, v: ValueRef) -> ValueRef {
+pub fn do_spill_noroot(cx: @mut Block, v: ValueRef) -> ValueRef {
let llptr = alloca(cx, val_ty(v), "");
Store(cx, v, llptr);
return llptr;
}
-pub fn spill_if_immediate(cx: block, v: ValueRef, t: ty::t) -> ValueRef {
+pub fn spill_if_immediate(cx: @mut Block, v: ValueRef, t: ty::t) -> ValueRef {
let _icx = push_ctxt("spill_if_immediate");
if ty::type_is_immediate(cx.tcx(), t) { return do_spill(cx, v, t); }
return v;
}
-pub fn load_if_immediate(cx: block, v: ValueRef, t: ty::t) -> ValueRef {
+pub fn load_if_immediate(cx: @mut Block, v: ValueRef, t: ty::t) -> ValueRef {
let _icx = push_ctxt("load_if_immediate");
if ty::type_is_immediate(cx.tcx(), t) { return Load(cx, v); }
return v;
}
-pub fn trans_trace(bcx: block, sp_opt: Option<span>, trace_str: @str) {
+pub fn trans_trace(bcx: @mut Block, sp_opt: Option<span>, trace_str: @str) {
if !bcx.sess().trace() { return; }
let _icx = push_ctxt("trans_trace");
add_comment(bcx, trace_str);
Call(bcx, ccx.upcalls.trace, args);
}
-pub fn ignore_lhs(_bcx: block, local: &ast::Local) -> bool {
+pub fn ignore_lhs(_bcx: @mut Block, local: &ast::Local) -> bool {
match local.pat.node {
ast::pat_wild => true, _ => false
}
}
-pub fn init_local(bcx: block, local: &ast::Local) -> block {
+pub fn init_local(bcx: @mut Block, local: &ast::Local) -> @mut Block {
debug!("init_local(bcx=%s, local.id=%?)",
bcx.to_str(), local.id);
_match::store_local(bcx, local.pat, local.init)
}
-pub fn trans_stmt(cx: block, s: &ast::stmt) -> block {
+pub fn trans_stmt(cx: @mut Block, s: &ast::stmt) -> @mut Block {
let _icx = push_ctxt("trans_stmt");
debug!("trans_stmt(%s)", stmt_to_str(s, cx.tcx().sess.intr()));
// You probably don't want to use this one. See the
// next three functions instead.
-pub fn new_block(cx: fn_ctxt, parent: Option<block>, scope: Option<@mut scope_info>,
- is_lpad: bool, name: &str, opt_node_info: Option<NodeInfo>)
- -> block {
-
+pub fn new_block(cx: @mut FunctionContext,
+ parent: Option<@mut Block>,
+ scope: Option<@mut ScopeInfo>,
+ is_lpad: bool,
+ name: &str,
+ opt_node_info: Option<NodeInfo>)
+ -> @mut Block {
unsafe {
let llbb = do name.as_c_str |buf| {
llvm::LLVMAppendBasicBlockInContext(cx.ccx.llcx, cx.llfn, buf)
};
- let bcx = mk_block(llbb,
- parent,
- is_lpad,
- opt_node_info,
- cx);
+ let bcx = @mut Block::new(llbb,
+ parent,
+ is_lpad,
+ opt_node_info,
+ cx);
bcx.scope = scope;
for parent.iter().advance |cx| {
if cx.unreachable {
}
}
-pub fn simple_block_scope(parent: Option<@mut scope_info>,
- node_info: Option<NodeInfo>) -> @mut scope_info {
- @mut scope_info {
+pub fn simple_block_scope(parent: Option<@mut ScopeInfo>,
+ node_info: Option<NodeInfo>) -> @mut ScopeInfo {
+ @mut ScopeInfo {
parent: parent,
loop_break: None,
loop_label: None,
}
// Use this when you're at the top block of a function or the like.
-pub fn top_scope_block(fcx: fn_ctxt, opt_node_info: Option<NodeInfo>)
- -> block {
+pub fn top_scope_block(fcx: @mut FunctionContext, opt_node_info: Option<NodeInfo>)
+ -> @mut Block {
return new_block(fcx, None, Some(simple_block_scope(None, opt_node_info)), false,
"function top level", opt_node_info);
}
-pub fn scope_block(bcx: block,
+pub fn scope_block(bcx: @mut Block,
opt_node_info: Option<NodeInfo>,
- n: &str) -> block {
+ n: &str) -> @mut Block {
return new_block(bcx.fcx, Some(bcx), Some(simple_block_scope(None, opt_node_info)), bcx.is_lpad,
n, opt_node_info);
}
-pub fn loop_scope_block(bcx: block,
- loop_break: block,
+pub fn loop_scope_block(bcx: @mut Block,
+ loop_break: @mut Block,
loop_label: Option<ident>,
n: &str,
- opt_node_info: Option<NodeInfo>) -> block {
- return new_block(bcx.fcx, Some(bcx), Some(@mut scope_info {
+ opt_node_info: Option<NodeInfo>) -> @mut Block {
+ return new_block(bcx.fcx, Some(bcx), Some(@mut ScopeInfo {
parent: None,
loop_break: Some(loop_break),
loop_label: loop_label,
}
// Use this when creating a block for the inside of a landing pad.
-pub fn lpad_block(bcx: block, n: &str) -> block {
+pub fn lpad_block(bcx: @mut Block, n: &str) -> @mut Block {
new_block(bcx.fcx, Some(bcx), None, true, n, None)
}
// Use this when you're making a general CFG BB within a scope.
-pub fn sub_block(bcx: block, n: &str) -> block {
+pub fn sub_block(bcx: @mut Block, n: &str) -> @mut Block {
new_block(bcx.fcx, Some(bcx), None, bcx.is_lpad, n, None)
}
-pub fn raw_block(fcx: fn_ctxt, is_lpad: bool, llbb: BasicBlockRef) -> block {
- mk_block(llbb, None, is_lpad, None, fcx)
+pub fn raw_block(fcx: @mut FunctionContext, is_lpad: bool, llbb: BasicBlockRef) -> @mut Block {
+ @mut Block::new(llbb, None, is_lpad, None, fcx)
}
// need to make sure those variables go out of scope when the block ends. We
// do that by running a 'cleanup' function for each variable.
// trans_block_cleanups runs all the cleanup functions for the block.
-pub fn trans_block_cleanups(bcx: block, cleanups: ~[cleanup]) -> block {
+pub fn trans_block_cleanups(bcx: @mut Block, cleanups: ~[cleanup]) -> @mut Block {
trans_block_cleanups_(bcx, cleanups, false)
}
-pub fn trans_block_cleanups_(bcx: block,
+pub fn trans_block_cleanups_(bcx: @mut Block,
cleanups: &[cleanup],
/* cleanup_cx: block, */
- is_lpad: bool) -> block {
+ is_lpad: bool) -> @mut Block {
let _icx = push_ctxt("trans_block_cleanups");
// NB: Don't short-circuit even if this block is unreachable because
// GC-based cleanup needs to the see that the roots are live.
// In the last argument, Some(block) mean jump to this block, and none means
// this is a landing pad and leaving should be accomplished with a resume
// instruction.
-pub fn cleanup_and_leave(bcx: block,
+pub fn cleanup_and_leave(bcx: @mut Block,
upto: Option<BasicBlockRef>,
leave: Option<BasicBlockRef>) {
let _icx = push_ctxt("cleanup_and_leave");
}
}
-pub fn cleanup_block(bcx: block, upto: Option<BasicBlockRef>) -> block{
+pub fn cleanup_block(bcx: @mut Block, upto: Option<BasicBlockRef>) -> @mut Block{
let _icx = push_ctxt("cleanup_block");
let mut cur = bcx;
let mut bcx = bcx;
bcx
}
-pub fn cleanup_and_Br(bcx: block, upto: block, target: BasicBlockRef) {
+pub fn cleanup_and_Br(bcx: @mut Block, upto: @mut Block, target: BasicBlockRef) {
let _icx = push_ctxt("cleanup_and_Br");
cleanup_and_leave(bcx, Some(upto.llbb), Some(target));
}
-pub fn leave_block(bcx: block, out_of: block) -> block {
+pub fn leave_block(bcx: @mut Block, out_of: @mut Block) -> @mut Block {
let _icx = push_ctxt("leave_block");
let next_cx = sub_block(block_parent(out_of), "next");
if bcx.unreachable { Unreachable(next_cx); }
next_cx
}
-pub fn with_scope(bcx: block,
+pub fn with_scope(bcx: @mut Block,
opt_node_info: Option<NodeInfo>,
name: &str,
- f: &fn(block) -> block) -> block {
+ f: &fn(@mut Block) -> @mut Block) -> @mut Block {
let _icx = push_ctxt("with_scope");
debug!("with_scope(bcx=%s, opt_node_info=%?, name=%s)",
ret
}
-pub fn with_scope_result(bcx: block,
+pub fn with_scope_result(bcx: @mut Block,
opt_node_info: Option<NodeInfo>,
_name: &str,
- f: &fn(block) -> Result) -> Result {
+ f: &fn(@mut Block) -> Result) -> Result {
let _icx = push_ctxt("with_scope_result");
let scope = simple_block_scope(bcx.scope, opt_node_info);
rslt(out_bcx, val)
}
-pub fn with_scope_datumblock(bcx: block, opt_node_info: Option<NodeInfo>,
- name: &str, f: &fn(block) -> datum::DatumBlock)
+pub fn with_scope_datumblock(bcx: @mut Block, opt_node_info: Option<NodeInfo>,
+ name: &str, f: &fn(@mut Block) -> datum::DatumBlock)
-> datum::DatumBlock {
use middle::trans::datum::DatumBlock;
}
}
-pub fn with_cond(bcx: block, val: ValueRef, f: &fn(block) -> block) -> block {
+pub fn with_cond(bcx: @mut Block, val: ValueRef, f: &fn(@mut Block) -> @mut Block) -> @mut Block {
let _icx = push_ctxt("with_cond");
let next_cx = base::sub_block(bcx, "next");
let cond_cx = base::sub_block(bcx, "cond");
next_cx
}
-pub fn call_memcpy(cx: block, dst: ValueRef, src: ValueRef, n_bytes: ValueRef, align: u32) {
+pub fn call_memcpy(cx: @mut Block, dst: ValueRef, src: ValueRef, n_bytes: ValueRef, align: u32) {
let _icx = push_ctxt("call_memcpy");
let ccx = cx.ccx();
let key = match ccx.sess.targ_cfg.arch {
Call(cx, memcpy, [dst_ptr, src_ptr, size, align, volatile]);
}
-pub fn memcpy_ty(bcx: block, dst: ValueRef, src: ValueRef, t: ty::t) {
+pub fn memcpy_ty(bcx: @mut Block, dst: ValueRef, src: ValueRef, t: ty::t) {
let _icx = push_ctxt("memcpy_ty");
let ccx = bcx.ccx();
if ty::type_is_structural(t) {
}
}
-pub fn zero_mem(cx: block, llptr: ValueRef, t: ty::t) {
+pub fn zero_mem(cx: @mut Block, llptr: ValueRef, t: ty::t) {
if cx.unreachable { return; }
let _icx = push_ctxt("zero_mem");
let bcx = cx;
b.call(llintrinsicfn, [llptr, llzeroval, size, align, volatile]);
}
-pub fn alloc_ty(bcx: block, t: ty::t, name: &str) -> ValueRef {
+pub fn alloc_ty(bcx: @mut Block, t: ty::t, name: &str) -> ValueRef {
let _icx = push_ctxt("alloc_ty");
let ccx = bcx.ccx();
let ty = type_of::type_of(ccx, t);
return val;
}
-pub fn alloca(cx: block, ty: Type, name: &str) -> ValueRef {
+pub fn alloca(cx: @mut Block, ty: Type, name: &str) -> ValueRef {
alloca_maybe_zeroed(cx, ty, name, false)
}
-pub fn alloca_maybe_zeroed(cx: block, ty: Type, name: &str, zero: bool) -> ValueRef {
+pub fn alloca_maybe_zeroed(cx: @mut Block, ty: Type, name: &str, zero: bool) -> ValueRef {
let _icx = push_ctxt("alloca");
if cx.unreachable {
unsafe {
p
}
-pub fn arrayalloca(cx: block, ty: Type, v: ValueRef) -> ValueRef {
+pub fn arrayalloca(cx: @mut Block, ty: Type, v: ValueRef) -> ValueRef {
let _icx = push_ctxt("arrayalloca");
if cx.unreachable {
unsafe {
pub fn mk_staticallocas_basic_block(llfn: ValueRef) -> BasicBlockRef {
unsafe {
let cx = task_llcx();
- str::as_c_str("static_allocas",
- |buf| llvm::LLVMAppendBasicBlockInContext(cx, llfn, buf))
+ do "static_allocas".as_c_str | buf| {
+ llvm::LLVMAppendBasicBlockInContext(cx, llfn, buf)
+ }
}
}
pub fn mk_return_basic_block(llfn: ValueRef) -> BasicBlockRef {
unsafe {
let cx = task_llcx();
- str::as_c_str("return",
- |buf| llvm::LLVMAppendBasicBlockInContext(cx, llfn, buf))
+ do "return".as_c_str |buf| {
+ llvm::LLVMAppendBasicBlockInContext(cx, llfn, buf)
+ }
}
}
// Creates and returns space for, or returns the argument representing, the
// slot where the return value of the function must go.
-pub fn make_return_pointer(fcx: fn_ctxt, output_type: ty::t) -> ValueRef {
+pub fn make_return_pointer(fcx: @mut FunctionContext, output_type: ty::t) -> ValueRef {
unsafe {
if !ty::type_is_immediate(fcx.ccx.tcx, output_type) {
llvm::LLVMGetParam(fcx.llfn, 0)
param_substs: Option<@param_substs>,
opt_node_info: Option<NodeInfo>,
sp: Option<span>)
- -> fn_ctxt {
+ -> @mut FunctionContext {
for param_substs.iter().advance |p| { p.validate(); }
debug!("new_fn_ctxt_w_id(path=%s, id=%?, \
}
};
let is_immediate = ty::type_is_immediate(ccx.tcx, substd_output_type);
- let fcx = @mut fn_ctxt_ {
+ let fcx = @mut FunctionContext {
llfn: llfndecl,
llenv: unsafe {
llvm::LLVMGetUndef(Type::i8p().to_ref())
llfndecl: ValueRef,
output_type: ty::t,
sp: Option<span>)
- -> fn_ctxt {
+ -> @mut FunctionContext {
new_fn_ctxt_w_id(ccx, path, llfndecl, -1, output_type, false, None, None, sp)
}
// spaces that have been created for them (by code in the llallocas field of
// the function's fn_ctxt). create_llargs_for_fn_args populates the llargs
// field of the fn_ctxt with
-pub fn create_llargs_for_fn_args(cx: fn_ctxt,
+pub fn create_llargs_for_fn_args(cx: @mut FunctionContext,
self_arg: self_arg,
args: &[ast::arg])
-> ~[ValueRef] {
})
}
-pub fn copy_args_to_allocas(fcx: fn_ctxt,
- bcx: block,
+pub fn copy_args_to_allocas(fcx: @mut FunctionContext,
+ bcx: @mut Block,
args: &[ast::arg],
raw_llargs: &[ValueRef],
- arg_tys: &[ty::t]) -> block {
+ arg_tys: &[ty::t]) -> @mut Block {
let _icx = push_ctxt("copy_args_to_allocas");
let mut bcx = bcx;
// Ties up the llstaticallocas -> llloadenv -> lltop edges,
// and builds the return block.
-pub fn finish_fn(fcx: fn_ctxt, last_bcx: block) {
+pub fn finish_fn(fcx: @mut FunctionContext, last_bcx: @mut Block) {
let _icx = push_ctxt("finish_fn");
let ret_cx = match fcx.llreturn {
}
// Builds the return block for a function.
-pub fn build_return_block(fcx: fn_ctxt, ret_cx: block) {
+pub fn build_return_block(fcx: &FunctionContext, ret_cx: @mut Block) {
// Return the value if this function immediate; otherwise, return void.
if fcx.llretptr.is_some() && fcx.has_immediate_return_value {
Ret(ret_cx, Load(ret_cx, fcx.llretptr.get()))
id: ast::node_id,
attributes: &[ast::Attribute],
output_type: ty::t,
- maybe_load_env: &fn(fn_ctxt),
- finish: &fn(block)) {
+ maybe_load_env: &fn(@mut FunctionContext),
+ finish: &fn(@mut Block)) {
ccx.stats.n_closures += 1;
let _icx = push_ctxt("trans_closure");
set_uwtable(llfndecl);
|_bcx| { });
}
-fn insert_synthetic_type_entries(bcx: block,
+fn insert_synthetic_type_entries(bcx: @mut Block,
fn_args: &[ast::arg],
arg_tys: &[ty::t])
{
};
decl_cdecl_fn(ccx.llmod, main_name, llfty)
};
- let llbb = str::as_c_str("top", |buf| {
+ let llbb = do "top".as_c_str |buf| {
unsafe {
llvm::LLVMAppendBasicBlockInContext(ccx.llcx, llfn, buf)
}
- });
+ };
let bld = ccx.builder.B;
unsafe {
llvm::LLVMPositionBuilderAtEnd(bld, llbb);
}
}
-pub fn fill_fn_pair(bcx: block, pair: ValueRef, llfn: ValueRef,
+pub fn fill_fn_pair(bcx: @mut Block, pair: ValueRef, llfn: ValueRef,
llenvptr: ValueRef) {
let ccx = bcx.ccx();
let code_cell = GEPi(bcx, pair, [0u, abi::fn_field_code]);
let val = match item {
ast_map::node_item(i, pth) => {
let my_path = vec::append((*pth).clone(), [path_name(i.ident)]);
- match i.node {
+ let v = match i.node {
ast::item_static(_, m, expr) => {
let typ = ty::node_id_to_type(ccx.tcx, i.id);
let s = mangle_exported_name(ccx, my_path, typ);
exprt = m == ast::m_mutbl;
unsafe {
let llty = llvm::LLVMTypeOf(v);
- let g = str::as_c_str(s, |buf| {
+ let g = do s.as_c_str |buf| {
llvm::LLVMAddGlobal(ccx.llmod, llty, buf)
- });
+ };
ccx.item_symbols.insert(i.id, s);
g
}
llfn
}
_ => fail!("get_item_val: weird result in table")
+ };
+ match (attr::first_attr_value_str_by_name(i.attrs, "link_section")) {
+ Some(sect) => unsafe {
+ do sect.as_c_str |buf| {
+ llvm::LLVMSetSection(v, buf);
+ }
+ },
+ None => ()
}
+ v
}
ast_map::node_trait_method(trait_method, _, pth) => {
debug!("get_item_val(): processing a node_trait_method");
ast::foreign_item_static(*) => {
let typ = ty::node_id_to_type(ccx.tcx, ni.id);
let ident = token::ident_to_str(&ni.ident);
- let g = do str::as_c_str(ident) |buf| {
+ let g = do ident.as_c_str |buf| {
unsafe {
let ty = type_of(ccx, typ);
llvm::LLVMAddGlobal(ccx.llmod, ty.to_ref(), buf)
let s = mangle_exported_name(ccx, p, ty::mk_int()).to_managed();
let disr_val = vi[i].disr_val;
note_unique_llvm_symbol(ccx, s);
- let discrim_gvar = str::as_c_str(s, |buf| {
+ let discrim_gvar = do s.as_c_str |buf| {
unsafe {
llvm::LLVMAddGlobal(ccx.llmod, ccx.int_type.to_ref(), buf)
}
- });
+ };
unsafe {
llvm::LLVMSetInitializer(discrim_gvar, C_int(ccx, disr_val));
llvm::LLVMSetGlobalConstant(discrim_gvar, True);
})));
}
-pub fn vp2i(cx: block, v: ValueRef) -> ValueRef {
+pub fn vp2i(cx: @mut Block, v: ValueRef) -> ValueRef {
let ccx = cx.ccx();
return PtrToInt(cx, v, ccx.int_type);
}
ifn!("llvm.dbg.value", [Type::metadata(), Type::i64(), Type::metadata()], Type::void());
}
-pub fn trap(bcx: block) {
+pub fn trap(bcx: @mut Block) {
match bcx.ccx().intrinsics.find_equiv(& &"llvm.trap") {
Some(&x) => { Call(bcx, x, []); },
_ => bcx.sess().bug("unbound llvm.trap in trap")
}
let gc_metadata_name = ~"_gc_module_metadata_" + llmod_id;
- let gc_metadata = do str::as_c_str(gc_metadata_name) |buf| {
+ let gc_metadata = do gc_metadata_name.as_c_str |buf| {
unsafe {
llvm::LLVMAddGlobal(ccx.llmod, Type::i32().to_ref(), buf)
}
let sym_name = ~"_rust_crate_map_" + mapname;
let arrtype = Type::array(&int_type, n_subcrates as u64);
let maptype = Type::struct_([Type::i32(), Type::i8p(), int_type, arrtype], false);
- let map = str::as_c_str(sym_name, |buf| {
+ let map = do sym_name.as_c_str |buf| {
unsafe {
llvm::LLVMAddGlobal(llmod, maptype.to_ref(), buf)
}
- });
+ };
lib::llvm::SetLinkage(map, lib::llvm::ExternalLinkage);
return map;
}
cdata.name,
cstore::get_crate_vers(cstore, i),
cstore::get_crate_hash(cstore, i));
- let cr = str::as_c_str(nm, |buf| {
+ let cr = do nm.as_c_str |buf| {
unsafe {
llvm::LLVMAddGlobal(ccx.llmod, ccx.int_type.to_ref(), buf)
}
- });
+ };
subcrates.push(p2i(ccx, cr));
i += 1;
}
let encode_parms = crate_ctxt_to_encode_parms(cx, encode_inlined_item);
let llmeta = C_bytes(encoder::encode_metadata(encode_parms, crate));
let llconst = C_struct([llmeta]);
- let mut llglobal = str::as_c_str("rust_metadata", |buf| {
+ let mut llglobal = do "rust_metadata".as_c_str |buf| {
unsafe {
llvm::LLVMAddGlobal(cx.llmod, val_ty(llconst).to_ref(), buf)
}
- });
+ };
unsafe {
llvm::LLVMSetInitializer(llglobal, llconst);
- str::as_c_str(cx.sess.targ_cfg.target_strs.meta_sect_name, |buf| {
+ do cx.sess.targ_cfg.target_strs.meta_sect_name.as_c_str |buf| {
llvm::LLVMSetSection(llglobal, buf)
- });
+ };
lib::llvm::SetLinkage(llglobal, lib::llvm::InternalLinkage);
let t_ptr_i8 = Type::i8p();
internal: bool)
-> ValueRef {
unsafe {
- let llglobal = do str::as_c_str(name) |buf| {
+ let llglobal = do name.as_c_str |buf| {
llvm::LLVMAddGlobal(ccx.llmod, val_ty(llval).to_ref(), buf)
};
llvm::LLVMSetInitializer(llglobal, llval);
write_metadata(ccx, crate);
if ccx.sess.trans_stats() {
io::println("--- trans stats ---");
- io::println(fmt!("n_static_tydescs: %u",
- ccx.stats.n_static_tydescs));
- io::println(fmt!("n_glues_created: %u",
- ccx.stats.n_glues_created));
- io::println(fmt!("n_null_glues: %u", ccx.stats.n_null_glues));
- io::println(fmt!("n_real_glues: %u", ccx.stats.n_real_glues));
-
- io::println(fmt!("n_fns: %u", ccx.stats.n_fns));
- io::println(fmt!("n_monos: %u", ccx.stats.n_monos));
- io::println(fmt!("n_inlines: %u", ccx.stats.n_inlines));
- io::println(fmt!("n_closures: %u", ccx.stats.n_closures));
+ printfln!("n_static_tydescs: %u", ccx.stats.n_static_tydescs);
+ printfln!("n_glues_created: %u", ccx.stats.n_glues_created);
+ printfln!("n_null_glues: %u", ccx.stats.n_null_glues);
+ printfln!("n_real_glues: %u", ccx.stats.n_real_glues);
+
+ printfln!("n_fns: %u", ccx.stats.n_fns);
+ printfln!("n_monos: %u", ccx.stats.n_monos);
+ printfln!("n_inlines: %u", ccx.stats.n_inlines);
+ printfln!("n_closures: %u", ccx.stats.n_closures);
io::println("fn stats:");
do sort::quick_sort(ccx.stats.fn_stats) |&(_, _, insns_a), &(_, _, insns_b)| {
insns_a > insns_b
for ccx.stats.fn_stats.iter().advance |tuple| {
match *tuple {
(ref name, ms, insns) => {
- io::println(fmt!("%u insns, %u ms, %s", insns, ms, *name));
+ printfln!("%u insns, %u ms, %s", insns, ms, *name);
}
}
}
}
if ccx.sess.count_llvm_insns() {
for ccx.stats.llvm_insns.iter().advance |(k, v)| {
- io::println(fmt!("%-7u %s", *v, *k));
+ printfln!("%-7u %s", *v, *k);
}
}
// Function context. Every LLVM function we create will have one of
// these.
-pub struct fn_ctxt_ {
+pub struct FunctionContext {
// The ValueRef returned from a call to llvm::LLVMAddFunction; the
// address of the first instruction in the sequence of
// instructions for this function that will go in the .text
// always be Some.
llretptr: Option<ValueRef>,
- entry_bcx: Option<block>,
+ entry_bcx: Option<@mut Block>,
// These elements: "hoisted basic blocks" containing
// administrative activities that have to happen in only one place in
ccx: @mut CrateContext
}
-impl fn_ctxt_ {
+impl FunctionContext {
pub fn arg_pos(&self, arg: uint) -> uint {
if self.has_immediate_return_value {
arg + 1u
}
}
-pub type fn_ctxt = @mut fn_ctxt_;
-
pub fn warn_not_to_commit(ccx: &mut CrateContext, msg: &str) {
if !ccx.do_not_commit_warning_issued {
ccx.do_not_commit_warning_issued = true;
}
pub enum cleanup {
- clean(@fn(block) -> block, cleantype),
- clean_temp(ValueRef, @fn(block) -> block, cleantype),
+ clean(@fn(@mut Block) -> @mut Block, cleantype),
+ clean_temp(ValueRef, @fn(@mut Block) -> @mut Block, cleantype),
}
// Can't use deriving(Clone) because of the managed closure.
dest: BasicBlockRef
}
-pub fn shrink_scope_clean(scope_info: &mut scope_info, size: uint) {
+pub fn shrink_scope_clean(scope_info: &mut ScopeInfo, size: uint) {
scope_info.landing_pad = None;
scope_info.cleanup_paths = scope_info.cleanup_paths.iter()
.take_while(|&cu| cu.size <= size).transform(|&x|x).collect();
}
-pub fn grow_scope_clean(scope_info: &mut scope_info) {
+pub fn grow_scope_clean(scope_info: &mut ScopeInfo) {
scope_info.landing_pad = None;
}
}
}
-pub fn add_clean(bcx: block, val: ValueRef, t: ty::t) {
+pub fn add_clean(bcx: @mut Block, val: ValueRef, t: ty::t) {
if !ty::type_needs_drop(bcx.tcx(), t) { return; }
debug!("add_clean(%s, %s, %s)", bcx.to_str(), bcx.val_to_str(val), t.repr(bcx.tcx()));
}
}
-pub fn add_clean_temp_immediate(cx: block, val: ValueRef, ty: ty::t) {
+pub fn add_clean_temp_immediate(cx: @mut Block, val: ValueRef, ty: ty::t) {
if !ty::type_needs_drop(cx.tcx(), ty) { return; }
debug!("add_clean_temp_immediate(%s, %s, %s)",
cx.to_str(), cx.val_to_str(val),
}
}
-pub fn add_clean_temp_mem(bcx: block, val: ValueRef, t: ty::t) {
+pub fn add_clean_temp_mem(bcx: @mut Block, val: ValueRef, t: ty::t) {
add_clean_temp_mem_in_scope_(bcx, None, val, t);
}
-pub fn add_clean_temp_mem_in_scope(bcx: block, scope_id: ast::node_id, val: ValueRef, t: ty::t) {
+pub fn add_clean_temp_mem_in_scope(bcx: @mut Block,
+ scope_id: ast::node_id,
+ val: ValueRef,
+ t: ty::t) {
add_clean_temp_mem_in_scope_(bcx, Some(scope_id), val, t);
}
-pub fn add_clean_temp_mem_in_scope_(bcx: block, scope_id: Option<ast::node_id>,
+pub fn add_clean_temp_mem_in_scope_(bcx: @mut Block, scope_id: Option<ast::node_id>,
val: ValueRef, t: ty::t) {
if !ty::type_needs_drop(bcx.tcx(), t) { return; }
debug!("add_clean_temp_mem(%s, %s, %s)",
grow_scope_clean(scope_info);
}
}
-pub fn add_clean_return_to_mut(bcx: block,
+pub fn add_clean_return_to_mut(bcx: @mut Block,
scope_id: ast::node_id,
root_key: root_map_key,
frozen_val_ref: ValueRef,
grow_scope_clean(scope_info);
}
}
-pub fn add_clean_free(cx: block, ptr: ValueRef, heap: heap) {
+pub fn add_clean_free(cx: @mut Block, ptr: ValueRef, heap: heap) {
let free_fn = match heap {
heap_managed | heap_managed_unique => {
- let f: @fn(block) -> block = |a| glue::trans_free(a, ptr);
+ let f: @fn(@mut Block) -> @mut Block = |a| glue::trans_free(a, ptr);
f
}
heap_exchange | heap_exchange_closure => {
- let f: @fn(block) -> block = |a| glue::trans_exchange_free(a, ptr);
+ let f: @fn(@mut Block) -> @mut Block = |a| glue::trans_exchange_free(a, ptr);
f
}
};
// to a system where we can also cancel the cleanup on local variables, but
// this will be more involved. For now, we simply zero out the local, and the
// drop glue checks whether it is zero.
-pub fn revoke_clean(cx: block, val: ValueRef) {
+pub fn revoke_clean(cx: @mut Block, val: ValueRef) {
do in_scope_cx(cx, None) |scope_info| {
let cleanup_pos = scope_info.cleanups.iter().position(
|cu| match *cu {
}
}
-pub fn block_cleanups(bcx: block) -> ~[cleanup] {
+pub fn block_cleanups(bcx: @mut Block) -> ~[cleanup] {
match bcx.scope {
None => ~[],
Some(inf) => inf.cleanups.clone(),
}
}
-pub struct scope_info {
- parent: Option<@mut scope_info>,
- loop_break: Option<block>,
+pub struct ScopeInfo {
+ parent: Option<@mut ScopeInfo>,
+ loop_break: Option<@mut Block>,
loop_label: Option<ident>,
// A list of functions that must be run at when leaving this
// block, cleaning up any variables that were introduced in the
node_info: Option<NodeInfo>,
}
-impl scope_info {
+impl ScopeInfo {
pub fn empty_cleanups(&mut self) -> bool {
self.cleanups.is_empty()
}
// code. Each basic block we generate is attached to a function, typically
// with many basic blocks per function. All the basic blocks attached to a
// function are organized as a directed graph.
-pub struct block_ {
+pub struct Block {
// The BasicBlockRef returned from a call to
// llvm::LLVMAppendBasicBlock(llfn, name), which adds a basic
// block to the function pointed to by llfn. We insert
llbb: BasicBlockRef,
terminated: bool,
unreachable: bool,
- parent: Option<block>,
+ parent: Option<@mut Block>,
// The current scope within this basic block
- scope: Option<@mut scope_info>,
+ scope: Option<@mut ScopeInfo>,
// Is this block part of a landing pad?
is_lpad: bool,
// info about the AST node this block originated from, if any
node_info: Option<NodeInfo>,
// The function context for the function to which this block is
// attached.
- fcx: fn_ctxt
-}
+ fcx: @mut FunctionContext
+}
+
+impl Block {
+
+ pub fn new(llbb: BasicBlockRef,
+ parent: Option<@mut Block>,
+ is_lpad: bool,
+ node_info: Option<NodeInfo>,
+ fcx: @mut FunctionContext)
+ -> Block {
+ Block {
+ llbb: llbb,
+ terminated: false,
+ unreachable: false,
+ parent: parent,
+ scope: None,
+ is_lpad: is_lpad,
+ node_info: node_info,
+ fcx: fcx
+ }
+ }
+
+ pub fn ccx(&self) -> @mut CrateContext { self.fcx.ccx }
+ pub fn tcx(&self) -> ty::ctxt { self.fcx.ccx.tcx }
+ pub fn sess(&self) -> Session { self.fcx.ccx.sess }
-pub fn block_(llbb: BasicBlockRef, parent: Option<block>,
- is_lpad: bool, node_info: Option<NodeInfo>, fcx: fn_ctxt)
- -> block_ {
+ pub fn ident(&self, ident: ident) -> @str {
+ token::ident_to_str(&ident)
+ }
- block_ {
- llbb: llbb,
- terminated: false,
- unreachable: false,
- parent: parent,
- scope: None,
- is_lpad: is_lpad,
- node_info: node_info,
- fcx: fcx
+ pub fn node_id_to_str(&self, id: ast::node_id) -> ~str {
+ ast_map::node_id_to_str(self.tcx().items, id, self.sess().intr())
+ }
+
+ pub fn expr_to_str(&self, e: @ast::expr) -> ~str {
+ e.repr(self.tcx())
+ }
+
+ pub fn expr_is_lval(&self, e: &ast::expr) -> bool {
+ ty::expr_is_lval(self.tcx(), self.ccx().maps.method_map, e)
+ }
+
+ pub fn expr_kind(&self, e: &ast::expr) -> ty::ExprKind {
+ ty::expr_kind(self.tcx(), self.ccx().maps.method_map, e)
+ }
+
+ pub fn def(&self, nid: ast::node_id) -> ast::def {
+ match self.tcx().def_map.find(&nid) {
+ Some(&v) => v,
+ None => {
+ self.tcx().sess.bug(fmt!(
+ "No def associated with node id %?", nid));
+ }
+ }
+ }
+
+ pub fn val_to_str(&self, val: ValueRef) -> ~str {
+ self.ccx().tn.val_to_str(val)
+ }
+
+ pub fn llty_str(&self, ty: Type) -> ~str {
+ self.ccx().tn.type_to_str(ty)
}
-}
-pub type block = @mut block_;
+ pub fn ty_to_str(&self, t: ty::t) -> ~str {
+ t.repr(self.tcx())
+ }
-pub fn mk_block(llbb: BasicBlockRef, parent: Option<block>,
- is_lpad: bool, node_info: Option<NodeInfo>, fcx: fn_ctxt)
- -> block {
- @mut block_(llbb, parent, is_lpad, node_info, fcx)
+ pub fn to_str(&self) -> ~str {
+ unsafe {
+ match self.node_info {
+ Some(node_info) => fmt!("[block %d]", node_info.id),
+ None => fmt!("[block %x]", transmute(&*self)),
+ }
+ }
+ }
}
pub struct Result {
- bcx: block,
+ bcx: @mut Block,
val: ValueRef
}
-pub fn rslt(bcx: block, val: ValueRef) -> Result {
+pub fn rslt(bcx: @mut Block, val: ValueRef) -> Result {
Result {bcx: bcx, val: val}
}
impl Result {
- pub fn unpack(&self, bcx: &mut block) -> ValueRef {
+ pub fn unpack(&self, bcx: &mut @mut Block) -> ValueRef {
*bcx = self.bcx;
return self.val;
}
}
}
-pub fn in_scope_cx(cx: block, scope_id: Option<ast::node_id>, f: &fn(si: &mut scope_info)) {
+pub fn in_scope_cx(cx: @mut Block, scope_id: Option<ast::node_id>, f: &fn(si: &mut ScopeInfo)) {
let mut cur = cx;
let mut cur_scope = cur.scope;
loop {
}
}
-pub fn block_parent(cx: block) -> block {
+pub fn block_parent(cx: @mut Block) -> @mut Block {
match cx.parent {
Some(b) => b,
None => cx.sess().bug(fmt!("block_parent called on root block %?",
}
}
-// Accessors
-
-impl block_ {
- pub fn ccx(&self) -> @mut CrateContext { self.fcx.ccx }
- pub fn tcx(&self) -> ty::ctxt { self.fcx.ccx.tcx }
- pub fn sess(&self) -> Session { self.fcx.ccx.sess }
-
- pub fn ident(&self, ident: ident) -> @str {
- token::ident_to_str(&ident)
- }
-
- pub fn node_id_to_str(&self, id: ast::node_id) -> ~str {
- ast_map::node_id_to_str(self.tcx().items, id, self.sess().intr())
- }
-
- pub fn expr_to_str(&self, e: @ast::expr) -> ~str {
- e.repr(self.tcx())
- }
-
- pub fn expr_is_lval(&self, e: &ast::expr) -> bool {
- ty::expr_is_lval(self.tcx(), self.ccx().maps.method_map, e)
- }
-
- pub fn expr_kind(&self, e: &ast::expr) -> ty::ExprKind {
- ty::expr_kind(self.tcx(), self.ccx().maps.method_map, e)
- }
-
- pub fn def(&self, nid: ast::node_id) -> ast::def {
- match self.tcx().def_map.find(&nid) {
- Some(&v) => v,
- None => {
- self.tcx().sess.bug(fmt!(
- "No def associated with node id %?", nid));
- }
- }
- }
-
- pub fn val_to_str(&self, val: ValueRef) -> ~str {
- self.ccx().tn.val_to_str(val)
- }
-
- pub fn llty_str(&self, ty: Type) -> ~str {
- self.ccx().tn.type_to_str(ty)
- }
-
- pub fn ty_to_str(&self, t: ty::t) -> ~str {
- t.repr(self.tcx())
- }
-
- pub fn to_str(&self) -> ~str {
- unsafe {
- match self.node_info {
- Some(node_info) => fmt!("[block %d]", node_info.id),
- None => fmt!("[block %x]", transmute(&*self)),
- }
- }
- }
-}
// Let T be the content of a box @T. tuplify_box_ty(t) returns the
// representation of @T as a tuple (i.e., the ty::t version of what T_box()
}
}
- // Returns a Plain Old LLVM String:
- pub fn C_postr(s: &str) -> ValueRef {
- unsafe {
- do s.as_c_str |buf| {
- llvm::LLVMConstStringInContext(base::task_llcx(), buf, s.len() as c_uint, False)
- }
- }
- }
-
pub fn C_zero_byte_arr(size: uint) -> ValueRef {
unsafe {
let mut i = 0u;
}
}
- pub fn C_bytes_plus_null(bytes: &[u8]) -> ValueRef {
- unsafe {
- return llvm::LLVMConstStringInContext(base::task_llcx(),
- cast::transmute(vec::raw::to_ptr(bytes)),
- bytes.len() as c_uint, False);
- }
- }
-
pub fn get_param(fndecl: ValueRef, param: uint) -> ValueRef {
unsafe {
llvm::LLVMGetParam(fndecl, param as c_uint)
pub type mono_id = @mono_id_;
-pub fn umax(cx: block, a: ValueRef, b: ValueRef) -> ValueRef {
+pub fn umax(cx: @mut Block, a: ValueRef, b: ValueRef) -> ValueRef {
let cond = build::ICmp(cx, lib::llvm::IntULT, a, b);
return build::Select(cx, cond, b, a);
}
-pub fn umin(cx: block, a: ValueRef, b: ValueRef) -> ValueRef {
+pub fn umin(cx: @mut Block, a: ValueRef, b: ValueRef) -> ValueRef {
let cond = build::ICmp(cx, lib::llvm::IntULT, a, b);
return build::Select(cx, cond, a, b);
}
-pub fn align_to(cx: block, off: ValueRef, align: ValueRef) -> ValueRef {
+pub fn align_to(cx: @mut Block, off: ValueRef, align: ValueRef) -> ValueRef {
let mask = build::Sub(cx, align, C_int(cx.ccx(), 1));
let bumped = build::Add(cx, off, mask);
return build::And(cx, bumped, build::Not(cx, mask));
r
}
-pub fn monomorphize_type(bcx: block, t: ty::t) -> ty::t {
+pub fn monomorphize_type(bcx: @mut Block, t: ty::t) -> ty::t {
match bcx.fcx.param_substs {
Some(substs) => {
ty::subst_tps(bcx.tcx(), substs.tys, substs.self_ty, t)
}
}
-pub fn node_id_type(bcx: block, id: ast::node_id) -> ty::t {
+pub fn node_id_type(bcx: @mut Block, id: ast::node_id) -> ty::t {
let tcx = bcx.tcx();
let t = ty::node_id_to_type(tcx, id);
monomorphize_type(bcx, t)
}
-pub fn expr_ty(bcx: block, ex: &ast::expr) -> ty::t {
+pub fn expr_ty(bcx: @mut Block, ex: &ast::expr) -> ty::t {
node_id_type(bcx, ex.id)
}
-pub fn expr_ty_adjusted(bcx: block, ex: &ast::expr) -> ty::t {
+pub fn expr_ty_adjusted(bcx: @mut Block, ex: &ast::expr) -> ty::t {
let tcx = bcx.tcx();
let t = ty::expr_ty_adjusted(tcx, ex);
monomorphize_type(bcx, t)
}
-pub fn node_id_type_params(bcx: block, id: ast::node_id) -> ~[ty::t] {
+pub fn node_id_type_params(bcx: @mut Block, id: ast::node_id) -> ~[ty::t] {
let tcx = bcx.tcx();
let params = ty::node_id_to_type_params(tcx, id);
}
}
-pub fn node_vtables(bcx: block, id: ast::node_id)
+pub fn node_vtables(bcx: @mut Block, id: ast::node_id)
-> Option<typeck::vtable_res> {
let raw_vtables = bcx.ccx().maps.vtable_map.find(&id);
raw_vtables.map(
|&vts| resolve_vtables_in_fn_ctxt(bcx.fcx, *vts))
}
-pub fn resolve_vtables_in_fn_ctxt(fcx: fn_ctxt, vts: typeck::vtable_res)
+pub fn resolve_vtables_in_fn_ctxt(fcx: &FunctionContext, vts: typeck::vtable_res)
-> typeck::vtable_res {
resolve_vtables_under_param_substs(fcx.ccx.tcx,
fcx.param_substs,
}
-// Apply the typaram substitutions in the fn_ctxt to a vtable. This should
+// Apply the typaram substitutions in the FunctionContext to a vtable. This should
// eliminate any vtable_params.
-pub fn resolve_vtable_in_fn_ctxt(fcx: fn_ctxt, vt: &typeck::vtable_origin)
+pub fn resolve_vtable_in_fn_ctxt(fcx: &FunctionContext, vt: &typeck::vtable_origin)
-> typeck::vtable_origin {
resolve_vtable_under_param_substs(fcx.ccx.tcx,
fcx.param_substs,
}
}
-pub fn filename_and_line_num_from_span(bcx: block,
+pub fn filename_and_line_num_from_span(bcx: @mut Block,
span: span) -> (ValueRef, ValueRef) {
let loc = bcx.sess().parse_sess.cm.lookup_char_pos(span.lo);
let filename_cstr = C_cstr(bcx.ccx(), loc.file.name);
}
// Casts a Rust bool value to an i1.
-pub fn bool_to_i1(bcx: block, llval: ValueRef) -> ValueRef {
+pub fn bool_to_i1(bcx: @mut Block, llval: ValueRef) -> ValueRef {
build::ICmp(bcx, lib::llvm::IntNE, llval, C_bool(false))
}
-pub fn langcall(bcx: block, span: Option<span>, msg: &str,
+pub fn langcall(bcx: @mut Block, span: Option<span>, msg: &str,
li: LangItem) -> ast::def_id {
match bcx.tcx().lang_items.require(li) {
Ok(id) => id,
use middle::trans::type_::Type;
- use std::str;
use syntax::ast;
use syntax::ast::ident;
use syntax::ast_map::path_mod;
use syntax::ast_util;
use syntax::codemap::span;
-pub fn trans_block(bcx: block, b: &ast::Block, dest: expr::Dest) -> block {
+pub fn trans_block(bcx: @mut Block, b: &ast::Block, dest: expr::Dest) -> @mut Block {
let _icx = push_ctxt("trans_block");
let mut bcx = bcx;
for b.stmts.iter().advance |s| {
return bcx;
}
-pub fn trans_if(bcx: block,
+pub fn trans_if(bcx: @mut Block,
cond: @ast::expr,
thn: &ast::Block,
els: Option<@ast::expr>,
dest: expr::Dest)
- -> block {
+ -> @mut Block {
debug!("trans_if(bcx=%s, cond=%s, thn=%?, dest=%s)",
bcx.to_str(), bcx.expr_to_str(cond), thn.id,
dest.to_str(bcx.ccx()));
return next_bcx;
// trans `else [ if { .. } ... | { .. } ]`
- fn trans_if_else(bcx: block, elexpr: @ast::expr,
- dest: expr::Dest, scope_name: &str) -> (block, block) {
+ fn trans_if_else(bcx: @mut Block, elexpr: @ast::expr,
+ dest: expr::Dest, scope_name: &str) -> (@mut Block, @mut Block) {
let else_bcx_in = scope_block(bcx, elexpr.info(), scope_name);
let else_bcx_out = match elexpr.node {
ast::expr_if(_, _, _) => {
}
}
-pub fn join_blocks(parent_bcx: block, in_cxs: &[block]) -> block {
+pub fn join_blocks(parent_bcx: @mut Block, in_cxs: &[@mut Block]) -> @mut Block {
let out = sub_block(parent_bcx, "join");
let mut reachable = false;
for in_cxs.iter().advance |bcx| {
return out;
}
-pub fn trans_while(bcx: block, cond: @ast::expr, body: &ast::Block) -> block {
+pub fn trans_while(bcx: @mut Block, cond: @ast::expr, body: &ast::Block) -> @mut Block {
let _icx = push_ctxt("trans_while");
let next_bcx = sub_block(bcx, "while next");
return next_bcx;
}
-pub fn trans_loop(bcx:block,
+pub fn trans_loop(bcx:@mut Block,
body: &ast::Block,
opt_label: Option<ident>)
- -> block {
+ -> @mut Block {
let _icx = push_ctxt("trans_loop");
let next_bcx = sub_block(bcx, "next");
let body_bcx_in = loop_scope_block(bcx, next_bcx, opt_label, "`loop`",
pub fn trans_log(log_ex: &ast::expr,
lvl: @ast::expr,
- bcx: block,
- e: @ast::expr) -> block {
+ bcx: @mut Block,
+ e: @ast::expr) -> @mut Block {
let _icx = push_ctxt("trans_log");
let ccx = bcx.ccx();
let mut bcx = bcx;
ccx, modpath, "loglevel");
let global;
unsafe {
- global = str::as_c_str(s, |buf| {
+ global = do s.as_c_str |buf| {
llvm::LLVMAddGlobal(ccx.llmod, Type::i32().to_ref(), buf)
- });
+ };
llvm::LLVMSetGlobalConstant(global, False);
llvm::LLVMSetInitializer(global, C_null(Type::i32()));
lib::llvm::SetLinkage(global, lib::llvm::InternalLinkage);
}
}
-pub fn trans_break_cont(bcx: block,
+pub fn trans_break_cont(bcx: @mut Block,
opt_label: Option<ident>,
to_end: bool)
- -> block {
+ -> @mut Block {
let _icx = push_ctxt("trans_break_cont");
// Locate closest loop block, outputting cleanup as we go.
let mut unwind = bcx;
let mut target;
loop {
cur_scope = match cur_scope {
- Some(@scope_info {
+ Some(@ScopeInfo {
loop_break: Some(brk),
loop_label: l,
parent,
return bcx;
}
-pub fn trans_break(bcx: block, label_opt: Option<ident>) -> block {
+pub fn trans_break(bcx: @mut Block, label_opt: Option<ident>) -> @mut Block {
return trans_break_cont(bcx, label_opt, true);
}
-pub fn trans_cont(bcx: block, label_opt: Option<ident>) -> block {
+pub fn trans_cont(bcx: @mut Block, label_opt: Option<ident>) -> @mut Block {
return trans_break_cont(bcx, label_opt, false);
}
-pub fn trans_ret(bcx: block, e: Option<@ast::expr>) -> block {
+pub fn trans_ret(bcx: @mut Block, e: Option<@ast::expr>) -> @mut Block {
let _icx = push_ctxt("trans_ret");
let mut bcx = bcx;
let dest = match bcx.fcx.loop_ret {
return bcx;
}
-pub fn trans_fail_expr(bcx: block,
+pub fn trans_fail_expr(bcx: @mut Block,
sp_opt: Option<span>,
fail_expr: Option<@ast::expr>)
- -> block {
+ -> @mut Block {
let _icx = push_ctxt("trans_fail_expr");
let mut bcx = bcx;
match fail_expr {
}
}
-pub fn trans_fail(bcx: block,
+pub fn trans_fail(bcx: @mut Block,
sp_opt: Option<span>,
fail_str: @str)
- -> block {
+ -> @mut Block {
let _icx = push_ctxt("trans_fail");
let V_fail_str = C_cstr(bcx.ccx(), fail_str);
return trans_fail_value(bcx, sp_opt, V_fail_str);
}
-fn trans_fail_value(bcx: block,
+fn trans_fail_value(bcx: @mut Block,
sp_opt: Option<span>,
V_fail_str: ValueRef)
- -> block {
+ -> @mut Block {
let _icx = push_ctxt("trans_fail_value");
let ccx = bcx.ccx();
let (V_filename, V_line) = match sp_opt {
return bcx;
}
-pub fn trans_fail_bounds_check(bcx: block, sp: span,
- index: ValueRef, len: ValueRef) -> block {
+pub fn trans_fail_bounds_check(bcx: @mut Block, sp: span,
+ index: ValueRef, len: ValueRef) -> @mut Block {
let _icx = push_ctxt("trans_fail_bounds_check");
let (filename, line) = filename_and_line_num_from_span(bcx, sp);
let args = ~[filename, line, index, len];
use std::hashmap::HashMap;
use std::libc::{c_uint, c_ulonglong, c_longlong};
use std::ptr;
- use std::str::as_c_str;
use std::vec;
use syntax::codemap::span;
use syntax::{ast, codemap, ast_util, ast_map};
///
/// Adds the created metadata nodes directly to the crate's IR.
/// The return value should be ignored if called from outside of the debuginfo module.
-pub fn create_local_var_metadata(bcx: block, local: @ast::Local) -> DIVariable {
+pub fn create_local_var_metadata(bcx: @mut Block, local: @ast::Local) -> DIVariable {
let cx = bcx.ccx();
let ident = match local.pat.node {
Some(_) => lexical_block_metadata(bcx)
};
- let var_metadata = do as_c_str(name) |name| {
+ let var_metadata = do name.as_c_str |name| {
unsafe {
llvm::LLVMDIBuilderCreateLocalVariable(
DIB(cx),
///
/// Adds the created metadata nodes directly to the crate's IR.
/// The return value should be ignored if called from outside of the debuginfo module.
-pub fn create_argument_metadata(bcx: block, arg: &ast::arg, span: span) -> Option<DIVariable> {
+pub fn create_argument_metadata(bcx: @mut Block, arg: &ast::arg, span: span) -> Option<DIVariable> {
debug!("create_argument_metadata");
if true {
// XXX create_argument_metadata disabled for now because "node_id_type(bcx, arg.id)" below
// XXX: This is wrong; it should work for multiple bindings.
let ident = path.idents.last();
let name: &str = cx.sess.str_of(*ident);
- let var_metadata = do as_c_str(name) |name| {
+ let var_metadata = do name.as_c_str |name| {
unsafe {
llvm::LLVMDIBuilderCreateLocalVariable(
DIB(cx),
/// Sets the current debug location at the beginning of the span
///
/// Maps to a call to llvm::LLVMSetCurrentDebugLocation(...)
-pub fn update_source_pos(bcx: block, span: span) {
+pub fn update_source_pos(bcx: @mut Block, span: span) {
if !bcx.sess().opts.debuginfo || (*span.lo == 0 && *span.hi == 0) {
return;
}
///
/// Adds the created metadata nodes directly to the crate's IR.
/// The return value should be ignored if called from outside of the debuginfo module.
-pub fn create_function_metadata(fcx: fn_ctxt) -> DISubprogram {
+pub fn create_function_metadata(fcx: &FunctionContext) -> DISubprogram {
let cx = fcx.ccx;
- let fcx = &mut *fcx;
let span = fcx.span.get();
let fnitem = cx.tcx.items.get_copy(&fcx.id);
};
let fn_metadata =
- do as_c_str(cx.sess.str_of(ident)) |name| {
- do as_c_str(cx.sess.str_of(ident)) |linkage| {
+ do cx.sess.str_of(ident).as_c_str |name| {
+ do cx.sess.str_of(ident).as_c_str |linkage| {
unsafe {
llvm::LLVMDIBuilderCreateFunction(
DIB(cx),
let work_dir = cx.sess.working_dir.to_str();
let producer = fmt!("rustc version %s", env!("CFG_VERSION"));
- do as_c_str(crate_name) |crate_name| {
- do as_c_str(work_dir) |work_dir| {
- do as_c_str(producer) |producer| {
- do as_c_str("") |flags| {
- do as_c_str("") |split_name| {
+ do crate_name.as_c_str |crate_name| {
+ do work_dir.as_c_str |work_dir| {
+ do producer.as_c_str |producer| {
+ do "".as_c_str |flags| {
+ do "".as_c_str |split_name| {
unsafe {
llvm::LLVMDIBuilderCreateCompileUnit(dcx.builder,
DW_LANG_RUST as c_uint, crate_name, work_dir, producer,
};
let file_metadata =
- do as_c_str(file_name) |file_name| {
- do as_c_str(work_dir) |work_dir| {
+ do file_name.as_c_str |file_name| {
+ do work_dir.as_c_str |work_dir| {
unsafe {
llvm::LLVMDIBuilderCreateFile(DIB(cx), file_name, work_dir)
}
}
/// Get or create the lexical block metadata node for the given LLVM basic block.
-fn lexical_block_metadata(bcx: block) -> DILexicalBlock {
+fn lexical_block_metadata(bcx: @mut Block) -> DILexicalBlock {
let cx = bcx.ccx();
let mut bcx = bcx;
let llvm_type = type_of::type_of(cx, t);
let (size, align) = size_and_align_of(cx, llvm_type);
- let ty_metadata = do as_c_str(name) |name| {
+ let ty_metadata = do name.as_c_str |name| {
unsafe {
llvm::LLVMDIBuilderCreateBasicType(
DIB(cx),
let pointer_llvm_type = type_of::type_of(cx, pointer_type);
let (pointer_size, pointer_align) = size_and_align_of(cx, pointer_llvm_type);
let name = ty_to_str(cx.tcx, pointer_type);
- let ptr_metadata = do as_c_str(name) |name| {
+ let ptr_metadata = do name.as_c_str |name| {
unsafe {
llvm::LLVMDIBuilderCreatePointerType(
DIB(cx),
debug!("unimplemented_type_metadata: %?", ty::get(t));
let name = ty_to_str(cx.tcx, t);
- let metadata = do as_c_str(fmt!("NYI<%s>", name)) |name| {
+ let metadata = do fmt!("NYI<%s>", name).as_c_str |name| {
unsafe {
llvm::LLVMDIBuilderCreateBasicType(
DIB(cx),
use middle::trans::type_::Type;
-use std::io;
use std::libc::c_uint;
- use std::str;
use syntax::ast;
-pub fn trans_free(cx: block, v: ValueRef) -> block {
+pub fn trans_free(cx: @mut Block, v: ValueRef) -> @mut Block {
let _icx = push_ctxt("trans_free");
callee::trans_lang_call(cx,
langcall(cx, None, "", FreeFnLangItem),
Some(expr::Ignore)).bcx
}
-pub fn trans_exchange_free(cx: block, v: ValueRef) -> block {
+pub fn trans_exchange_free(cx: @mut Block, v: ValueRef) -> @mut Block {
let _icx = push_ctxt("trans_exchange_free");
callee::trans_lang_call(cx,
langcall(cx, None, "", ExchangeFreeFnLangItem),
Some(expr::Ignore)).bcx
}
-pub fn take_ty(cx: block, v: ValueRef, t: ty::t) -> block {
+pub fn take_ty(cx: @mut Block, v: ValueRef, t: ty::t) -> @mut Block {
// NB: v is an *alias* of type t here, not a direct value.
let _icx = push_ctxt("take_ty");
if ty::type_needs_drop(cx.tcx(), t) {
return cx;
}
-pub fn drop_ty(cx: block, v: ValueRef, t: ty::t) -> block {
+pub fn drop_ty(cx: @mut Block, v: ValueRef, t: ty::t) -> @mut Block {
// NB: v is an *alias* of type t here, not a direct value.
let _icx = push_ctxt("drop_ty");
if ty::type_needs_drop(cx.tcx(), t) {
return cx;
}
-pub fn drop_ty_immediate(bcx: block, v: ValueRef, t: ty::t) -> block {
+pub fn drop_ty_immediate(bcx: @mut Block, v: ValueRef, t: ty::t) -> @mut Block {
let _icx = push_ctxt("drop_ty_immediate");
match ty::get(t).sty {
ty::ty_uniq(_)
}
}
-pub fn free_ty(cx: block, v: ValueRef, t: ty::t) -> block {
+pub fn free_ty(cx: @mut Block, v: ValueRef, t: ty::t) -> @mut Block {
// NB: v is an *alias* of type t here, not a direct value.
let _icx = push_ctxt("free_ty");
if ty::type_needs_drop(cx.tcx(), t) {
return cx;
}
-pub fn free_ty_immediate(bcx: block, v: ValueRef, t: ty::t) -> block {
+pub fn free_ty_immediate(bcx: @mut Block, v: ValueRef, t: ty::t) -> @mut Block {
let _icx = push_ctxt("free_ty_immediate");
match ty::get(t).sty {
ty::ty_uniq(_) |
}
// See [Note-arg-mode]
-pub fn call_tydesc_glue_full(bcx: block,
+pub fn call_tydesc_glue_full(bcx: @mut Block,
v: ValueRef,
tydesc: ValueRef,
field: uint,
}
// See [Note-arg-mode]
-pub fn call_tydesc_glue(cx: block, v: ValueRef, t: ty::t, field: uint)
- -> block {
+pub fn call_tydesc_glue(cx: @mut Block, v: ValueRef, t: ty::t, field: uint)
+ -> @mut Block {
let _icx = push_ctxt("call_tydesc_glue");
let ti = get_tydesc(cx.ccx(), t);
call_tydesc_glue_full(cx, v, ti.tydesc, field, Some(ti));
return cx;
}
-pub fn make_visit_glue(bcx: block, v: ValueRef, t: ty::t) -> block {
+pub fn make_visit_glue(bcx: @mut Block, v: ValueRef, t: ty::t) -> @mut Block {
let _icx = push_ctxt("make_visit_glue");
do with_scope(bcx, None, "visitor cleanup") |bcx| {
let mut bcx = bcx;
}
}
-pub fn make_free_glue(bcx: block, v: ValueRef, t: ty::t) -> block {
+pub fn make_free_glue(bcx: @mut Block, v: ValueRef, t: ty::t) -> @mut Block {
// NB: v0 is an *alias* of type t here, not a direct value.
let _icx = push_ctxt("make_free_glue");
match ty::get(t).sty {
}
}
-pub fn trans_struct_drop_flag(bcx: block, t: ty::t, v0: ValueRef, dtor_did: ast::def_id,
- class_did: ast::def_id, substs: &ty::substs) -> block {
+pub fn trans_struct_drop_flag(bcx: @mut Block, t: ty::t, v0: ValueRef, dtor_did: ast::def_id,
+ class_did: ast::def_id, substs: &ty::substs) -> @mut Block {
let repr = adt::represent_type(bcx.ccx(), t);
let drop_flag = adt::trans_drop_flag_ptr(bcx, repr, v0);
do with_cond(bcx, IsNotNull(bcx, Load(bcx, drop_flag))) |cx| {
}
}
-pub fn trans_struct_drop(mut bcx: block, t: ty::t, v0: ValueRef, dtor_did: ast::def_id,
- class_did: ast::def_id, substs: &ty::substs) -> block {
+pub fn trans_struct_drop(mut bcx: @mut Block, t: ty::t, v0: ValueRef, dtor_did: ast::def_id,
+ class_did: ast::def_id, substs: &ty::substs) -> @mut Block {
let repr = adt::represent_type(bcx.ccx(), t);
// Find and call the actual destructor
bcx
}
-pub fn make_drop_glue(bcx: block, v0: ValueRef, t: ty::t) -> block {
+pub fn make_drop_glue(bcx: @mut Block, v0: ValueRef, t: ty::t) -> @mut Block {
// NB: v0 is an *alias* of type t here, not a direct value.
let _icx = push_ctxt("make_drop_glue");
let ccx = bcx.ccx();
}
// box_ptr_ptr is optional, it is constructed if not supplied.
-pub fn decr_refcnt_maybe_free(bcx: block, box_ptr: ValueRef,
+pub fn decr_refcnt_maybe_free(bcx: @mut Block, box_ptr: ValueRef,
box_ptr_ptr: Option<ValueRef>,
t: ty::t)
- -> block {
+ -> @mut Block {
let _icx = push_ctxt("decr_refcnt_maybe_free");
let ccx = bcx.ccx();
}
-pub fn make_take_glue(bcx: block, v: ValueRef, t: ty::t) -> block {
+pub fn make_take_glue(bcx: @mut Block, v: ValueRef, t: ty::t) -> @mut Block {
let _icx = push_ctxt("make_take_glue");
// NB: v is a *pointer* to type t here, not a direct value.
match ty::get(t).sty {
}
}
-pub fn incr_refcnt_of_boxed(cx: block, box_ptr: ValueRef) {
+pub fn incr_refcnt_of_boxed(cx: @mut Block, box_ptr: ValueRef) {
let _icx = push_ctxt("incr_refcnt_of_boxed");
let ccx = cx.ccx();
let rc_ptr = GEPi(cx, box_ptr, [0u, abi::box_field_refcnt]);
let llty = type_of(ccx, t);
if ccx.sess.count_type_sizes() {
- io::println(fmt!("%u\t%s", llsize_of_real(ccx, llty),
- ppaux::ty_to_str(ccx.tcx, t)));
+ printfln!("%u\t%s", llsize_of_real(ccx, llty),
+ ppaux::ty_to_str(ccx.tcx, t));
}
let llsize = llsize_of(ccx, llty);
let name = mangle_internal_name_by_type_and_seq(ccx, t, "tydesc").to_managed();
note_unique_llvm_symbol(ccx, name);
debug!("+++ declare_tydesc %s %s", ppaux::ty_to_str(ccx.tcx, t), name);
- let gvar = str::as_c_str(name, |buf| {
+ let gvar = do name.as_c_str |buf| {
unsafe {
llvm::LLVMAddGlobal(ccx.llmod, ccx.tydesc_type.to_ref(), buf)
}
- });
+ };
let inf = @mut tydesc_info {
ty: t,
tydesc: gvar,
return inf;
}
-pub type glue_helper<'self> = &'self fn(block, ValueRef, ty::t) -> block;
+pub type glue_helper<'self> = &'self fn(@mut Block, ValueRef, ty::t) -> @mut Block;
pub fn declare_generic_glue(ccx: &mut CrateContext, t: ty::t, llfnty: Type,
name: &str) -> ValueRef {
*/
use at_vec;
- use cast::transmute;
use cast;
use char;
use char::Char;
use to_str::ToStr;
use uint;
use vec;
- use vec::{OwnedVector, OwnedCopyableVector, ImmutableVector};
+ use vec::{OwnedVector, OwnedCopyableVector, ImmutableVector, MutableVector};
/*
Section: Conditions
}
}
- /// Copy a slice into a new unique str
- #[inline]
- pub fn to_owned(s: &str) -> ~str {
- unsafe { raw::slice_bytes_owned(s, 0, s.len()) }
- }
-
impl ToStr for ~str {
#[inline]
- fn to_str(&self) -> ~str { to_owned(*self) }
+ fn to_str(&self) -> ~str { self.to_owned() }
}
impl<'self> ToStr for &'self str {
#[inline]
- fn to_str(&self) -> ~str { to_owned(*self) }
+ fn to_str(&self) -> ~str { self.to_owned() }
}
impl ToStr for @str {
#[inline]
- fn to_str(&self) -> ~str { to_owned(*self) }
+ fn to_str(&self) -> ~str { self.to_owned() }
}
/**
let len = self.iter().transform(|s| s.as_slice().len()).sum();
- let mut s = ~"";
-
- s.reserve(len);
+ let mut s = with_capacity(len);
unsafe {
- do as_buf(s) |buf, _| {
- let mut buf = ::cast::transmute_mut_unsafe(buf);
+ do s.as_mut_buf |buf, _| {
+ let mut buf = buf;
for self.iter().advance |ss| {
- do as_buf(ss.as_slice()) |ssbuf, sslen| {
+ do ss.as_slice().as_imm_buf |ssbuf, sslen| {
let sslen = sslen - 1;
ptr::copy_memory(buf, ssbuf, sslen);
buf = buf.offset(sslen);
s.reserve(len);
unsafe {
- do as_buf(s) |buf, _| {
- do as_buf(sep) |sepbuf, seplen| {
+ do s.as_mut_buf |buf, _| {
+ do sep.as_imm_buf |sepbuf, seplen| {
let seplen = seplen - 1;
let mut buf = ::cast::transmute_mut_unsafe(buf);
for self.iter().advance |ss| {
- do as_buf(ss.as_slice()) |ssbuf, sslen| {
+ do ss.as_slice().as_imm_buf |ssbuf, sslen| {
let sslen = sslen - 1;
if first {
first = false;
#[lang="str_eq"]
#[inline]
pub fn eq_slice(a: &str, b: &str) -> bool {
- do as_buf(a) |ap, alen| {
- do as_buf(b) |bp, blen| {
+ do a.as_imm_buf |ap, alen| {
+ do b.as_imm_buf |bp, blen| {
if (alen != blen) { false }
else {
unsafe {
#[cfg(test)]
#[inline]
pub fn eq_slice(a: &str, b: &str) -> bool {
- do as_buf(a) |ap, alen| {
- do as_buf(b) |bp, blen| {
+ do a.as_imm_buf |ap, alen| {
+ do b.as_imm_buf |bp, blen| {
if (alen != blen) { false }
else {
unsafe {
* Allocates a new string with the specified capacity. The string returned is
* the empty string, but has capacity for much more.
*/
+ #[inline]
pub fn with_capacity(capacity: uint) -> ~str {
let mut buf = ~"";
buf.reserve(capacity);
static MAX_THREE_B: uint = 65536u;
static TAG_FOUR_B: uint = 240u;
- /**
- * A dummy trait to hold all the utility methods that we implement on strings.
- */
- pub trait StrUtil {
- /**
- * Work with the byte buffer of a string as a null-terminated C string.
- *
- * Allows for unsafe manipulation of strings, which is useful for foreign
- * interop. This is similar to `str::as_buf`, but guarantees null-termination.
- * If the given slice is not already null-terminated, this function will
- * allocate a temporary, copy the slice, null terminate it, and pass
- * that instead.
- *
- * # Example
- *
- * ~~~ {.rust}
- * let s = "PATH".as_c_str(|path| libc::getenv(path));
- * ~~~
- */
- fn as_c_str<T>(self, f: &fn(*libc::c_char) -> T) -> T;
- }
-
- impl<'self> StrUtil for &'self str {
- #[inline]
- fn as_c_str<T>(self, f: &fn(*libc::c_char) -> T) -> T {
- do as_buf(self) |buf, len| {
- // NB: len includes the trailing null.
- assert!(len > 0);
- if unsafe { *(ptr::offset(buf,len-1)) != 0 } {
- to_owned(self).as_c_str(|s| f(s))
- } else {
- f(buf as *libc::c_char)
- }
- }
- }
- }
-
- /**
- * Deprecated. Use the `as_c_str` method on strings instead.
- */
- #[inline]
- pub fn as_c_str<T>(s: &str, f: &fn(*libc::c_char) -> T) -> T {
- s.as_c_str(f)
- }
-
- /**
- * Work with the byte buffer and length of a slice.
- *
- * The given length is one byte longer than the 'official' indexable
- * length of the string. This is to permit probing the byte past the
- * indexable area for a null byte, as is the case in slices pointing
- * to full strings, or suffixes of them.
- */
- #[inline]
- pub fn as_buf<T>(s: &str, f: &fn(*u8, uint) -> T) -> T {
- unsafe {
- let v : *(*u8,uint) = transmute(&s);
- let (buf,len) = *v;
- f(buf, len)
- }
- }
-
/// Unsafe operations
pub mod raw {
use cast;
use libc;
use ptr;
use str::raw;
- use str::{as_buf, is_utf8};
+ use str::{is_utf8};
use vec;
use vec::MutableVector;
::cast::transmute(v)
}
- /**
- * Takes a bytewise (not UTF-8) slice from a string.
- *
- * Returns the substring from [`begin`..`end`).
- *
- * # Failure
- *
- * If begin is greater than end.
- * If end is greater than the length of the string.
- */
- pub unsafe fn slice_bytes_owned(s: &str, begin: uint, end: uint) -> ~str {
- do as_buf(s) |sbuf, n| {
- assert!((begin <= end));
- assert!((end <= n));
-
- let mut v = vec::with_capacity(end - begin + 1u);
- do v.as_imm_buf |vbuf, _vlen| {
- let vbuf = ::cast::transmute_mut_unsafe(vbuf);
- let src = ptr::offset(sbuf, begin);
- ptr::copy_memory(vbuf, src, end - begin);
- }
- vec::raw::set_len(&mut v, end - begin);
- v.push(0u8);
- ::cast::transmute(v)
- }
- }
-
/**
* Takes a bytewise (not UTF-8) slice from a string.
*
*/
#[inline]
pub unsafe fn slice_bytes(s: &str, begin: uint, end: uint) -> &str {
- do as_buf(s) |sbuf, n| {
+ do s.as_imm_buf |sbuf, n| {
assert!((begin <= end));
assert!((end <= n));
pub unsafe fn push_byte(s: &mut ~str, b: u8) {
let new_len = s.len() + 1;
s.reserve_at_least(new_len);
- do as_buf(*s) |buf, len| {
- let buf: *mut u8 = ::cast::transmute(buf);
+ do s.as_mut_buf |buf, len| {
*ptr::mut_offset(buf, len) = b;
}
set_len(&mut *s, new_len);
let len = s.len();
assert!((len > 0u));
let b = s[0];
- *s = raw::slice_bytes_owned(*s, 1u, len);
+ *s = s.slice(1, len).to_owned();
return b;
}
impl<'self> Container for &'self str {
#[inline]
fn len(&self) -> uint {
- do as_buf(*self) |_p, n| { n - 1u }
+ do self.as_imm_buf |_p, n| { n - 1u }
}
#[inline]
fn is_empty(&self) -> bool {
fn lev_distance(&self, t: &str) -> uint;
fn subslice_offset(&self, inner: &str) -> uint;
+
+ fn as_imm_buf<T>(&self, f: &fn(*u8, uint) -> T) -> T;
+ fn as_c_str<T>(&self, f: &fn(*libc::c_char) -> T) -> T;
}
/// Extension methods for strings
/// Copy a slice into a new unique str
#[inline]
- fn to_owned(&self) -> ~str { to_owned(*self) }
+ fn to_owned(&self) -> ~str {
+ do self.as_imm_buf |src, len| {
+ assert!(len > 0);
+ unsafe {
+ let mut v = vec::with_capacity(len);
+
+ do v.as_mut_buf |dst, _| {
+ ptr::copy_memory(dst, src, len - 1);
+ }
+ vec::raw::set_len(&mut v, len - 1);
+ v.push(0u8);
+ ::cast::transmute(v)
+ }
+ }
+ }
#[inline]
fn to_managed(&self) -> @str {
* let i = 0u;
* while i < s.len() {
* let CharRange {ch, next} = s.char_range_at(i);
- * std::io::println(fmt!("%u: %c",i,ch));
+ * printfln!("%u: %c", i, ch);
* i = next;
* }
* ~~~
/// Given a string, make a new string with repeated copies of it.
fn repeat(&self, nn: uint) -> ~str {
- do as_buf(*self) |buf, len| {
- let mut ret = ~"";
+ do self.as_imm_buf |buf, len| {
// ignore the NULL terminator
let len = len - 1;
- ret.reserve(nn * len);
+ let mut ret = with_capacity(nn * len);
unsafe {
- do as_buf(ret) |rbuf, _len| {
- let mut rbuf = ::cast::transmute_mut_unsafe(rbuf);
+ do ret.as_mut_buf |rbuf, _len| {
+ let mut rbuf = rbuf;
for nn.times {
ptr::copy_memory(rbuf, buf, len);
*/
#[inline]
fn subslice_offset(&self, inner: &str) -> uint {
- do as_buf(*self) |a, a_len| {
- do as_buf(inner) |b, b_len| {
+ do self.as_imm_buf |a, a_len| {
+ do inner.as_imm_buf |b, b_len| {
let a_start: uint;
let a_end: uint;
let b_start: uint;
}
}
+ /**
+ * Work with the byte buffer and length of a slice.
+ *
+ * The given length is one byte longer than the 'official' indexable
+ * length of the string. This is to permit probing the byte past the
+ * indexable area for a null byte, as is the case in slices pointing
+ * to full strings, or suffixes of them.
+ */
+ #[inline]
+ fn as_imm_buf<T>(&self, f: &fn(*u8, uint) -> T) -> T {
+ let v: &[u8] = unsafe { cast::transmute(*self) };
+ v.as_imm_buf(f)
+ }
+
+ /**
+ * Work with the byte buffer of a string as a null-terminated C string.
+ *
+ * Allows for unsafe manipulation of strings, which is useful for foreign
+ * interop. This is similar to `str::as_buf`, but guarantees null-termination.
+ * If the given slice is not already null-terminated, this function will
+ * allocate a temporary, copy the slice, null terminate it, and pass
+ * that instead.
+ *
+ * # Example
+ *
+ * ~~~ {.rust}
+ * let s = "PATH".as_c_str(|path| libc::getenv(path));
+ * ~~~
+ */
+ #[inline]
+ fn as_c_str<T>(&self, f: &fn(*libc::c_char) -> T) -> T {
+ do self.as_imm_buf |buf, len| {
+ // NB: len includes the trailing null.
+ assert!(len > 0);
+ if unsafe { *(ptr::offset(buf, len - 1)) != 0 } {
+ self.to_owned().as_c_str(|s| f(s))
+ } else {
+ f(buf as *libc::c_char)
+ }
+ }
+ }
}
#[allow(missing_doc)]
fn pop_char(&mut self) -> char;
fn shift_char(&mut self) -> char;
fn unshift_char(&mut self, ch: char);
- fn append(&self, rhs: &str) -> ~str; // FIXME #4850: this should consume self.
+ fn append(self, rhs: &str) -> ~str;
fn reserve(&mut self, n: uint);
fn reserve_at_least(&mut self, n: uint);
fn capacity(&self) -> uint;
+ fn to_bytes_with_null(self) -> ~[u8];
- fn as_bytes_with_null_consume(self) -> ~[u8];
+ /**
+ * Work with the mutable byte buffer and length of a slice.
+ *
+ * The given length is one byte longer than the 'official' indexable
+ * length of the string. This is to permit probing the byte past the
+ * indexable area for a null byte, as is the case in slices pointing
+ * to full strings, or suffixes of them.
+ *
+ * Make sure any mutations to this buffer keep this string valid UTF8.
+ */
+ fn as_mut_buf<T>(&mut self, f: &fn(*mut u8, uint) -> T) -> T;
}
impl OwnedStr for ~str {
let llen = self.len();
let rlen = rhs.len();
self.reserve(llen + rlen);
- do as_buf(*self) |lbuf, _llen| {
- do as_buf(rhs) |rbuf, _rlen| {
+ do self.as_imm_buf |lbuf, _llen| {
+ do rhs.as_imm_buf |rbuf, _rlen| {
let dst = ptr::offset(lbuf, llen);
let dst = ::cast::transmute_mut_unsafe(dst);
ptr::copy_memory(dst, rbuf, rlen);
let llen = self.len();
let rlen = rhs.len();
self.reserve_at_least(llen + rlen);
- do as_buf(*self) |lbuf, _llen| {
- do as_buf(rhs) |rbuf, _rlen| {
+ do self.as_imm_buf |lbuf, _llen| {
+ do rhs.as_imm_buf |rbuf, _rlen| {
let dst = ptr::offset(lbuf, llen);
let dst = ::cast::transmute_mut_unsafe(dst);
ptr::copy_memory(dst, rbuf, rlen);
let new_len = len + nb;
self.reserve_at_least(new_len);
let off = len;
- do as_buf(*self) |buf, _len| {
- let buf: *mut u8 = ::cast::transmute(buf);
+ do self.as_mut_buf |buf, _len| {
match nb {
1u => {
*ptr::mut_offset(buf, off) = code as u8;
*/
fn shift_char(&mut self) -> char {
let CharRange {ch, next} = self.char_range_at(0u);
- *self = unsafe { raw::slice_bytes_owned(*self, next, self.len()) };
+ *self = self.slice(next, self.len()).to_owned();
return ch;
}
/// Concatenate two strings together.
#[inline]
- fn append(&self, rhs: &str) -> ~str {
- // FIXME #4850: this should consume self, but that causes segfaults
- let mut v = self.clone();
- v.push_str_no_overallocate(rhs);
- v
+ fn append(self, rhs: &str) -> ~str {
+ let mut new_str = self;
+ new_str.push_str_no_overallocate(rhs);
+ new_str
}
/**
/// Convert to a vector of bytes. This does not allocate a new
/// string, and includes the null terminator.
#[inline]
- fn as_bytes_with_null_consume(self) -> ~[u8] {
+ fn to_bytes_with_null(self) -> ~[u8] {
unsafe { ::cast::transmute(self) }
}
+
+ #[inline]
+ fn as_mut_buf<T>(&mut self, f: &fn(*mut u8, uint) -> T) -> T {
+ let v: &mut ~[u8] = unsafe { cast::transmute(self) };
+ v.as_mut_buf(f)
+ }
}
impl Clone for ~str {
#[inline]
fn clone(&self) -> ~str {
- to_owned(*self)
+ self.to_owned()
}
}
}
#[test]
- fn test_as_bytes_with_null_consume() {
+ fn test_to_bytes_with_null() {
let s = ~"ศไทย中华Việt Nam";
let v = ~[
224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228,
184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97,
109, 0
];
- assert_eq!((~"").as_bytes_with_null_consume(), ~[0]);
- assert_eq!((~"abc").as_bytes_with_null_consume(),
+ assert_eq!((~"").to_bytes_with_null(), ~[0]);
+ assert_eq!((~"abc").to_bytes_with_null(),
~['a' as u8, 'b' as u8, 'c' as u8, 0]);
- assert_eq!(s.as_bytes_with_null_consume(), v);
+ assert_eq!(s.to_bytes_with_null(), v);
}
#[test]
}
#[test]
- fn test_as_buf() {
- let a = "Abcdefg";
- let b = as_buf(a, |buf, _l| {
- assert_eq!(unsafe { *buf }, 65u8);
- 100
- });
- assert_eq!(b, 100);
- }
+ fn test_as_imm_buf() {
+ do "".as_imm_buf |buf, len| {
+ assert_eq!(len, 1);
+ unsafe {
+ assert_eq!(*ptr::offset(buf, 0), 0);
+ }
+ }
- #[test]
- fn test_as_buf_small() {
- let a = "A";
- let b = as_buf(a, |buf, _l| {
- assert_eq!(unsafe { *buf }, 65u8);
- 100
- });
- assert_eq!(b, 100);
+ do "hello".as_imm_buf |buf, len| {
+ assert_eq!(len, 6);
+ unsafe {
+ assert_eq!(*ptr::offset(buf, 0), 'h' as u8);
+ assert_eq!(*ptr::offset(buf, 1), 'e' as u8);
+ assert_eq!(*ptr::offset(buf, 2), 'l' as u8);
+ assert_eq!(*ptr::offset(buf, 3), 'l' as u8);
+ assert_eq!(*ptr::offset(buf, 4), 'o' as u8);
+ assert_eq!(*ptr::offset(buf, 5), 0);
+ }
+ }
}
#[test]
- fn test_as_buf2() {
- unsafe {
- let s = ~"hello";
- let sb = as_buf(s, |b, _l| b);
- let s_cstr = raw::from_buf(sb);
- assert_eq!(s_cstr, s);
+ fn test_as_c_str() {
+ let a = ~"";
+ do a.as_c_str |buf| {
+ unsafe {
+ assert_eq!(*ptr::offset(buf, 0), 0);
+ }
}
- }
- #[test]
- fn test_as_buf_3() {
let a = ~"hello";
- do as_buf(a) |buf, len| {
+ do a.as_c_str |buf| {
unsafe {
- assert_eq!(a[0], 'h' as u8);
- assert_eq!(*buf, 'h' as u8);
- assert_eq!(len, 6u);
- assert_eq!(*ptr::offset(buf,4u), 'o' as u8);
- assert_eq!(*ptr::offset(buf,5u), 0u8);
+ assert_eq!(*ptr::offset(buf, 0), 'h' as libc::c_char);
+ assert_eq!(*ptr::offset(buf, 1), 'e' as libc::c_char);
+ assert_eq!(*ptr::offset(buf, 2), 'l' as libc::c_char);
+ assert_eq!(*ptr::offset(buf, 3), 'l' as libc::c_char);
+ assert_eq!(*ptr::offset(buf, 4), 'o' as libc::c_char);
+ assert_eq!(*ptr::offset(buf, 5), 0);
}
}
}
assert_eq!(5, sum_len([s.as_slice()]));
}
}
+
+#[cfg(test)]
+mod bench {
+ use extra::test::BenchHarness;
+ use str;
+
+ #[bench]
+ fn is_utf8_100_ascii(bh: &mut BenchHarness) {
+
+ let s = bytes!("Hello there, the quick brown fox jumped over the lazy dog! \
+ Lorem ipsum dolor sit amet, consectetur. ");
+
+ assert_eq!(100, s.len());
+ do bh.iter {
+ str::is_utf8(s);
+ }
+ }
+
+ #[bench]
+ fn is_utf8_100_multibyte(bh: &mut BenchHarness) {
+ let s = bytes!("𐌀𐌖𐌋𐌄𐌑𐌉ปรدولة الكويتทศไทย中华𐍅𐌿𐌻𐍆𐌹𐌻𐌰");
+ assert_eq!(100, s.len());
+ do bh.iter {
+ str::is_utf8(s);
+ }
+ }
+
+ #[bench]
+ fn map_chars_100_ascii(bh: &mut BenchHarness) {
+ let s = "HelloHelloHelloHelloHelloHelloHelloHelloHelloHello\
+ HelloHelloHelloHelloHelloHelloHelloHelloHelloHello";
+ do bh.iter {
+ s.map_chars(|c| ((c as uint) + 1) as char);
+ }
+ }
+
+ #[bench]
+ fn map_chars_100_multibytes(bh: &mut BenchHarness) {
+ let s = "𐌀𐌖𐌋𐌄𐌑𐌀𐌖𐌋𐌄𐌑𐌀𐌖𐌋𐌄𐌑𐌀𐌖𐌋𐌄𐌑𐌀𐌖𐌋𐌄𐌑\
+ 𐌀𐌖𐌋𐌄𐌑𐌀𐌖𐌋𐌄𐌑𐌀𐌖𐌋𐌄𐌑𐌀𐌖𐌋𐌄𐌑𐌀𐌖𐌋𐌄𐌑\
+ 𐌀𐌖𐌋𐌄𐌑𐌀𐌖𐌋𐌄𐌑𐌀𐌖𐌋𐌄𐌑𐌀𐌖𐌋𐌄𐌑𐌀𐌖𐌋𐌄𐌑\
+ 𐌀𐌖𐌋𐌄𐌑𐌀𐌖𐌋𐌄𐌑𐌀𐌖𐌋𐌄𐌑𐌀𐌖𐌋𐌄𐌑𐌀𐌖𐌋𐌄𐌑";
+ do bh.iter {
+ s.map_chars(|c| ((c as uint) + 1) as char);
+ }
+ }
+}
}
/// Creates a new vector with a capacity of `capacity`
+ #[inline]
pub fn with_capacity<T>(capacity: uint) -> ~[T] {
unsafe {
if contains_managed::<T>() {
* ~~~ {.rust}
* let v = &[1,2,3,4];
* for v.window_iter().advance |win| {
- * io::println(fmt!("%?", win));
+ * printfln!(win);
* }
* ~~~
*
* ~~~ {.rust}
* let v = &[1,2,3,4,5];
* for v.chunk_iter().advance |win| {
- * io::println(fmt!("%?", win));
+ * printfln!(win);
* }
* ~~~
*
unsafe fn unsafe_mut_ref(&self, index: uint) -> *mut T;
unsafe fn unsafe_set(&self, index: uint, val: T);
- fn as_mut_buf<U>(&self, f: &fn(*mut T, uint) -> U) -> U;
+ fn as_mut_buf<U>(self, f: &fn(*mut T, uint) -> U) -> U;
}
impl<'self,T> MutableVector<'self, T> for &'self mut [T] {
/// Similar to `as_imm_buf` but passing a `*mut T`
#[inline]
- fn as_mut_buf<U>(&self, f: &fn(*mut T, uint) -> U) -> U {
- unsafe {
- let v : *(*mut T,uint) = transmute(self);
- let (buf,len) = *v;
- f(buf, len / sys::nonzero_size_of::<T>())
- }
+ fn as_mut_buf<U>(self, f: &fn(*mut T, uint) -> U) -> U {
+ let (buf, len): (*mut T, uint) = unsafe { transmute(self) };
+ f(buf, len / sys::nonzero_size_of::<T>())
}
}
#[inline]
fn size_hint(&self) -> (uint, Option<uint>) {
- let diff = (self.end as uint) - (self.ptr as uint);
- let exact = diff / sys::nonzero_size_of::<$elem>();
+ let exact = self.indexable();
(exact, Some(exact))
}
}
}
}
+macro_rules! random_access_iterator {
+ (impl $name:ident -> $elem:ty) => {
+ impl<'self, T> RandomAccessIterator<$elem> for $name<'self, T> {
+ #[inline]
+ fn indexable(&self) -> uint {
+ let diff = (self.end as uint) - (self.ptr as uint);
+ diff / sys::nonzero_size_of::<T>()
+ }
+
+ fn idx(&self, index: uint) -> Option<$elem> {
+ unsafe {
+ if index < self.indexable() {
+ cast::transmute(self.ptr.offset(index))
+ } else {
+ None
+ }
+ }
+ }
+ }
+ }
+}
+
//iterator!{struct VecIterator -> *T, &'self T}
/// An iterator for iterating over a vector.
pub struct VecIterator<'self, T> {
}
iterator!{impl VecIterator -> &'self T}
double_ended_iterator!{impl VecIterator -> &'self T}
+random_access_iterator!{impl VecIterator -> &'self T}
pub type VecRevIterator<'self, T> = InvertIterator<&'self T, VecIterator<'self, T>>;
impl<'self, T> Clone for VecIterator<'self, T> {
}
iterator!{impl VecMutIterator -> &'self mut T}
double_ended_iterator!{impl VecMutIterator -> &'self mut T}
+random_access_iterator!{impl VecMutIterator -> &'self mut T}
pub type VecMutRevIterator<'self, T> = InvertIterator<&'self mut T, VecMutIterator<'self, T>>;
/// An iterator that moves out of a vector.
assert!(it.next().is_none());
}
+ #[test]
+ fn test_random_access_iterator() {
+ use iterator::*;
+ let xs = [1, 2, 5, 10, 11];
+ let mut it = xs.iter();
+
+ assert_eq!(it.indexable(), 5);
+ assert_eq!(it.idx(0).unwrap(), &1);
+ assert_eq!(it.idx(2).unwrap(), &5);
+ assert_eq!(it.idx(4).unwrap(), &11);
+ assert!(it.idx(5).is_none());
+
+ assert_eq!(it.next().unwrap(), &1);
+ assert_eq!(it.indexable(), 4);
+ assert_eq!(it.idx(0).unwrap(), &2);
+ assert_eq!(it.idx(3).unwrap(), &11);
+ assert!(it.idx(4).is_none());
+
+ assert_eq!(it.next().unwrap(), &2);
+ assert_eq!(it.indexable(), 3);
+ assert_eq!(it.idx(1).unwrap(), &10);
+ assert!(it.idx(3).is_none());
+
+ assert_eq!(it.next().unwrap(), &5);
+ assert_eq!(it.indexable(), 2);
+ assert_eq!(it.idx(1).unwrap(), &11);
+
+ assert_eq!(it.next().unwrap(), &10);
+ assert_eq!(it.indexable(), 1);
+ assert_eq!(it.idx(0).unwrap(), &11);
+ assert!(it.idx(1).is_none());
+
+ assert_eq!(it.next().unwrap(), &11);
+ assert_eq!(it.indexable(), 0);
+ assert!(it.idx(0).is_none());
+
+ assert!(it.next().is_none());
+ }
+
#[test]
fn test_iter_size_hints() {
use iterator::*;