diff --git a/src/comp/metadata/astencode.rs b/src/comp/metadata/astencode.rs index 71ddbeb749bf..c24c80cf74b2 100644 --- a/src/comp/metadata/astencode.rs +++ b/src/comp/metadata/astencode.rs @@ -31,6 +31,8 @@ import syntax::print::pprust; export encode_inlined_item; export decode_inlined_item; +export encode_inlined_method; +export decode_inlined_method; type decode_ctxt = @{ cdata: cstore::crate_metadata, @@ -49,25 +51,36 @@ iface tr { } // ______________________________________________________________________ -// Enumerating the IDs which appear in an AST +// Top-level methods. + +// The type inline_fn should be a type that can represent both methods +// and top-level items. As it happens, the type ast::method is perfect +// for this purpose, but I use this typedef just to keep clear when +// the thing may not, in fact, be an actual method in the AST but +// rather some sort of function. +enum inline_fn = @ast::method; fn encode_inlined_item(ecx: @e::encode_ctxt, ebml_w: ebml::writer, path: ast_map::path, item: @ast::item) { - #debug["> Encoding inlined item: %s::%s (%u)", - ast_map::path_to_str(path), - item.ident, - ebml_w.writer.tell()]; - let id_range = compute_id_range(item); - ebml_w.wr_tag(c::tag_ast as uint) {|| - encode_id_range(ebml_w, id_range); - encode_ast(ebml_w, item); - encode_side_tables_for_item(ecx, ebml_w, item); - } - #debug["< Encoded inlined item: %s (%u)", - ast_map::path_to_str(path), - ebml_w.writer.tell()]; + let ifn = inline_fn(alt item.node { + ast::item_fn(decl, tps, body) { + @{ident: item.ident, + attrs: item.attrs, + tps: tps, + decl: decl, + body: body, + id: item.id, + span: item.span} + } + + _ { + ecx.ccx.sess.span_bug(item.span, "Cannot inline non-function") + } + }); + + encode_inlined_fn(ecx, ebml_w, path, ifn); } fn decode_inlined_item(cdata: cstore::crate_metadata, @@ -75,23 +88,88 @@ fn decode_inlined_item(cdata: cstore::crate_metadata, maps: maps, path: ast_map::path, par_doc: ebml::doc) -> option<@ast::item> { + let oifn = decode_inlined_fn(cdata, tcx, maps, path, par_doc); + option::map(oifn) {|ifn| + let item = @{ident: ifn.ident, + attrs: ifn.attrs, + id: ifn.id, + node: ast::item_fn(ifn.decl, ifn.tps, ifn.body), + span: ifn.span}; + ast_map::map_decoded_item(tcx.items, path, item); + item + } +} + +fn encode_inlined_method(ecx: @e::encode_ctxt, + ebml_w: ebml::writer, + path: ast_map::path, + mthd: @ast::method) { + encode_inlined_fn(ecx, ebml_w, path, inline_fn(mthd)) +} + +fn decode_inlined_method(cdata: cstore::crate_metadata, + tcx: ty::ctxt, + maps: maps, + path: ast_map::path, + par_doc: ebml::doc) -> option<@ast::method> { + let oifn = decode_inlined_fn(cdata, tcx, maps, path, par_doc); + option::map(oifn) {|ifn| + ast_map::map_decoded_method(tcx.items, path, *ifn); + *ifn + } +} + +fn encode_inlined_fn(ecx: @e::encode_ctxt, + ebml_w: ebml::writer, + path: ast_map::path, + ifn: inline_fn) { + + #debug["> Encoding inlined item: %s::%s (%u)", + ast_map::path_to_str(path), + ifn.ident, + ebml_w.writer.tell()]; + + let id_range = compute_id_range(ifn); + ebml_w.wr_tag(c::tag_ast as uint) {|| + encode_id_range(ebml_w, id_range); + encode_ast(ebml_w, ifn); + encode_side_tables_for_ifn(ecx, ebml_w, ifn); + } + + #debug["< Encoded inlined fn: %s::%s (%u)", + ast_map::path_to_str(path), + ifn.ident, + ebml_w.writer.tell()]; +} + +// Decodes the inlined function and associated side tables. Does +// *not* insert the function into the ast_map, since the correct way +// to do this depends on whether this is an inlined item or method; +// therefore, you ought to be invoking decode_inlined_item() or +// decode_inlined_method() and not this helper function. +fn decode_inlined_fn(cdata: cstore::crate_metadata, + tcx: ty::ctxt, + maps: maps, + path: ast_map::path, + par_doc: ebml::doc) -> option { let dcx = @{cdata: cdata, tcx: tcx, maps: maps}; alt par_doc.opt_child(c::tag_ast) { none { none } some(ast_doc) { - #debug["> Decoding inlined item: %s", ast_map::path_to_str(path)]; + #debug["> Decoding inlined fn: %s", ast_map::path_to_str(path)]; let from_id_range = decode_id_range(ast_doc); let to_id_range = reserve_id_range(dcx.tcx.sess, from_id_range); let xcx = @{dcx: dcx, from_id_range: from_id_range, to_id_range: to_id_range}; - let raw_item = decode_ast(ast_doc); - let item = renumber_ast(xcx, raw_item); - #debug[">> Item named: %s", item.ident]; - ast_map::map_decoded_item(dcx.tcx.items, path, item); + let raw_ifn = decode_ast(ast_doc); + let ifn = renumber_ast(xcx, raw_ifn); + #debug["Fn named: %s", ifn.ident]; decode_side_tables(xcx, ast_doc); - #debug["< Decoded inlined item: %s", ast_map::path_to_str(path)]; - some(item) + #debug["< Decoded inlined fn: %s::%s", + ast_map::path_to_str(path), + ifn.ident]; + some(ifn) } } } @@ -105,7 +183,7 @@ fn empty(range: id_range) -> bool { range.min >= range.max } -fn visit_ids(item: @ast::item, vfn: fn@(ast::node_id)) { +fn visit_ids(ifn: inline_fn, vfn: fn@(ast::node_id)) { let visitor = visit::mk_simple_visitor(@{ visit_mod: fn@(_m: ast::_mod, _sp: span, id: ast::node_id) { vfn(id) @@ -214,13 +292,13 @@ fn visit_ids(item: @ast::item, vfn: fn@(ast::node_id)) { } }); - visitor.visit_item(item, (), visitor); + visit::visit_method_helper(*ifn, (), visitor); } -fn compute_id_range(item: @ast::item) -> id_range { +fn compute_id_range(ifn: inline_fn) -> id_range { let min = @mutable int::max_value; let max = @mutable int::min_value; - visit_ids(item) {|id| + visit_ids(ifn) {|id| *min = int::min(*min, id); *max = int::max(*max, id + 1); } @@ -317,25 +395,25 @@ impl deserializer_helpers for D { // We also have to adjust the spans: for now we just insert a dummy span, // but eventually we should add entries to the local codemap as required. -fn encode_ast(ebml_w: ebml::writer, item: @ast::item) { +fn encode_ast(ebml_w: ebml::writer, ifn: inline_fn) { ebml_w.wr_tag(c::tag_tree as uint) {|| - astencode_gen::serialize_syntax_ast_item(ebml_w, *item); + astencode_gen::serialize_syntax_ast_method(ebml_w, **ifn) } } -fn decode_ast(par_doc: ebml::doc) -> @ast::item { +fn decode_ast(par_doc: ebml::doc) -> inline_fn { let chi_doc = par_doc[c::tag_tree]; let d = serialization::mk_ebml_deserializer(chi_doc); - @astencode_gen::deserialize_syntax_ast_item(d) + inline_fn(@astencode_gen::deserialize_syntax_ast_method(d)) } -fn renumber_ast(xcx: extended_decode_ctxt, item: @ast::item) -> @ast::item { +fn renumber_ast(xcx: extended_decode_ctxt, ifn: inline_fn) -> inline_fn { let fld = fold::make_fold({ new_id: xcx.tr_id(_), new_span: xcx.tr_span(_) with *fold::default_ast_fold() }); - fld.fold_item(item) + inline_fn(fld.fold_method(*ifn)) } // ______________________________________________________________________ @@ -586,11 +664,11 @@ impl writer for ebml::writer { } } -fn encode_side_tables_for_item(ecx: @e::encode_ctxt, - ebml_w: ebml::writer, - item: @ast::item) { +fn encode_side_tables_for_ifn(ecx: @e::encode_ctxt, + ebml_w: ebml::writer, + ifn: inline_fn) { ebml_w.wr_tag(c::tag_table as uint) {|| - visit_ids(item, fn@(id: ast::node_id) { + visit_ids(ifn, fn@(id: ast::node_id) { // Note: this will cause a copy of ebml_w, which is bad as // it has mutable fields. But I believe it's harmless since // we generate balanced EBML. @@ -820,7 +898,21 @@ fn decode_side_tables(xcx: extended_decode_ctxt, } // ______________________________________________________________________ -// Testing +// Testing of astencode_gen + +#[cfg(test)] +fn encode_item_ast(ebml_w: ebml::writer, item: @ast::item) { + ebml_w.wr_tag(c::tag_tree as uint) {|| + astencode_gen::serialize_syntax_ast_item(ebml_w, *item); + } +} + +#[cfg(test)] +fn decode_item_ast(par_doc: ebml::doc) -> @ast::item { + let chi_doc = par_doc[c::tag_tree]; + let d = serialization::mk_ebml_deserializer(chi_doc); + @astencode_gen::deserialize_syntax_ast_item(d) +} #[cfg(test)] fn new_parse_sess() -> parser::parse_sess { @@ -864,9 +956,9 @@ fn roundtrip(in_item: @ast::item) { #debug["in_item = %s", pprust::item_to_str(in_item)]; let mbuf = io::mk_mem_buffer(); let ebml_w = ebml::mk_writer(io::mem_buffer_writer(mbuf)); - encode_ast(ebml_w, in_item); + encode_item_ast(ebml_w, in_item); let ebml_doc = ebml::new_doc(@io::mem_buffer_buf(mbuf)); - let out_item = decode_ast(ebml_doc); + let out_item = decode_item_ast(ebml_doc); #debug["out_item = %s", pprust::item_to_str(out_item)]; assert in_item == out_item; } diff --git a/src/comp/metadata/astencode_gen.rs b/src/comp/metadata/astencode_gen.rs index f95b9a2105f3..abbe7376e1bf 100644 --- a/src/comp/metadata/astencode_gen.rs +++ b/src/comp/metadata/astencode_gen.rs @@ -8748,3 +8748,12 @@ fn deserialize_syntax_ast_def_id(s: S) -> syntax::ast::def_id { deserialize_162(s) } +fn serialize_syntax_ast_method(s: S, + v: + syntax::ast::method) { + serialize_160(s, v); +} +fn deserialize_syntax_ast_method(s: S) -> + syntax::ast::method { + deserialize_160(s) +} diff --git a/src/comp/middle/ast_map.rs b/src/comp/middle/ast_map.rs index 79410158ad55..b5944402bb25 100644 --- a/src/comp/middle/ast_map.rs +++ b/src/comp/middle/ast_map.rs @@ -73,6 +73,15 @@ fn map_decoded_item(map: map, path: path, i: @item) { v.visit_item(i, cx, v); } +fn map_decoded_method(map: map, path: path, m: @method) { + // As above. + let cx = {map: map, + mutable path: path, + mutable local_id: 0u}; + let v = mk_ast_map_visitor(); + visit::visit_method_helper(m, cx, v); +} + fn map_fn(fk: visit::fn_kind, decl: fn_decl, body: blk, sp: codemap::span, id: node_id, cx: ctx, v: vt) { for a in decl.inputs { diff --git a/src/comp/syntax/visit.rs b/src/comp/syntax/visit.rs index 5cf4773101e2..55958abd7af6 100644 --- a/src/comp/syntax/visit.rs +++ b/src/comp/syntax/visit.rs @@ -130,8 +130,7 @@ fn visit_item(i: @item, e: E, v: vt) { alt ifce { some(ty) { v.visit_ty(ty, e, v); } _ {} } v.visit_ty(ty, e, v); for m in methods { - v.visit_fn(fk_method(m.ident, m.tps), m.decl, m.body, m.span, - m.id, e, v); + visit_method_helper(m, e, v) } } item_class(tps, members, _, ctor_decl, ctor_blk) { @@ -252,6 +251,15 @@ fn visit_fn_decl(fd: fn_decl, e: E, v: vt) { v.visit_ty(fd.output, e, v); } +// Note: there is no visit_method() method in the visitor, instead override +// visit_fn() and check for fk_method(). I named this visit_method_helper() +// because it is not a default impl of any method, though I doubt that really +// clarifies anything. - Niko +fn visit_method_helper(m: @method, e: E, v: vt) { + v.visit_fn(fk_method(m.ident, m.tps), m.decl, m.body, m.span, + m.id, e, v); +} + fn visit_fn(fk: fn_kind, decl: fn_decl, body: blk, _sp: span, _id: node_id, e: E, v: vt) { visit_fn_decl(decl, e, v); diff --git a/src/compiletest/runtest.rs b/src/compiletest/runtest.rs index 8bf5124d3f2f..517da771c0a6 100644 --- a/src/compiletest/runtest.rs +++ b/src/compiletest/runtest.rs @@ -289,10 +289,15 @@ fn compile_test(config: config, props: test_props, testfile: str) -> procres { vec::iter(props.aux_builds) {|rel_ab| let abs_ab = fs::connect(config.aux_base, rel_ab); - compose_and_run(config, abs_ab, - make_compile_args(_, props, ["--lib"], - make_lib_name, _), - config.compile_lib_path, option::none); + let auxres = compose_and_run(config, abs_ab, + make_compile_args(_, props, ["--lib"], + make_lib_name, _), + config.compile_lib_path, option::none); + if auxres.status != 0 { + fatal_procres( + #fmt["auxiliary build of %s failed to compile: ", abs_ab], + auxres); + } } compose_and_run(config, testfile, diff --git a/src/etc/gen-astencode b/src/etc/gen-astencode index 601c73ae0a24..2be64dab7848 100755 --- a/src/etc/gen-astencode +++ b/src/etc/gen-astencode @@ -16,7 +16,8 @@ function msg { M=src/comp/metadata GEN_TYPES="syntax::ast::item syntax::ast::def middle::typeck::method_origin \ - middle::freevars::freevar_entry syntax::ast::def_id" + middle::freevars::freevar_entry syntax::ast::def_id + syntax::ast::method" # Find serializer tool: for S in build/*/stage1/bin/serializer; do diff --git a/src/libcore/sys.rs b/src/libcore/sys.rs index 9cdbfaa61af7..7532177246cc 100644 --- a/src/libcore/sys.rs +++ b/src/libcore/sys.rs @@ -20,12 +20,15 @@ native mod rustrt { fn unsupervise(); fn shape_log_str(t: *sys::type_desc, data: T) -> str; fn rust_set_exit_status(code: ctypes::intptr_t); - fn rust_frame_address() -> ctypes::uintptr_t; } #[abi = "rust-intrinsic"] native mod rusti { fn get_type_desc() -> *type_desc; + + // Invokes __builtin_frame_address(). + // See . + fn frame_address(n: ctypes::c_uint) -> ctypes::uintptr_t; } /* @@ -78,10 +81,6 @@ fn log_str(t: T) -> str { rustrt::shape_log_str(get_type_desc::(), t) } -fn frame_address() -> uint { - rustrt::rust_frame_address() -} - #[doc( brief = "Sets the process exit code", desc = "Sets the exit code returned by the process if all supervised \ diff --git a/src/rt/intrinsics/intrinsics.cpp b/src/rt/intrinsics/intrinsics.cpp index 04fb683eb752..d36bdf876751 100644 --- a/src/rt/intrinsics/intrinsics.cpp +++ b/src/rt/intrinsics/intrinsics.cpp @@ -166,3 +166,9 @@ upcall_vec_push(rust_vec** vp, type_desc* elt_ty, void* elt) { upcall_intrinsic_vec_push(vp, elt_ty, elt); } + +extern "C" CDECL void +rust_intrinsic_frame_address(void **p, unsigned n) { + *p = __builtin_frame_address(n); +} + diff --git a/src/rt/intrinsics/intrinsics.i386.ll.in b/src/rt/intrinsics/intrinsics.i386.ll.in index d8373cc0b108..a03bed031181 100644 --- a/src/rt/intrinsics/intrinsics.i386.ll.in +++ b/src/rt/intrinsics/intrinsics.i386.ll.in @@ -1,125 +1,114 @@ ; ModuleID = 'src/rt/intrinsics/intrinsics.cpp' -; target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32-S128" +; target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128-n8:16:32" target triple = "@CFG_TARGET_TRIPLE@" -%struct.type_desc = type { %struct.type_desc**, i32, i32, void (i8*, i8*, %struct.type_desc**, i8*)*, void (i8*, i8*, %struct.type_desc**, i8*)*, void (i8*, i8*, %struct.type_desc**, i8*)*, i8*, void (i8*, i8*, %struct.type_desc**, i8*)*, void (i8*, i8*, %struct.type_desc**, i8*)*, i32, i8*, i8*, %struct.rust_shape_tables*, i32, i32, %struct.UT_hash_handle, i32, [0 x %struct.type_desc*] } -%struct.rust_shape_tables = type { i8*, i8* } +%0 = type { i32, %struct.rust_task**, i32 } +%1 = type { %"struct.hash_map::map_entry"* } +%class.array_list = type { i32, %"struct.memory_region::alloc_header"**, i32 } +%class.boxed_region = type { %class.memory_region*, %struct.rust_opaque_box* } +%class.circular_buffer = type { %class.rust_kernel*, i32, i32, i32, i32, i8* } +%class.context = type { %struct.registers_t, %class.context*, [12 x i8] } +%"class.debug::task_debug_info" = type { %"class.std::map" } +%class.hash_map = type { %"struct.hash_map::map_entry"* } +%class.indexed_list = type { i32 (...)**, %0 } +%class.lock_and_signal = type { i32 (...)**, %struct._opaque_pthread_cond_t, %struct._opaque_pthread_mutex_t, %struct._opaque_pthread_t* } +%class.memory_region = type { i32 (...)**, %class.rust_srv*, %class.memory_region*, i32, %class.array_list, i8, i8, %class.lock_and_signal } +%class.rust_crate_cache = type { %struct.type_desc*, %struct.rust_hashable_dict*, %struct.rust_task_thread*, i32 } +%class.rust_kernel = type { %class.memory_region, %class.rust_log, %class.rust_srv*, %class.lock_and_signal, i32, i32, %1, %class.lock_and_signal, i32, %class.lock_and_signal, i32, %"class.std::map", %"class.std::vector", %struct.rust_env* } +%class.rust_log = type { i32 (...)**, %class.rust_srv*, %struct.rust_task_thread*, i8 } +%class.rust_obstack = type { %struct.rust_obstack_chunk*, %struct.rust_task* } +%class.rust_port = type { i32, i32, %class.rust_kernel*, %struct.rust_task*, i32, %class.circular_buffer, %class.lock_and_signal } +%class.rust_port_selector = type { %class.rust_port**, i32, %class.lock_and_signal } +%class.rust_scheduler = type opaque +%class.rust_srv = type { i32 (...)**, %struct.rust_env*, %class.memory_region } +%class.rust_task_list = type { %class.indexed_list, %struct.rust_task_thread*, i8* } +%class.rust_thread = type { i32 (...)**, %struct._opaque_pthread_t*, i32 } +%"class.std::_Rb_tree" = type { %"struct.std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::_Rb_tree_impl" } +%"class.std::map" = type { %"class.std::_Rb_tree" } +%"class.std::vector" = type { %"struct.std::_Vector_base" } +%struct.UT_hash_bucket = type { %struct.UT_hash_handle*, i32, i32 } %struct.UT_hash_handle = type { %struct.UT_hash_table*, i8*, i8*, %struct.UT_hash_handle*, %struct.UT_hash_handle*, i8*, i32, i32 } %struct.UT_hash_table = type { %struct.UT_hash_bucket*, i32, i32, i32, %struct.UT_hash_handle*, i32, i32, i32, i32, i32 } -%struct.UT_hash_bucket = type { %struct.UT_hash_handle*, i32, i32 } -%struct.rust_vec = type { i32, i32, [0 x i8] } -%struct.rust_fn = type { i32*, %struct.rust_box* } -%struct.rust_box = type opaque -%struct.rust_task = type { i32, i32, i8, %struct.chan_handle, [12 x i8], %class.context, %struct.stk_seg*, i32, %class.rust_scheduler*, %struct.rust_task_thread*, %class.rust_crate_cache*, %class.rust_kernel*, i8*, %class.rust_task_list*, %struct.rust_cond*, i8*, %struct.rust_task*, i32, i32, i32*, %class.memory_region, %class.boxed_region, i8, i8, %class.lock_and_signal, %class.hash_map.3, %class.rust_obstack, i32, %"class.debug::task_debug_info", i32, i8, i8, %struct.stk_seg*, i32, i32, %class.rust_port_selector, [8 x i8] } +%struct.__darwin_pthread_handler_rec = type { void (i8*)*, i8*, %struct.__darwin_pthread_handler_rec* } +%struct._opaque_pthread_attr_t = type { i32, [36 x i8] } +%struct._opaque_pthread_cond_t = type { i32, [24 x i8] } +%struct._opaque_pthread_mutex_t = type { i32, [40 x i8] } +%struct._opaque_pthread_t = type { i32, %struct.__darwin_pthread_handler_rec*, [596 x i8] } %struct.chan_handle = type { i32, i32 } -%class.context = type { %struct.registers_t, %class.context*, [12 x i8] } -%struct.registers_t = type { i32, i32, i32, i32, i32, i32, i32, i32, i16, i16, i16, i16, i16, i16, i32, i32, [12 x i8] } -%struct.stk_seg = type { %struct.stk_seg*, %struct.stk_seg*, i32, i32, i32, i32, [0 x i8] } -%class.rust_scheduler = type opaque -%struct.rust_task_thread = type { %class.rust_thread, i32, %class.rust_log, i32, %class.rust_srv*, i8*, %class.rust_task_list, %class.rust_task_list, %class.rust_task_list, %class.rust_task_list, %class.rust_crate_cache, %struct.randctx, %class.rust_kernel*, %class.rust_scheduler*, i32, i32, %class.lock_and_signal, i32, %union.pthread_attr_t, %struct.rust_env*, [8 x i8], %class.context, i8, %struct.stk_seg*, %struct.stk_seg*, [4 x i8] } -%class.rust_thread = type { i32 (...)**, i32, i32 } -%class.rust_log = type { i32 (...)**, %class.rust_srv*, %struct.rust_task_thread*, i8 } -%class.rust_srv = type { i32 (...)**, %struct.rust_env*, %class.memory_region } -%struct.rust_env = type { i32, i32, i32, i8*, i8, i8, i8* } -%class.memory_region = type { i32 (...)**, %class.rust_srv*, %class.memory_region*, i32, %class.array_list, i8, i8, %class.lock_and_signal } -%class.array_list = type { i32, %"struct.memory_region::alloc_header"**, i32 } +%"struct.hash_map::map_entry" = type opaque +%"struct.hash_map::map_entry" = type opaque %"struct.memory_region::alloc_header" = type { i8 } -%class.lock_and_signal = type { i32 (...)**, %union.pthread_cond_t, %union.pthread_mutex_t, i32 } -%union.pthread_cond_t = type { %struct.anon, [4 x i8] } -%struct.anon = type { i32, i32, i64, i64, i64, i8*, i32, i32 } -%union.pthread_mutex_t = type { %"struct.::__pthread_mutex_s" } -%"struct.::__pthread_mutex_s" = type { i32, i32, i32, i32, i32, %union.anon } -%union.anon = type { i32 } -%class.rust_task_list = type { %class.indexed_list, %struct.rust_task_thread*, i8* } -%class.indexed_list = type { i32 (...)**, %class.array_list.1 } -%class.array_list.1 = type { i32, %struct.rust_task**, i32 } -%class.rust_crate_cache = type { %struct.type_desc*, %struct.rust_hashable_dict*, %struct.rust_task_thread*, i32 } -%struct.rust_hashable_dict = type { %struct.UT_hash_handle, [0 x i8*] } %struct.randctx = type { i32, [256 x i32], [256 x i32], i32, i32, i32 } -%class.rust_kernel = type { %class.memory_region, %class.rust_log, %class.rust_srv*, %class.lock_and_signal, i32, i32, %class.hash_map, %class.lock_and_signal, i32, %class.lock_and_signal, i32, i32, %"class.std::map", %struct.rust_env* } -%class.hash_map = type { %"struct.hash_map::map_entry"* } -%"struct.hash_map::map_entry" = type opaque -%"class.std::map" = type { %"class.std::_Rb_tree" } -%"class.std::_Rb_tree" = type { %"struct.std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::_Rb_tree_impl" } -%"struct.std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::_Rb_tree_impl" = type { %"struct.std::less", %"struct.std::_Rb_tree_node_base", i32 } -%"struct.std::less" = type { i8 } -%"struct.std::_Rb_tree_node_base" = type { i32, %"struct.std::_Rb_tree_node_base"*, %"struct.std::_Rb_tree_node_base"*, %"struct.std::_Rb_tree_node_base"* } -%union.pthread_attr_t = type { i32, [32 x i8] } -%struct.rust_cond = type { i8 } -%class.boxed_region = type { %class.memory_region*, %struct.rust_opaque_box* } -%struct.rust_opaque_box = type { i32, %struct.type_desc*, %struct.rust_opaque_box*, %struct.rust_opaque_box* } -%class.hash_map.3 = type { %"struct.hash_map::map_entry"* } -%"struct.hash_map::map_entry" = type opaque -%class.rust_obstack = type { %struct.rust_obstack_chunk*, %struct.rust_task* } +%struct.registers_t = type { i32, i32, i32, i32, i32, i32, i32, i32, i16, i16, i16, i16, i16, i16, i32, i32, [12 x i8] } +%struct.rust_box = type opaque +%struct.rust_env = type { i32, i32, i32, i8*, i8, i8, i8* } +%struct.rust_fn = type { i32*, %struct.rust_box* } +%struct.rust_hashable_dict = type { %struct.UT_hash_handle, [0 x i8*] } %struct.rust_obstack_chunk = type { %struct.rust_obstack_chunk*, i32, i32, i32, [0 x i8] } -%"class.debug::task_debug_info" = type { %"class.std::map.4" } -%"class.std::map.4" = type { %"class.std::_Rb_tree.5" } -%"class.std::_Rb_tree.5" = type { %"struct.std::_Rb_tree >, std::_Select1st > >, std::less, std::allocator > > >::_Rb_tree_impl" } -%"struct.std::_Rb_tree >, std::_Select1st > >, std::less, std::allocator > > >::_Rb_tree_impl" = type { %"struct.std::less.9", %"struct.std::_Rb_tree_node_base", i32 } -%"struct.std::less.9" = type { i8 } -%class.rust_port_selector = type { %class.rust_port**, i32, %class.lock_and_signal } -%class.rust_port = type { i32, i32, %class.rust_kernel*, %struct.rust_task*, i32, %class.circular_buffer, %class.lock_and_signal } -%class.circular_buffer = type { %class.rust_kernel*, i32, i32, i32, i32, i8* } +%struct.rust_opaque_box = type { i32, %struct.type_desc*, %struct.rust_opaque_box*, %struct.rust_opaque_box* } +%struct.rust_shape_tables = type { i8*, i8* } +%struct.rust_task = type { i32, i32, i8, %struct.chan_handle, [12 x i8], %class.context, %struct.stk_seg*, i32, %class.rust_scheduler*, %struct.rust_task_thread*, %class.rust_crate_cache*, %class.rust_kernel*, i8*, %class.rust_task_list*, %"struct.memory_region::alloc_header"*, i8*, %struct.rust_task*, i32, i32, i32*, %class.memory_region, %class.boxed_region, i8, i8, %class.lock_and_signal, %class.hash_map, %class.rust_obstack, i32, %"class.debug::task_debug_info", i32, i8, i8, %struct.stk_seg*, i32, i32, %class.rust_port_selector, [8 x i8] } +%struct.rust_task_thread = type { %class.rust_thread, i32, %class.rust_log, i32, %class.rust_srv*, i8*, %class.rust_task_list, %class.rust_task_list, %class.rust_task_list, %class.rust_task_list, %class.rust_crate_cache, %struct.randctx, %class.rust_kernel*, %class.rust_scheduler*, i32, i32, %class.lock_and_signal, i32, %struct._opaque_pthread_attr_t, %struct.rust_env*, [4 x i8], %class.context, i8, %struct.stk_seg*, %struct.stk_seg*, [4 x i8] } +%struct.rust_vec = type { i32, i32, [0 x i8] } +%"struct.std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::_Rb_tree_impl" = type { %"struct.memory_region::alloc_header", %"struct.std::_Rb_tree_node_base", i32 } +%"struct.std::_Rb_tree_node_base" = type { i32, %"struct.std::_Rb_tree_node_base"*, %"struct.std::_Rb_tree_node_base"*, %"struct.std::_Rb_tree_node_base"* } +%"struct.std::_Vector_base" = type { %"struct.std::_Vector_base >::_Vector_impl" } +%"struct.std::_Vector_base >::_Vector_impl" = type { i32*, i32*, i32* } +%struct.stk_seg = type { %struct.stk_seg*, %struct.stk_seg*, i32, i32, i32, i32, [0 x i8] } +%struct.type_desc = type { %struct.type_desc**, i32, i32, void (i8*, i8*, %struct.type_desc**, i8*)*, void (i8*, i8*, %struct.type_desc**, i8*)*, void (i8*, i8*, %struct.type_desc**, i8*)*, i8*, void (i8*, i8*, %struct.type_desc**, i8*)*, void (i8*, i8*, %struct.type_desc**, i8*)*, i32, i8*, i8*, %struct.rust_shape_tables*, i32, i32, %struct.UT_hash_handle, i32, [0 x %struct.type_desc*] } define void @rust_intrinsic_vec_len(i32* nocapture %retptr, i8* nocapture %env, %struct.type_desc* nocapture %ty, %struct.rust_vec** nocapture %vp) nounwind { -entry: - %0 = load %struct.rust_vec** %vp, align 4, !tbaa !0 - %fill = getelementptr inbounds %struct.rust_vec* %0, i32 0, i32 0 - %1 = load i32* %fill, align 4, !tbaa !3 - %size = getelementptr inbounds %struct.type_desc* %ty, i32 0, i32 1 - %2 = load i32* %size, align 4, !tbaa !3 - %div = udiv i32 %1, %2 - store i32 %div, i32* %retptr, align 4, !tbaa !3 + %1 = load %struct.rust_vec** %vp, align 4 + %2 = getelementptr inbounds %struct.rust_vec* %1, i32 0, i32 0 + %3 = load i32* %2, align 4 + %4 = getelementptr inbounds %struct.type_desc* %ty, i32 0, i32 1 + %5 = load i32* %4, align 4 + %6 = udiv i32 %3, %5 + store i32 %6, i32* %retptr, align 4 ret void } define void @rust_intrinsic_ptr_offset(i8** nocapture %retptr, i8* nocapture %env, %struct.type_desc* nocapture %ty, i8* %ptr, i32 %count) nounwind { -entry: - %size = getelementptr inbounds %struct.type_desc* %ty, i32 0, i32 1 - %0 = load i32* %size, align 4, !tbaa !3 - %mul = mul i32 %0, %count - %arrayidx = getelementptr inbounds i8* %ptr, i32 %mul - store i8* %arrayidx, i8** %retptr, align 4, !tbaa !0 + %1 = getelementptr inbounds %struct.type_desc* %ty, i32 0, i32 1 + %2 = load i32* %1, align 4 + %3 = mul i32 %2, %count + %4 = getelementptr inbounds i8* %ptr, i32 %3 + store i8* %4, i8** %retptr, align 4 ret void } define void @rust_intrinsic_cast(i8* nocapture %retptr, i8* nocapture %env, %struct.type_desc* nocapture %t1, %struct.type_desc* nocapture %t2, i8* nocapture %src) nounwind { -entry: - %size = getelementptr inbounds %struct.type_desc* %t1, i32 0, i32 1 - %0 = load i32* %size, align 4, !tbaa !3 - tail call void @llvm.memmove.p0i8.p0i8.i32(i8* %retptr, i8* %src, i32 %0, i32 1, i1 false) + %1 = getelementptr inbounds %struct.type_desc* %t1, i32 0, i32 1 + %2 = load i32* %1, align 4 + tail call void @llvm.memmove.p0i8.p0i8.i32(i8* %retptr, i8* %src, i32 %2, i32 1, i1 false) ret void } declare void @llvm.memmove.p0i8.p0i8.i32(i8* nocapture, i8* nocapture, i32, i32, i1) nounwind define void @rust_intrinsic_addr_of(i8** nocapture %retptr, i8* nocapture %env, %struct.type_desc* nocapture %ty, i8* %valptr) nounwind { -entry: - store i8* %valptr, i8** %retptr, align 4, !tbaa !0 + store i8* %valptr, i8** %retptr, align 4 ret void } define void @rust_intrinsic_call_with_retptr(i8** %retptr, i8* nocapture %env, %struct.type_desc* nocapture %ty, %struct.rust_fn* nocapture %recvfn) { -entry: - %fn1 = getelementptr inbounds %struct.rust_fn* %recvfn, i32 0, i32 0 - %0 = load i32** %fn1, align 4, !tbaa !0 - %1 = bitcast i32* %0 to void (i8**, i8*, i8**)* - %env2 = getelementptr inbounds %struct.rust_fn* %recvfn, i32 0, i32 1 - %2 = load %struct.rust_box** %env2, align 4, !tbaa !0 - %3 = bitcast %struct.rust_box* %2 to i8* - tail call void %1(i8** null, i8* %3, i8** %retptr) + %1 = getelementptr inbounds %struct.rust_fn* %recvfn, i32 0, i32 0 + %2 = load i32** %1, align 4 + %3 = bitcast i32* %2 to void (i8**, i8*, i8**)* + %4 = getelementptr inbounds %struct.rust_fn* %recvfn, i32 0, i32 1 + %5 = load %struct.rust_box** %4, align 4 + %6 = bitcast %struct.rust_box* %5 to i8* + tail call void %3(i8** null, i8* %6, i8** %retptr) ret void } define void @rust_intrinsic_get_type_desc(i8** nocapture %retptr, i8* nocapture %env, %struct.type_desc* %ty) nounwind { -entry: %ty.c = bitcast %struct.type_desc* %ty to i8* - store i8* %ty.c, i8** %retptr, align 4, !tbaa !0 + store i8* %ty.c, i8** %retptr, align 4 ret void } define void @rust_intrinsic_task_yield(i8** nocapture %retptr, i8* nocapture %env, %struct.rust_task* %task, i8* %killed) { -entry: tail call void @rust_task_yield(%struct.rust_task* %task, i8* %killed) ret void } @@ -127,114 +116,121 @@ entry: declare void @rust_task_yield(%struct.rust_task*, i8*) define void @rust_intrinsic_memmove(i8* nocapture %retptr, i8* nocapture %env, %struct.type_desc* nocapture %ty, i8* nocapture %dst, i8* nocapture %src, i32 %count) nounwind { -entry: - %size = getelementptr inbounds %struct.type_desc* %ty, i32 0, i32 1 - %0 = load i32* %size, align 4, !tbaa !3 - %mul = mul i32 %0, %count - tail call void @llvm.memmove.p0i8.p0i8.i32(i8* %dst, i8* %src, i32 %mul, i32 1, i1 false) + %1 = getelementptr inbounds %struct.type_desc* %ty, i32 0, i32 1 + %2 = load i32* %1, align 4 + %3 = mul i32 %2, %count + tail call void @llvm.memmove.p0i8.p0i8.i32(i8* %dst, i8* %src, i32 %3, i32 1, i1 false) ret void } define void @rust_intrinsic_memcpy(i8* nocapture %retptr, i8* nocapture %env, %struct.type_desc* nocapture %ty, i8* nocapture %dst, i8* nocapture %src, i32 %count) nounwind { -entry: - %size = getelementptr inbounds %struct.type_desc* %ty, i32 0, i32 1 - %0 = load i32* %size, align 4, !tbaa !3 - %mul = mul i32 %0, %count - tail call void @llvm.memcpy.p0i8.p0i8.i32(i8* %dst, i8* %src, i32 %mul, i32 1, i1 false) + %1 = getelementptr inbounds %struct.type_desc* %ty, i32 0, i32 1 + %2 = load i32* %1, align 4 + %3 = mul i32 %2, %count + tail call void @llvm.memcpy.p0i8.p0i8.i32(i8* %dst, i8* %src, i32 %3, i32 1, i1 false) ret void } declare void @llvm.memcpy.p0i8.p0i8.i32(i8* nocapture, i8* nocapture, i32, i32, i1) nounwind define void @rust_intrinsic_leak(i8* nocapture %retptr, i8* nocapture %env, %struct.type_desc* nocapture %ty, i8* nocapture %thing) nounwind readnone { -entry: ret void } define void @upcall_intrinsic_vec_push(%struct.rust_vec** nocapture %vp, %struct.type_desc* nocapture %elt_ty, i8* nocapture %elt) { -entry: - %0 = load %struct.rust_vec** %vp, align 4, !tbaa !0 - %fill = getelementptr inbounds %struct.rust_vec* %0, i32 0, i32 0 - %1 = load i32* %fill, align 4, !tbaa !3 - %size = getelementptr inbounds %struct.type_desc* %elt_ty, i32 0, i32 1 - %2 = load i32* %size, align 4, !tbaa !3 - %add = add i32 %2, %1 - %alloc.i = getelementptr inbounds %struct.rust_vec* %0, i32 0, i32 1 - %3 = load i32* %alloc.i, align 4, !tbaa !3 - %cmp.i = icmp ult i32 %3, %add - br i1 %cmp.i, label %if.then.i, label %_Z16reserve_vec_fastPP8rust_vecj.exit +;