diff --git a/src/librustc/middle/kind.rs b/src/librustc/middle/kind.rs index ae2a27ed6ed..cce5a9d85f5 100644 --- a/src/librustc/middle/kind.rs +++ b/src/librustc/middle/kind.rs @@ -122,7 +122,7 @@ fn check_item(item: @item, (cx, visitor): (Context, visit::vt)) { None => cx.tcx.sess.bug("trait ref not in def map!"), Some(&trait_def) => { let trait_def_id = ast_util::def_id_of_def(trait_def); - if cx.tcx.lang_items.drop_trait() == trait_def_id { + if cx.tcx.lang_items.drop_trait() == Some(trait_def_id) { // Yes, it's a destructor. match self_type.node { ty_path(_, ref bounds, path_node_id) => { diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index 0e9361193b0..912096e8098 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -153,135 +153,143 @@ impl LanguageItems { // FIXME #4621: Method macros sure would be nice here. - pub fn freeze_trait(&self) -> def_id { - self.items[FreezeTraitLangItem as uint].get() - } - pub fn copy_trait(&self) -> def_id { - self.items[CopyTraitLangItem as uint].get() - } - pub fn send_trait(&self) -> def_id { - self.items[SendTraitLangItem as uint].get() - } - pub fn sized_trait(&self) -> def_id { - self.items[SizedTraitLangItem as uint].get() + pub fn require(&self, it: LangItem) -> Result { + match self.items[it as uint] { + Some(id) => Ok(id), + None => Err(fmt!("requires `%s` lang_item", + LanguageItems::item_name(it as uint))) + } } - pub fn drop_trait(&self) -> def_id { - self.items[DropTraitLangItem as uint].get() + pub fn freeze_trait(&self) -> Option { + self.items[FreezeTraitLangItem as uint] + } + pub fn copy_trait(&self) -> Option { + self.items[CopyTraitLangItem as uint] + } + pub fn send_trait(&self) -> Option { + self.items[SendTraitLangItem as uint] + } + pub fn sized_trait(&self) -> Option { + self.items[SizedTraitLangItem as uint] } - pub fn add_trait(&self) -> def_id { - self.items[AddTraitLangItem as uint].get() - } - pub fn sub_trait(&self) -> def_id { - self.items[SubTraitLangItem as uint].get() - } - pub fn mul_trait(&self) -> def_id { - self.items[MulTraitLangItem as uint].get() - } - pub fn div_trait(&self) -> def_id { - self.items[DivTraitLangItem as uint].get() - } - pub fn rem_trait(&self) -> def_id { - self.items[RemTraitLangItem as uint].get() - } - pub fn neg_trait(&self) -> def_id { - self.items[NegTraitLangItem as uint].get() - } - pub fn not_trait(&self) -> def_id { - self.items[NotTraitLangItem as uint].get() - } - pub fn bitxor_trait(&self) -> def_id { - self.items[BitXorTraitLangItem as uint].get() - } - pub fn bitand_trait(&self) -> def_id { - self.items[BitAndTraitLangItem as uint].get() - } - pub fn bitor_trait(&self) -> def_id { - self.items[BitOrTraitLangItem as uint].get() - } - pub fn shl_trait(&self) -> def_id { - self.items[ShlTraitLangItem as uint].get() - } - pub fn shr_trait(&self) -> def_id { - self.items[ShrTraitLangItem as uint].get() - } - pub fn index_trait(&self) -> def_id { - self.items[IndexTraitLangItem as uint].get() + pub fn drop_trait(&self) -> Option { + self.items[DropTraitLangItem as uint] } - pub fn eq_trait(&self) -> def_id { - self.items[EqTraitLangItem as uint].get() + pub fn add_trait(&self) -> Option { + self.items[AddTraitLangItem as uint] } - pub fn ord_trait(&self) -> def_id { - self.items[OrdTraitLangItem as uint].get() + pub fn sub_trait(&self) -> Option { + self.items[SubTraitLangItem as uint] + } + pub fn mul_trait(&self) -> Option { + self.items[MulTraitLangItem as uint] + } + pub fn div_trait(&self) -> Option { + self.items[DivTraitLangItem as uint] + } + pub fn rem_trait(&self) -> Option { + self.items[RemTraitLangItem as uint] + } + pub fn neg_trait(&self) -> Option { + self.items[NegTraitLangItem as uint] + } + pub fn not_trait(&self) -> Option { + self.items[NotTraitLangItem as uint] + } + pub fn bitxor_trait(&self) -> Option { + self.items[BitXorTraitLangItem as uint] + } + pub fn bitand_trait(&self) -> Option { + self.items[BitAndTraitLangItem as uint] + } + pub fn bitor_trait(&self) -> Option { + self.items[BitOrTraitLangItem as uint] + } + pub fn shl_trait(&self) -> Option { + self.items[ShlTraitLangItem as uint] + } + pub fn shr_trait(&self) -> Option { + self.items[ShrTraitLangItem as uint] + } + pub fn index_trait(&self) -> Option { + self.items[IndexTraitLangItem as uint] } - pub fn str_eq_fn(&self) -> def_id { - self.items[StrEqFnLangItem as uint].get() + pub fn eq_trait(&self) -> Option { + self.items[EqTraitLangItem as uint] } - pub fn uniq_str_eq_fn(&self) -> def_id { - self.items[UniqStrEqFnLangItem as uint].get() + pub fn ord_trait(&self) -> Option { + self.items[OrdTraitLangItem as uint] } - pub fn annihilate_fn(&self) -> def_id { - self.items[AnnihilateFnLangItem as uint].get() + + pub fn str_eq_fn(&self) -> Option { + self.items[StrEqFnLangItem as uint] } - pub fn log_type_fn(&self) -> def_id { - self.items[LogTypeFnLangItem as uint].get() + pub fn uniq_str_eq_fn(&self) -> Option { + self.items[UniqStrEqFnLangItem as uint] } - pub fn fail_fn(&self) -> def_id { - self.items[FailFnLangItem as uint].get() + pub fn annihilate_fn(&self) -> Option { + self.items[AnnihilateFnLangItem as uint] } - pub fn fail_bounds_check_fn(&self) -> def_id { - self.items[FailBoundsCheckFnLangItem as uint].get() + pub fn log_type_fn(&self) -> Option { + self.items[LogTypeFnLangItem as uint] } - pub fn exchange_malloc_fn(&self) -> def_id { - self.items[ExchangeMallocFnLangItem as uint].get() + pub fn fail_fn(&self) -> Option { + self.items[FailFnLangItem as uint] } - pub fn closure_exchange_malloc_fn(&self) -> def_id { - self.items[ClosureExchangeMallocFnLangItem as uint].get() + pub fn fail_bounds_check_fn(&self) -> Option { + self.items[FailBoundsCheckFnLangItem as uint] } - pub fn exchange_free_fn(&self) -> def_id { - self.items[ExchangeFreeFnLangItem as uint].get() + pub fn exchange_malloc_fn(&self) -> Option { + self.items[ExchangeMallocFnLangItem as uint] } - pub fn malloc_fn(&self) -> def_id { - self.items[MallocFnLangItem as uint].get() + pub fn closure_exchange_malloc_fn(&self) -> Option { + self.items[ClosureExchangeMallocFnLangItem as uint] } - pub fn free_fn(&self) -> def_id { - self.items[FreeFnLangItem as uint].get() + pub fn exchange_free_fn(&self) -> Option { + self.items[ExchangeFreeFnLangItem as uint] } - pub fn borrow_as_imm_fn(&self) -> def_id { - self.items[BorrowAsImmFnLangItem as uint].get() + pub fn malloc_fn(&self) -> Option { + self.items[MallocFnLangItem as uint] } - pub fn borrow_as_mut_fn(&self) -> def_id { - self.items[BorrowAsMutFnLangItem as uint].get() + pub fn free_fn(&self) -> Option { + self.items[FreeFnLangItem as uint] } - pub fn return_to_mut_fn(&self) -> def_id { - self.items[ReturnToMutFnLangItem as uint].get() + pub fn borrow_as_imm_fn(&self) -> Option { + self.items[BorrowAsImmFnLangItem as uint] } - pub fn check_not_borrowed_fn(&self) -> def_id { - self.items[CheckNotBorrowedFnLangItem as uint].get() + pub fn borrow_as_mut_fn(&self) -> Option { + self.items[BorrowAsMutFnLangItem as uint] } - pub fn strdup_uniq_fn(&self) -> def_id { - self.items[StrDupUniqFnLangItem as uint].get() + pub fn return_to_mut_fn(&self) -> Option { + self.items[ReturnToMutFnLangItem as uint] } - pub fn record_borrow_fn(&self) -> def_id { - self.items[RecordBorrowFnLangItem as uint].get() + pub fn check_not_borrowed_fn(&self) -> Option { + self.items[CheckNotBorrowedFnLangItem as uint] } - pub fn unrecord_borrow_fn(&self) -> def_id { - self.items[UnrecordBorrowFnLangItem as uint].get() + pub fn strdup_uniq_fn(&self) -> Option { + self.items[StrDupUniqFnLangItem as uint] } - pub fn start_fn(&self) -> def_id { - self.items[StartFnLangItem as uint].get() + pub fn record_borrow_fn(&self) -> Option { + self.items[RecordBorrowFnLangItem as uint] } - pub fn ty_desc(&const self) -> def_id { - self.items[TyDescStructLangItem as uint].get() + pub fn unrecord_borrow_fn(&self) -> Option { + self.items[UnrecordBorrowFnLangItem as uint] } - pub fn ty_visitor(&const self) -> def_id { - self.items[TyVisitorTraitLangItem as uint].get() + pub fn start_fn(&self) -> Option { + self.items[StartFnLangItem as uint] } - pub fn opaque(&const self) -> def_id { - self.items[OpaqueStructLangItem as uint].get() + pub fn ty_desc(&self) -> Option { + self.items[TyDescStructLangItem as uint] + } + pub fn ty_visitor(&self) -> Option { + self.items[TyVisitorTraitLangItem as uint] + } + pub fn opaque(&self) -> Option { + self.items[OpaqueStructLangItem as uint] } } @@ -439,23 +447,9 @@ impl<'self> LanguageItemCollector<'self> { } } - pub fn check_completeness(&self) { - for self.item_refs.iter().advance |(&key, &item_ref)| { - match self.items.items[item_ref] { - None => { - self.session.err(fmt!("no item found for `%s`", key)); - } - Some(_) => { - // OK. - } - } - } - } - pub fn collect(&mut self) { self.collect_local_language_items(); self.collect_external_language_items(); - self.check_completeness(); } } diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs index 619bfbdb547..6a84e568219 100644 --- a/src/librustc/middle/resolve.rs +++ b/src/librustc/middle/resolve.rs @@ -5268,8 +5268,13 @@ impl Resolver { pub fn add_fixed_trait_for_expr(@mut self, expr_id: node_id, - trait_id: def_id) { - self.trait_map.insert(expr_id, @mut ~[trait_id]); + trait_id: Option) { + match trait_id { + Some(trait_id) => { + self.trait_map.insert(expr_id, @mut ~[trait_id]); + } + None => {} + } } pub fn record_def(@mut self, node_id: node_id, def: def) { diff --git a/src/librustc/middle/trans/_match.rs b/src/librustc/middle/trans/_match.rs index d5d0cde1ee0..2f27949e869 100644 --- a/src/librustc/middle/trans/_match.rs +++ b/src/librustc/middle/trans/_match.rs @@ -152,6 +152,7 @@ use back::abi; use lib::llvm::{llvm, ValueRef, BasicBlockRef}; use middle::const_eval; use middle::borrowck::root_map_key; +use middle::lang_items::{UniqStrEqFnLangItem, StrEqFnLangItem}; use middle::pat_util::*; use middle::resolve::DefMap; use middle::trans::adt; @@ -1099,7 +1100,9 @@ pub fn compare_values(cx: block, Store(cx, lhs, scratch_lhs); let scratch_rhs = alloca(cx, val_ty(rhs), "__rhs"); Store(cx, rhs, scratch_rhs); - let did = cx.tcx().lang_items.uniq_str_eq_fn(); + let did = langcall(cx, None, + fmt!("comparison of `%s`", cx.ty_to_str(rhs_t)), + UniqStrEqFnLangItem); let result = callee::trans_lang_call(cx, did, [scratch_lhs, scratch_rhs], None); Result { bcx: result.bcx, @@ -1107,7 +1110,9 @@ pub fn compare_values(cx: block, } } ty::ty_estr(_) => { - let did = cx.tcx().lang_items.str_eq_fn(); + let did = langcall(cx, None, + fmt!("comparison of `%s`", cx.ty_to_str(rhs_t)), + StrEqFnLangItem); let result = callee::trans_lang_call(cx, did, [lhs, rhs], None); Result { bcx: result.bcx, diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index fc635954237..d7c04907513 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -34,6 +34,8 @@ use lib; use metadata::common::LinkMeta; use metadata::{csearch, cstore, encoder}; use middle::astencode; +use middle::lang_items::{LangItem, ExchangeMallocFnLangItem, StartFnLangItem}; +use middle::lang_items::{MallocFnLangItem, ClosureExchangeMallocFnLangItem}; use middle::resolve; use middle::trans::_match; use middle::trans::adt; @@ -284,13 +286,25 @@ pub fn malloc_raw_dyn(bcx: block, let _icx = push_ctxt("malloc_raw"); let ccx = bcx.ccx(); + fn require_alloc_fn(bcx: block, t: ty::t, it: LangItem) -> ast::def_id { + let li = &bcx.tcx().lang_items; + match li.require(it) { + Ok(id) => id, + Err(s) => { + bcx.tcx().sess.fatal(fmt!("allocation of `%s` %s", + bcx.ty_to_str(t), s)); + } + } + } + if heap == heap_exchange { let llty_value = type_of::type_of(ccx, t); + // Allocate space: let r = callee::trans_lang_call( bcx, - bcx.tcx().lang_items.exchange_malloc_fn(), + require_alloc_fn(bcx, t, ExchangeMallocFnLangItem), [size], None); rslt(r.bcx, PointerCast(r.bcx, r.val, llty_value.ptr_to())) @@ -298,10 +312,12 @@ pub fn malloc_raw_dyn(bcx: block, // we treat ~fn, @fn and @[] as @ here, which isn't ideal let (mk_fn, langcall) = match heap { heap_managed | heap_managed_unique => { - (ty::mk_imm_box, bcx.tcx().lang_items.malloc_fn()) + (ty::mk_imm_box, + require_alloc_fn(bcx, t, MallocFnLangItem)) } heap_exchange_closure => { - (ty::mk_imm_box, bcx.tcx().lang_items.closure_exchange_malloc_fn()) + (ty::mk_imm_box, + require_alloc_fn(bcx, t, ClosureExchangeMallocFnLangItem)) } _ => fail!("heap_exchange already handled") }; @@ -2324,7 +2340,8 @@ pub fn create_entry_wrapper(ccx: @mut CrateContext, fn create_entry_fn(ccx: @mut CrateContext, rust_main: ValueRef, use_start_lang_item: bool) { - let llfty = Type::func([ccx.int_type, Type::i8().ptr_to().ptr_to()], &ccx.int_type); + let llfty = Type::func([ccx.int_type, Type::i8().ptr_to().ptr_to()], + &ccx.int_type); // FIXME #4404 android JNI hacks let llfn = if *ccx.sess.building_library { @@ -2345,25 +2362,21 @@ pub fn create_entry_wrapper(ccx: @mut CrateContext, unsafe { llvm::LLVMPositionBuilderAtEnd(bld, llbb); - let start_def_id = ccx.tcx.lang_items.start_fn(); - if start_def_id.crate != ast::local_crate { - let start_fn_type = csearch::get_type(ccx.tcx, - start_def_id).ty; - trans_external_path(ccx, start_def_id, start_fn_type); - } - let crate_map = ccx.crate_map; let opaque_crate_map = do "crate_map".as_c_str |buf| { llvm::LLVMBuildPointerCast(bld, crate_map, Type::i8p().to_ref(), buf) }; let (start_fn, args) = if use_start_lang_item { - let start_def_id = ccx.tcx.lang_items.start_fn(); + let start_def_id = match ccx.tcx.lang_items.require(StartFnLangItem) { + Ok(id) => id, + Err(s) => { ccx.tcx.sess.fatal(s); } + }; let start_fn = if start_def_id.crate == ast::local_crate { get_item_val(ccx, start_def_id.node) } else { let start_fn_type = csearch::get_type(ccx.tcx, - start_def_id).ty; + start_def_id).ty; trans_external_path(ccx, start_def_id, start_fn_type) }; @@ -2383,14 +2396,12 @@ pub fn create_entry_wrapper(ccx: @mut CrateContext, (start_fn, args) } else { debug!("using user-defined start fn"); - let args = { - ~[ - C_null(Type::opaque_box(ccx).ptr_to()), - llvm::LLVMGetParam(llfn, 0 as c_uint), - llvm::LLVMGetParam(llfn, 1 as c_uint), - opaque_crate_map - ] - }; + let args = ~[ + C_null(Type::opaque_box(ccx).ptr_to()), + llvm::LLVMGetParam(llfn, 0 as c_uint), + llvm::LLVMGetParam(llfn, 1 as c_uint), + opaque_crate_map + ]; (rust_main, args) }; @@ -2832,17 +2843,18 @@ pub fn fill_crate_map(ccx: @mut CrateContext, map: ValueRef) { } subcrates.push(C_int(ccx, 0)); - let llannihilatefn; - let annihilate_def_id = ccx.tcx.lang_items.annihilate_fn(); - if annihilate_def_id.crate == ast::local_crate { - llannihilatefn = get_item_val(ccx, annihilate_def_id.node); - } else { - let annihilate_fn_type = csearch::get_type(ccx.tcx, - annihilate_def_id).ty; - llannihilatefn = trans_external_path(ccx, - annihilate_def_id, - annihilate_fn_type); - } + let llannihilatefn = match ccx.tcx.lang_items.annihilate_fn() { + Some(annihilate_def_id) => { + if annihilate_def_id.crate == ast::local_crate { + get_item_val(ccx, annihilate_def_id.node) + } else { + let annihilate_fn_type = csearch::get_type(ccx.tcx, + annihilate_def_id).ty; + trans_external_path(ccx, annihilate_def_id, annihilate_fn_type) + } + } + None => { C_null(Type::i8p()) } + }; unsafe { let mod_map = create_module_map(ccx); diff --git a/src/librustc/middle/trans/closure.rs b/src/librustc/middle/trans/closure.rs index d2953f8913e..4e754bea916 100644 --- a/src/librustc/middle/trans/closure.rs +++ b/src/librustc/middle/trans/closure.rs @@ -13,6 +13,7 @@ use back::abi; use back::link::{mangle_internal_name_by_path_and_seq}; use lib::llvm::{llvm, ValueRef}; use middle::moves; +use middle::lang_items::ClosureExchangeMallocFnLangItem; use middle::trans::base::*; use middle::trans::build::*; use middle::trans::callee; @@ -541,9 +542,13 @@ pub fn make_opaque_cbox_take_glue( // Allocate memory, update original ptr, and copy existing data let opaque_tydesc = PointerCast(bcx, tydesc, Type::i8p()); let mut bcx = bcx; + let alloc_fn = langcall(bcx, None, + fmt!("allocation of type with sigil `%s`", + sigil.to_str()), + ClosureExchangeMallocFnLangItem); let llresult = unpack_result!(bcx, callee::trans_lang_call( bcx, - bcx.tcx().lang_items.closure_exchange_malloc_fn(), + alloc_fn, [opaque_tydesc, sz], None)); let cbox_out = PointerCast(bcx, llresult, llopaquecboxty); diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs index 196807baabb..ea5068c445b 100644 --- a/src/librustc/middle/trans/common.rs +++ b/src/librustc/middle/trans/common.rs @@ -17,6 +17,7 @@ use lib::llvm::{ValueRef, BasicBlockRef, BuilderRef}; use lib::llvm::{True, False, Bool}; use lib::llvm::{llvm}; use lib; +use middle::lang_items::LangItem; use middle::trans::base; use middle::trans::build; use middle::trans::datum; @@ -1126,3 +1127,17 @@ pub fn filename_and_line_num_from_span(bcx: block, pub fn bool_to_i1(bcx: block, llval: ValueRef) -> ValueRef { build::ICmp(bcx, lib::llvm::IntNE, llval, C_bool(false)) } + +pub fn langcall(bcx: block, span: Option, msg: &str, + li: LangItem) -> ast::def_id { + match bcx.tcx().lang_items.require(li) { + Ok(id) => id, + Err(s) => { + let msg = fmt!("%s %s", msg, s); + match span { + Some(span) => { bcx.tcx().sess.span_fatal(span, msg); } + None => { bcx.tcx().sess.fatal(msg); } + } + } + } +} diff --git a/src/librustc/middle/trans/controlflow.rs b/src/librustc/middle/trans/controlflow.rs index 36f1f5cdbef..df1db4a1ab3 100644 --- a/src/librustc/middle/trans/controlflow.rs +++ b/src/librustc/middle/trans/controlflow.rs @@ -12,6 +12,8 @@ use back::link; use lib; use lib::llvm::*; +use middle::lang_items::{FailFnLangItem, FailBoundsCheckFnLangItem}; +use middle::lang_items::LogTypeFnLangItem; use middle::trans::base::*; use middle::trans::build::*; use middle::trans::callee; @@ -276,7 +278,7 @@ pub fn trans_log(log_ex: &ast::expr, // Call the polymorphic log function let val = val_datum.to_ref_llval(bcx); - let did = bcx.tcx().lang_items.log_type_fn(); + let did = langcall(bcx, Some(e.span), "", LogTypeFnLangItem); let bcx = callee::trans_lang_call_with_type_params( bcx, did, [level, val], [val_datum.ty], expr::Ignore); bcx @@ -435,8 +437,8 @@ fn trans_fail_value(bcx: block, let V_str = PointerCast(bcx, V_fail_str, Type::i8p()); let V_filename = PointerCast(bcx, V_filename, Type::i8p()); let args = ~[V_str, V_filename, C_int(ccx, V_line)]; - let bcx = callee::trans_lang_call( - bcx, bcx.tcx().lang_items.fail_fn(), args, Some(expr::Ignore)).bcx; + let did = langcall(bcx, sp_opt, "", FailFnLangItem); + let bcx = callee::trans_lang_call(bcx, did, args, Some(expr::Ignore)).bcx; Unreachable(bcx); return bcx; } @@ -446,8 +448,8 @@ pub fn trans_fail_bounds_check(bcx: block, sp: span, 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]; - let bcx = callee::trans_lang_call( - bcx, bcx.tcx().lang_items.fail_bounds_check_fn(), args, Some(expr::Ignore)).bcx; + let did = langcall(bcx, Some(sp), "", FailBoundsCheckFnLangItem); + let bcx = callee::trans_lang_call(bcx, did, args, Some(expr::Ignore)).bcx; Unreachable(bcx); return bcx; } diff --git a/src/librustc/middle/trans/glue.rs b/src/librustc/middle/trans/glue.rs index f007aa502dc..c92bfc23b1d 100644 --- a/src/librustc/middle/trans/glue.rs +++ b/src/librustc/middle/trans/glue.rs @@ -18,6 +18,7 @@ use back::link::*; use driver::session; use lib; use lib::llvm::{llvm, ValueRef, True}; +use middle::lang_items::{FreeFnLangItem, ExchangeFreeFnLangItem}; use middle::trans::adt; use middle::trans::base::*; use middle::trans::callee; @@ -44,7 +45,7 @@ use syntax::ast; pub fn trans_free(cx: block, v: ValueRef) -> block { let _icx = push_ctxt("trans_free"); callee::trans_lang_call(cx, - cx.tcx().lang_items.free_fn(), + langcall(cx, None, "", FreeFnLangItem), [PointerCast(cx, v, Type::i8p())], Some(expr::Ignore)).bcx } @@ -52,7 +53,7 @@ pub fn trans_free(cx: block, v: ValueRef) -> block { pub fn trans_exchange_free(cx: block, v: ValueRef) -> block { let _icx = push_ctxt("trans_exchange_free"); callee::trans_lang_call(cx, - cx.tcx().lang_items.exchange_free_fn(), + langcall(cx, None, "", ExchangeFreeFnLangItem), [PointerCast(cx, v, Type::i8p())], Some(expr::Ignore)).bcx } @@ -365,7 +366,12 @@ pub fn make_visit_glue(bcx: block, v: ValueRef, t: ty::t) -> block { let _icx = push_ctxt("make_visit_glue"); do with_scope(bcx, None, "visitor cleanup") |bcx| { let mut bcx = bcx; - let (visitor_trait, object_ty) = ty::visitor_object_ty(bcx.tcx()); + let (visitor_trait, object_ty) = match ty::visitor_object_ty(bcx.tcx()){ + Ok(pair) => pair, + Err(s) => { + bcx.tcx().sess.fatal(s); + } + }; let v = PointerCast(bcx, v, type_of::type_of(bcx.ccx(), object_ty).ptr_to()); bcx = reflect::emit_calls_to_trait_visit_ty(bcx, t, v, visitor_trait.def_id); // The visitor is a boxed object and needs to be dropped diff --git a/src/librustc/middle/trans/reflect.rs b/src/librustc/middle/trans/reflect.rs index 47f0a4c06af..2dc3a88fe86 100644 --- a/src/librustc/middle/trans/reflect.rs +++ b/src/librustc/middle/trans/reflect.rs @@ -279,7 +279,7 @@ impl Reflector { let repr = adt::represent_type(bcx.ccx(), t); let variants = ty::substd_enum_variants(ccx.tcx, did, substs); let llptrty = type_of(ccx, t).ptr_to(); - let opaquety = ty::get_opaque_ty(ccx.tcx); + let opaquety = ty::get_opaque_ty(ccx.tcx).unwrap(); let opaqueptrty = ty::mk_ptr(ccx.tcx, ty::mt { ty: opaquety, mutbl: ast::m_imm }); let make_get_disr = || { @@ -380,7 +380,7 @@ pub fn emit_calls_to_trait_visit_ty(bcx: block, visitor_trait_id: def_id) -> block { let final = sub_block(bcx, "final"); - let tydesc_ty = ty::get_tydesc_ty(bcx.ccx().tcx); + let tydesc_ty = ty::get_tydesc_ty(bcx.ccx().tcx).unwrap(); let tydesc_ty = type_of(bcx.ccx(), tydesc_ty); let mut r = Reflector { visitor_val: visitor_val, diff --git a/src/librustc/middle/trans/tvec.rs b/src/librustc/middle/trans/tvec.rs index 561c9a3399a..be840f6a295 100644 --- a/src/librustc/middle/trans/tvec.rs +++ b/src/librustc/middle/trans/tvec.rs @@ -12,6 +12,7 @@ use back::abi; use lib; use lib::llvm::{llvm, ValueRef}; +use middle::lang_items::StrDupUniqFnLangItem; use middle::trans::base; use middle::trans::base::*; use middle::trans::build::*; @@ -312,16 +313,18 @@ pub fn trans_uniq_or_managed_vstore(bcx: block, heap: heap, vstore_expr: @ast::e heap_exchange => { match content_expr.node { ast::expr_lit(@codemap::spanned { - node: ast::lit_str(s), _ + node: ast::lit_str(s), span }) => { let llptrval = C_cstr(bcx.ccx(), s); let llptrval = PointerCast(bcx, llptrval, Type::i8p()); let llsizeval = C_uint(bcx.ccx(), s.len()); let typ = ty::mk_estr(bcx.tcx(), ty::vstore_uniq); let lldestval = scratch_datum(bcx, typ, "", false); + let alloc_fn = langcall(bcx, Some(span), "", + StrDupUniqFnLangItem); let bcx = callee::trans_lang_call( bcx, - bcx.tcx().lang_items.strdup_uniq_fn(), + alloc_fn, [ llptrval, llsizeval ], Some(expr::SaveIn(lldestval.to_ref_llval(bcx)))).bcx; return DatumBlock { diff --git a/src/librustc/middle/trans/write_guard.rs b/src/librustc/middle/trans/write_guard.rs index 1804a7334f2..b9a9a57d046 100644 --- a/src/librustc/middle/trans/write_guard.rs +++ b/src/librustc/middle/trans/write_guard.rs @@ -17,6 +17,10 @@ use lib::llvm::ValueRef; use middle::borrowck::{RootInfo, root_map_key, DynaImm, DynaMut}; +use middle::lang_items::CheckNotBorrowedFnLangItem; +use middle::lang_items::{BorrowAsImmFnLangItem, BorrowAsMutFnLangItem}; +use middle::lang_items::{RecordBorrowFnLangItem, UnrecordBorrowFnLangItem}; +use middle::lang_items::ReturnToMutFnLangItem; use middle::trans::base::*; use middle::trans::build::*; use middle::trans::callee; @@ -74,7 +78,7 @@ pub fn return_to_mut(mut bcx: block, if bcx.tcx().sess.debug_borrows() { bcx = callee::trans_lang_call( bcx, - bcx.tcx().lang_items.unrecord_borrow_fn(), + langcall(bcx, None, "unborrow", UnrecordBorrowFnLangItem), [ box_ptr, bits_val, @@ -86,7 +90,7 @@ pub fn return_to_mut(mut bcx: block, callee::trans_lang_call( bcx, - bcx.tcx().lang_items.return_to_mut_fn(), + langcall(bcx, None, "unborrow", ReturnToMutFnLangItem), [ box_ptr, bits_val, @@ -138,16 +142,16 @@ fn root(datum: &Datum, let scratch_bits = scratch_datum(bcx, ty::mk_uint(), "__write_guard_bits", false); - let freeze_did = match freeze_kind { - DynaImm => bcx.tcx().lang_items.borrow_as_imm_fn(), - DynaMut => bcx.tcx().lang_items.borrow_as_mut_fn(), + let freeze_item = match freeze_kind { + DynaImm => BorrowAsImmFnLangItem, + DynaMut => BorrowAsMutFnLangItem, }; let box_ptr = Load(bcx, PointerCast(bcx, scratch.val, Type::i8p().ptr_to())); let llresult = unpack_result!(bcx, callee::trans_lang_call( bcx, - freeze_did, + langcall(bcx, Some(span), "freeze", freeze_item), [ box_ptr, filename, @@ -158,7 +162,7 @@ fn root(datum: &Datum, if bcx.tcx().sess.debug_borrows() { bcx = callee::trans_lang_call( bcx, - bcx.tcx().lang_items.record_borrow_fn(), + langcall(bcx, Some(span), "freeze", RecordBorrowFnLangItem), [ box_ptr, llresult, @@ -187,7 +191,7 @@ fn perform_write_guard(datum: &Datum, callee::trans_lang_call( bcx, - bcx.tcx().lang_items.check_not_borrowed_fn(), + langcall(bcx, Some(span), "write guard", CheckNotBorrowedFnLangItem), [PointerCast(bcx, llval, Type::i8p()), filename, line], Some(expr::Ignore)).bcx } diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index eb69798d0cc..5e118b25a5f 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -13,6 +13,8 @@ use driver::session; use metadata::csearch; use metadata; use middle::const_eval; +use middle::lang_items::{TyDescStructLangItem, TyVisitorTraitLangItem}; +use middle::lang_items::OpaqueStructLangItem; use middle::freevars; use middle::resolve::{Impl, MethodInfo}; use middle::resolve; @@ -4373,29 +4375,34 @@ pub fn get_impl_id(tcx: ctxt, trait_id: def_id, self_ty: t) -> def_id { } } -pub fn get_tydesc_ty(tcx: ctxt) -> t { - let tydesc_lang_item = tcx.lang_items.ty_desc(); - tcx.intrinsic_defs.find_copy(&tydesc_lang_item) - .expect("Failed to resolve TyDesc") +pub fn get_tydesc_ty(tcx: ctxt) -> Result { + do tcx.lang_items.require(TyDescStructLangItem).map |tydesc_lang_item| { + tcx.intrinsic_defs.find_copy(tydesc_lang_item) + .expect("Failed to resolve TyDesc") + } } -pub fn get_opaque_ty(tcx: ctxt) -> t { - let opaque_lang_item = tcx.lang_items.opaque(); - tcx.intrinsic_defs.find_copy(&opaque_lang_item) - .expect("Failed to resolve Opaque") +pub fn get_opaque_ty(tcx: ctxt) -> Result { + do tcx.lang_items.require(OpaqueStructLangItem).map |opaque_lang_item| { + tcx.intrinsic_defs.find_copy(opaque_lang_item) + .expect("Failed to resolve Opaque") + } } -pub fn visitor_object_ty(tcx: ctxt) -> (@TraitRef, t) { +pub fn visitor_object_ty(tcx: ctxt) -> Result<(@TraitRef, t), ~str> { + let trait_lang_item = match tcx.lang_items.require(TyVisitorTraitLangItem) { + Ok(id) => id, + Err(s) => { return Err(s); } + }; let substs = substs { self_r: None, self_ty: None, tps: ~[] }; - let trait_lang_item = tcx.lang_items.ty_visitor(); let trait_ref = @TraitRef { def_id: trait_lang_item, substs: substs }; let mut static_trait_bound = EmptyBuiltinBounds(); static_trait_bound.add(BoundStatic); - (trait_ref, - mk_trait(tcx, trait_ref.def_id, copy trait_ref.substs, - BoxTraitStore, ast::m_imm, static_trait_bound)) + Ok((trait_ref, + mk_trait(tcx, trait_ref.def_id, copy trait_ref.substs, + BoxTraitStore, ast::m_imm, static_trait_bound))) } diff --git a/src/librustc/middle/typeck/astconv.rs b/src/librustc/middle/typeck/astconv.rs index 1186f8cecab..e9297b12ed0 100644 --- a/src/librustc/middle/typeck/astconv.rs +++ b/src/librustc/middle/typeck/astconv.rs @@ -811,16 +811,16 @@ pub fn try_add_builtin_trait(tcx: ty::ctxt, //! is a builtin trait. let li = &tcx.lang_items; - if trait_def_id == li.send_trait() { + if Some(trait_def_id) == li.send_trait() { builtin_bounds.add(ty::BoundSend); true - } else if trait_def_id == li.copy_trait() { + } else if Some(trait_def_id) == li.copy_trait() { builtin_bounds.add(ty::BoundCopy); true - } else if trait_def_id == li.freeze_trait() { + } else if Some(trait_def_id) == li.freeze_trait() { builtin_bounds.add(ty::BoundFreeze); true - } else if trait_def_id == li.sized_trait() { + } else if Some(trait_def_id) == li.sized_trait() { builtin_bounds.add(ty::BoundSized); true } else { diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index 396fae68f73..87d45294967 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -3551,7 +3551,10 @@ pub fn check_intrinsic_type(ccx: @mut CrateCtxt, it: @ast::foreign_item) { } "get_tydesc" => { - let tydesc_ty = ty::get_tydesc_ty(ccx.tcx); + let tydesc_ty = match ty::get_tydesc_ty(ccx.tcx) { + Ok(t) => t, + Err(s) => { tcx.sess.span_fatal(it.span, s); } + }; let td_ptr = ty::mk_ptr(ccx.tcx, ty::mt { ty: tydesc_ty, mutbl: ast::m_imm @@ -3559,8 +3562,15 @@ pub fn check_intrinsic_type(ccx: @mut CrateCtxt, it: @ast::foreign_item) { (1u, ~[], td_ptr) } "visit_tydesc" => { - let tydesc_ty = ty::get_tydesc_ty(ccx.tcx); - let (_, visitor_object_ty) = ty::visitor_object_ty(tcx); + let tydesc_ty = match ty::get_tydesc_ty(ccx.tcx) { + Ok(t) => t, + Err(s) => { tcx.sess.span_fatal(it.span, s); } + }; + let visitor_object_ty = match ty::visitor_object_ty(tcx) { + Ok((_, vot)) => vot, + Err(s) => { tcx.sess.span_fatal(it.span, s); } + }; + let td_ptr = ty::mk_ptr(ccx.tcx, ty::mt { ty: tydesc_ty, mutbl: ast::m_imm diff --git a/src/librustc/middle/typeck/coherence.rs b/src/librustc/middle/typeck/coherence.rs index 7ee731d4f46..768c4cd04e7 100644 --- a/src/librustc/middle/typeck/coherence.rs +++ b/src/librustc/middle/typeck/coherence.rs @@ -960,7 +960,9 @@ impl CoherenceChecker { pub fn populate_destructor_table(&self) { let coherence_info = &self.crate_context.coherence_info; let tcx = self.crate_context.tcx; - let drop_trait = tcx.lang_items.drop_trait(); + let drop_trait = match tcx.lang_items.drop_trait() { + Some(id) => id, None => { return } + }; let impls_opt = coherence_info.extension_methods.find(&drop_trait); let impls; diff --git a/src/librustc/middle/typeck/collect.rs b/src/librustc/middle/typeck/collect.rs index ec384543dea..16ddef2b8e0 100644 --- a/src/librustc/middle/typeck/collect.rs +++ b/src/librustc/middle/typeck/collect.rs @@ -69,8 +69,12 @@ pub fn collect_item_types(ccx: @mut CrateCtxt, crate: &ast::crate) { ccx.tcx.intrinsic_defs.insert(lang_item, ty); } - collect_intrinsic_type(ccx, ccx.tcx.lang_items.ty_desc()); - collect_intrinsic_type(ccx, ccx.tcx.lang_items.opaque()); + match ccx.tcx.lang_items.ty_desc() { + Some(id) => { collect_intrinsic_type(ccx, id); } None => {} + } + match ccx.tcx.lang_items.opaque() { + Some(id) => { collect_intrinsic_type(ccx, id); } None => {} + } visit::visit_crate( crate, ((), diff --git a/src/test/run-pass/smallest-hello-world.rs b/src/test/run-pass/smallest-hello-world.rs new file mode 100644 index 00000000000..bbd5857335d --- /dev/null +++ b/src/test/run-pass/smallest-hello-world.rs @@ -0,0 +1,41 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// xfail-fast - windows doesn't like this + +// Smallest hello world with no runtime + +#[no_std]; + +// This is an unfortunate thing to have to do on linux :( +#[cfg(target_os = "linux")] +#[doc(hidden)] +pub mod linkhack { + #[link_args="-lrustrt -lrt"] + extern {} +} + +extern { + fn puts(s: *u8); +} + +extern "rust-intrinsic" { + fn transmute(t: T) -> U; +} + +#[start] +fn main(_: int, _: **u8, _: *u8) -> int { + unsafe { + let (ptr, _): (*u8, uint) = transmute("Hello!"); + puts(ptr); + } + return 0; +} +