diff --git a/src/libcore/rt.rs b/src/libcore/rt.rs index 5ad2da4824130..ebe8746cfcad8 100644 --- a/src/libcore/rt.rs +++ b/src/libcore/rt.rs @@ -38,15 +38,14 @@ extern mod rustrt { fn rust_upcall_free(ptr: *c_char); } -// FIXME (#2861): This needs both the attribute, and the name prefixed with -// 'rt_', otherwise the compiler won't find it. To fix this, see -// gather_rust_rtcalls. #[rt(fail_)] +#[lang="fail_"] pub fn rt_fail_(expr: *c_char, file: *c_char, line: size_t) -> ! { sys::begin_unwind_(expr, file, line); } #[rt(fail_bounds_check)] +#[lang="fail_bounds_check"] pub fn rt_fail_bounds_check(file: *c_char, line: size_t, index: size_t, len: size_t) { let msg = fmt!("index out of bounds: the len is %d but the index is %d", @@ -57,6 +56,7 @@ pub fn rt_fail_bounds_check(file: *c_char, line: size_t, } #[rt(exchange_malloc)] +#[lang="exchange_malloc"] pub fn rt_exchange_malloc(td: *c_char, size: uintptr_t) -> *c_char { return rustrt::rust_upcall_exchange_malloc(td, size); } @@ -65,11 +65,13 @@ pub fn rt_exchange_malloc(td: *c_char, size: uintptr_t) -> *c_char { // inside a landing pad may corrupt the state of the exception handler. If a // problem occurs, call exit instead. #[rt(exchange_free)] +#[lang="exchange_free"] pub fn rt_exchange_free(ptr: *c_char) { rustrt::rust_upcall_exchange_free(ptr); } #[rt(malloc)] +#[lang="malloc"] pub fn rt_malloc(td: *c_char, size: uintptr_t) -> *c_char { return rustrt::rust_upcall_malloc(td, size); } @@ -78,6 +80,7 @@ pub fn rt_malloc(td: *c_char, size: uintptr_t) -> *c_char { // inside a landing pad may corrupt the state of the exception handler. If a // problem occurs, call exit instead. #[rt(free)] +#[lang="free"] pub fn rt_free(ptr: *c_char) { rustrt::rust_upcall_free(ptr); } diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index def3f0fb98272..ec01b79c37e6f 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -34,43 +34,49 @@ use std::map::HashMap; use str_eq = str::eq; pub enum LangItem { - ConstTraitLangItem, // 0 - CopyTraitLangItem, // 1 - OwnedTraitLangItem, // 2 - DurableTraitLangItem, // 3 - - DropTraitLangItem, // 4 - - AddTraitLangItem, // 5 - SubTraitLangItem, // 6 - MulTraitLangItem, // 7 - DivTraitLangItem, // 8 - ModuloTraitLangItem, // 9 - NegTraitLangItem, // 10 - BitXorTraitLangItem, // 11 - BitAndTraitLangItem, // 12 - BitOrTraitLangItem, // 13 - ShlTraitLangItem, // 14 - ShrTraitLangItem, // 15 - IndexTraitLangItem, // 16 - - EqTraitLangItem, // 17 - OrdTraitLangItem, // 18 - - StrEqFnLangItem, // 19 - UniqStrEqFnLangItem, // 20 - AnnihilateFnLangItem, // 21 - LogTypeFnLangItem, // 22 + ConstTraitLangItem, // 0 + CopyTraitLangItem, // 1 + OwnedTraitLangItem, // 2 + DurableTraitLangItem, // 3 + + DropTraitLangItem, // 4 + + AddTraitLangItem, // 5 + SubTraitLangItem, // 6 + MulTraitLangItem, // 7 + DivTraitLangItem, // 8 + ModuloTraitLangItem, // 9 + NegTraitLangItem, // 10 + BitXorTraitLangItem, // 11 + BitAndTraitLangItem, // 12 + BitOrTraitLangItem, // 13 + ShlTraitLangItem, // 14 + ShrTraitLangItem, // 15 + IndexTraitLangItem, // 16 + + EqTraitLangItem, // 17 + OrdTraitLangItem, // 18 + + StrEqFnLangItem, // 19 + UniqStrEqFnLangItem, // 20 + AnnihilateFnLangItem, // 21 + LogTypeFnLangItem, // 22 + FailFnLangItem, // 23 + FailBoundsCheckFnLangItem, // 24 + ExchangeMallocFnLangItem, // 25 + ExchangeFreeFnLangItem, // 26 + MallocFnLangItem, // 27 + FreeFnLangItem, // 28 } struct LanguageItems { - items: [ Option * 23 ] + items: [ Option * 29 ] } impl LanguageItems { static pub fn new() -> LanguageItems { LanguageItems { - items: [ None, ..23 ] + items: [ None, ..29 ] } } @@ -110,6 +116,12 @@ impl LanguageItems { 20 => "uniq_str_eq", 21 => "annihilate", 22 => "log_type", + 23 => "fail_", + 24 => "fail_bounds_check", + 25 => "exchange_malloc", + 26 => "exchange_free", + 27 => "malloc", + 28 => "free", _ => "???" } @@ -190,6 +202,24 @@ impl LanguageItems { pub fn log_type_fn(&const self) -> def_id { self.items[LogTypeFnLangItem as uint].get() } + pub fn fail_fn(&const self) -> def_id { + self.items[FailFnLangItem as uint].get() + } + pub fn fail_bounds_check_fn(&const self) -> def_id { + self.items[FailBoundsCheckFnLangItem as uint].get() + } + pub fn exchange_malloc_fn(&const self) -> def_id { + self.items[ExchangeMallocFnLangItem as uint].get() + } + pub fn exchange_free_fn(&const self) -> def_id { + self.items[ExchangeFreeFnLangItem as uint].get() + } + pub fn malloc_fn(&const self) -> def_id { + self.items[MallocFnLangItem as uint].get() + } + pub fn free_fn(&const self) -> def_id { + self.items[FreeFnLangItem as uint].get() + } } fn LanguageItemCollector(crate: @crate, @@ -225,6 +255,12 @@ fn LanguageItemCollector(crate: @crate, item_refs.insert(~"uniq_str_eq", UniqStrEqFnLangItem as uint); item_refs.insert(~"annihilate", AnnihilateFnLangItem as uint); item_refs.insert(~"log_type", LogTypeFnLangItem as uint); + item_refs.insert(~"fail_", FailFnLangItem as uint); + item_refs.insert(~"fail_bounds_check", FailBoundsCheckFnLangItem as uint); + item_refs.insert(~"exchange_malloc", ExchangeMallocFnLangItem as uint); + item_refs.insert(~"exchange_free", ExchangeFreeFnLangItem as uint); + item_refs.insert(~"malloc", MallocFnLangItem as uint); + item_refs.insert(~"free", FreeFnLangItem as uint); LanguageItemCollector { crate: crate, diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index ad4774702289e..d87b383247b3f 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -262,14 +262,20 @@ fn opaque_box_body(bcx: block, // malloc_raw_dyn: allocates a box to contain a given type, but with a // potentially dynamic size. -fn malloc_raw_dyn(bcx: block, t: ty::t, heap: heap, +fn malloc_raw_dyn(bcx: block, + t: ty::t, + heap: heap, size: ValueRef) -> Result { let _icx = bcx.insn_ctxt("malloc_raw"); let ccx = bcx.ccx(); - let (mk_fn, rtcall) = match heap { - heap_shared => (ty::mk_imm_box, ~"malloc"), - heap_exchange => (ty::mk_imm_uniq, ~"exchange_malloc") + let (mk_fn, langcall) = match heap { + heap_shared => { + (ty::mk_imm_box, bcx.tcx().lang_items.malloc_fn()) + } + heap_exchange => { + (ty::mk_imm_uniq, bcx.tcx().lang_items.exchange_malloc_fn()) + } }; // Grab the TypeRef type of box_ptr_ty. @@ -283,8 +289,11 @@ fn malloc_raw_dyn(bcx: block, t: ty::t, heap: heap, // Allocate space: let tydesc = PointerCast(bcx, static_ti.tydesc, T_ptr(T_i8())); let rval = alloca_zeroed(bcx, T_ptr(T_i8())); - let bcx = callee::trans_rtcall(bcx, rtcall, ~[tydesc, size], - expr::SaveIn(rval)); + let bcx = callee::trans_rtcall_or_lang_call( + bcx, + langcall, + ~[tydesc, size], + expr::SaveIn(rval)); return rslt(bcx, PointerCast(bcx, Load(bcx, rval), llty)); } @@ -2539,92 +2548,6 @@ fn trap(bcx: block) { } } -fn push_rtcall(ccx: @crate_ctxt, name: ~str, did: ast::def_id) { - match ccx.rtcalls.find(name) { - Some(existing_did) if did != existing_did => { - ccx.sess.fatal(fmt!("multiple definitions for runtime call %s", - name)); - } - Some(_) | None => { - ccx.rtcalls.insert(name, did); - } - } -} - -fn gather_local_rtcalls(ccx: @crate_ctxt, crate: @ast::crate) { - visit::visit_crate(*crate, (), visit::mk_simple_visitor(@{ - visit_item: |item| match item.node { - ast::item_fn(*) => { - let attr_metas = attr::attr_metas( - attr::find_attrs_by_name(item.attrs, ~"rt")); - for vec::each(attr_metas) |attr_meta| { - match attr::get_meta_item_list(*attr_meta) { - Some(list) => { - let head = vec::head(list); - let name = attr::get_meta_item_name(head); - push_rtcall(ccx, name, {crate: ast::local_crate, - node: item.id}); - } - None => () - } - } - } - _ => () - }, - ..*visit::default_simple_visitor() - })); -} - -fn gather_external_rtcalls(ccx: @crate_ctxt) { - do cstore::iter_crate_data(ccx.sess.cstore) |_cnum, cmeta| { - let get_crate_data: decoder::GetCrateDataCb = |cnum| { - cstore::get_crate_data(ccx.sess.cstore, cnum) - }; - do decoder::each_path(ccx.sess.intr(), cmeta, get_crate_data) |path| { - let pathname = path.path_string; - match path.def_like { - decoder::dl_def(d) => { - match d { - ast::def_fn(did, _) => { - // FIXME (#2861): This should really iterate attributes - // like gather_local_rtcalls, but we'll need to - // export attributes in metadata/encoder before we can do - // that. - let sentinel = ~"rt::rt_"; - let slen = str::len(sentinel); - if str::starts_with(pathname, sentinel) { - let name = str::substr(pathname, - slen, str::len(pathname)-slen); - push_rtcall(ccx, name, did); - } - } - _ => () - } - } - _ => () - } - true - } - } -} - -fn gather_rtcalls(ccx: @crate_ctxt, crate: @ast::crate) { - gather_local_rtcalls(ccx, crate); - gather_external_rtcalls(ccx); - - // FIXME (#2861): Check for other rtcalls too, once they are - // supported. Also probably want to check type signature so we don't crash - // in some obscure place in LLVM if the user provides the wrong signature - // for an rtcall. - let expected_rtcalls = - ~[~"exchange_free", ~"exchange_malloc", ~"fail_", ~"free", ~"malloc"]; - for vec::each(expected_rtcalls) |name| { - if !ccx.rtcalls.contains_key(*name) { - fail fmt!("no definition for runtime call %s", *name); - } - } -} - fn decl_gc_metadata(ccx: @crate_ctxt, llmod_id: ~str) { if !ccx.sess.opts.gc || !ccx.uses_gc { return; @@ -2869,9 +2792,7 @@ fn trans_crate(sess: session::Session, llvm_insn_ctxt: @mut ~[], llvm_insns: HashMap(), fn_times: @mut ~[]}, - upcalls: - upcall::declare_upcalls(targ_cfg, llmod), - rtcalls: HashMap(), + upcalls: upcall::declare_upcalls(targ_cfg, llmod), tydesc_type: tydesc_type, int_type: int_type, float_type: float_type, @@ -2885,8 +2806,6 @@ fn trans_crate(sess: session::Session, mut do_not_commit_warning_issued: false }; - gather_rtcalls(ccx, crate); - { let _icx = ccx.insn_ctxt("data"); trans_constants(ccx, crate); diff --git a/src/librustc/middle/trans/callee.rs b/src/librustc/middle/trans/callee.rs index 4c78c60f5b6f0..de02039539678 100644 --- a/src/librustc/middle/trans/callee.rs +++ b/src/librustc/middle/trans/callee.rs @@ -333,13 +333,6 @@ fn trans_method_call(in_cx: block, DontAutorefArg) } -fn trans_rtcall(bcx: block, name: ~str, args: ~[ValueRef], dest: expr::Dest) - -> block -{ - let did = bcx.ccx().rtcalls[name]; - return trans_rtcall_or_lang_call(bcx, did, args, dest); -} - fn trans_rtcall_or_lang_call(bcx: block, did: ast::def_id, args: ~[ValueRef], dest: expr::Dest) -> block { let fty = if did.crate == ast::local_crate { diff --git a/src/librustc/middle/trans/closure.rs b/src/librustc/middle/trans/closure.rs index 26ba1869c27e8..353f1100cc93f 100644 --- a/src/librustc/middle/trans/closure.rs +++ b/src/librustc/middle/trans/closure.rs @@ -492,11 +492,13 @@ fn make_opaque_cbox_take_glue( let sz = Add(bcx, sz, shape::llsize_of(ccx, T_box_header(ccx))); // Allocate memory, update original ptr, and copy existing data - let malloc = ~"exchange_malloc"; let opaque_tydesc = PointerCast(bcx, tydesc, T_ptr(T_i8())); let rval = alloca_zeroed(bcx, T_ptr(T_i8())); - let bcx = callee::trans_rtcall(bcx, malloc, ~[opaque_tydesc, sz], - expr::SaveIn(rval)); + let bcx = callee::trans_rtcall_or_lang_call( + bcx, + bcx.tcx().lang_items.exchange_malloc_fn(), + ~[opaque_tydesc, sz], + expr::SaveIn(rval)); let cbox_out = PointerCast(bcx, Load(bcx, rval), llopaquecboxty); call_memcpy(bcx, cbox_out, cbox_in, sz); Store(bcx, cbox_out, cboxptr); diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs index b5c5507a22e9c..50810129569bf 100644 --- a/src/librustc/middle/trans/common.rs +++ b/src/librustc/middle/trans/common.rs @@ -197,7 +197,6 @@ struct crate_ctxt { maps: astencode::maps, stats: stats, upcalls: @upcall::upcalls, - rtcalls: HashMap<~str, ast::def_id>, tydesc_type: TypeRef, int_type: TypeRef, float_type: TypeRef, diff --git a/src/librustc/middle/trans/controlflow.rs b/src/librustc/middle/trans/controlflow.rs index 67bdfb74efc15..11cd0925d1a60 100644 --- a/src/librustc/middle/trans/controlflow.rs +++ b/src/librustc/middle/trans/controlflow.rs @@ -368,7 +368,8 @@ fn trans_fail_value(bcx: block, sp_opt: Option, V_fail_str: ValueRef) let V_str = PointerCast(bcx, V_fail_str, T_ptr(T_i8())); let V_filename = PointerCast(bcx, V_filename, T_ptr(T_i8())); let args = ~[V_str, V_filename, C_int(ccx, V_line)]; - let bcx = callee::trans_rtcall(bcx, ~"fail_", args, expr::Ignore); + let bcx = callee::trans_rtcall_or_lang_call( + bcx, bcx.tcx().lang_items.fail_fn(), args, expr::Ignore); Unreachable(bcx); return bcx; } @@ -384,8 +385,8 @@ fn trans_fail_bounds_check(bcx: block, sp: span, let filename = PointerCast(bcx, filename_cstr, T_ptr(T_i8())); let args = ~[filename, line, index, len]; - let bcx = callee::trans_rtcall(bcx, ~"fail_bounds_check", args, - expr::Ignore); + let bcx = callee::trans_rtcall_or_lang_call( + bcx, bcx.tcx().lang_items.fail_bounds_check_fn(), args, expr::Ignore); Unreachable(bcx); return bcx; } diff --git a/src/librustc/middle/trans/glue.rs b/src/librustc/middle/trans/glue.rs index 9396f64fdbe1e..d095048109773 100644 --- a/src/librustc/middle/trans/glue.rs +++ b/src/librustc/middle/trans/glue.rs @@ -28,14 +28,19 @@ use core::str; fn trans_free(cx: block, v: ValueRef) -> block { let _icx = cx.insn_ctxt("trans_free"); - callee::trans_rtcall(cx, ~"free", ~[PointerCast(cx, v, T_ptr(T_i8()))], - expr::Ignore) + callee::trans_rtcall_or_lang_call( + cx, + cx.tcx().lang_items.free_fn(), + ~[PointerCast(cx, v, T_ptr(T_i8()))], + expr::Ignore) } fn trans_unique_free(cx: block, v: ValueRef) -> block { let _icx = cx.insn_ctxt("trans_unique_free"); - callee::trans_rtcall( - cx, ~"exchange_free", ~[PointerCast(cx, v, T_ptr(T_i8()))], + callee::trans_rtcall_or_lang_call( + cx, + cx.tcx().lang_items.exchange_free_fn(), + ~[PointerCast(cx, v, T_ptr(T_i8()))], expr::Ignore) }