Make all lang_items optional
Whenever a lang_item is required, some relevant message is displayed, often with a span of what triggered the usage of the lang item
This commit is contained in:
parent
9db190305f
commit
88a1b71305
@ -122,7 +122,7 @@ fn check_item(item: @item, (cx, visitor): (Context, visit::vt<Context>)) {
|
||||
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) => {
|
||||
|
@ -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<def_id, ~str> {
|
||||
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<def_id> {
|
||||
self.items[FreezeTraitLangItem as uint]
|
||||
}
|
||||
pub fn copy_trait(&self) -> Option<def_id> {
|
||||
self.items[CopyTraitLangItem as uint]
|
||||
}
|
||||
pub fn send_trait(&self) -> Option<def_id> {
|
||||
self.items[SendTraitLangItem as uint]
|
||||
}
|
||||
pub fn sized_trait(&self) -> Option<def_id> {
|
||||
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<def_id> {
|
||||
self.items[DropTraitLangItem as uint]
|
||||
}
|
||||
|
||||
pub fn eq_trait(&self) -> def_id {
|
||||
self.items[EqTraitLangItem as uint].get()
|
||||
pub fn add_trait(&self) -> Option<def_id> {
|
||||
self.items[AddTraitLangItem as uint]
|
||||
}
|
||||
pub fn ord_trait(&self) -> def_id {
|
||||
self.items[OrdTraitLangItem as uint].get()
|
||||
pub fn sub_trait(&self) -> Option<def_id> {
|
||||
self.items[SubTraitLangItem as uint]
|
||||
}
|
||||
pub fn mul_trait(&self) -> Option<def_id> {
|
||||
self.items[MulTraitLangItem as uint]
|
||||
}
|
||||
pub fn div_trait(&self) -> Option<def_id> {
|
||||
self.items[DivTraitLangItem as uint]
|
||||
}
|
||||
pub fn rem_trait(&self) -> Option<def_id> {
|
||||
self.items[RemTraitLangItem as uint]
|
||||
}
|
||||
pub fn neg_trait(&self) -> Option<def_id> {
|
||||
self.items[NegTraitLangItem as uint]
|
||||
}
|
||||
pub fn not_trait(&self) -> Option<def_id> {
|
||||
self.items[NotTraitLangItem as uint]
|
||||
}
|
||||
pub fn bitxor_trait(&self) -> Option<def_id> {
|
||||
self.items[BitXorTraitLangItem as uint]
|
||||
}
|
||||
pub fn bitand_trait(&self) -> Option<def_id> {
|
||||
self.items[BitAndTraitLangItem as uint]
|
||||
}
|
||||
pub fn bitor_trait(&self) -> Option<def_id> {
|
||||
self.items[BitOrTraitLangItem as uint]
|
||||
}
|
||||
pub fn shl_trait(&self) -> Option<def_id> {
|
||||
self.items[ShlTraitLangItem as uint]
|
||||
}
|
||||
pub fn shr_trait(&self) -> Option<def_id> {
|
||||
self.items[ShrTraitLangItem as uint]
|
||||
}
|
||||
pub fn index_trait(&self) -> Option<def_id> {
|
||||
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<def_id> {
|
||||
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<def_id> {
|
||||
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<def_id> {
|
||||
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<def_id> {
|
||||
self.items[UniqStrEqFnLangItem as uint]
|
||||
}
|
||||
pub fn fail_fn(&self) -> def_id {
|
||||
self.items[FailFnLangItem as uint].get()
|
||||
pub fn annihilate_fn(&self) -> Option<def_id> {
|
||||
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<def_id> {
|
||||
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<def_id> {
|
||||
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<def_id> {
|
||||
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<def_id> {
|
||||
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<def_id> {
|
||||
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<def_id> {
|
||||
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<def_id> {
|
||||
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<def_id> {
|
||||
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<def_id> {
|
||||
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<def_id> {
|
||||
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<def_id> {
|
||||
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<def_id> {
|
||||
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<def_id> {
|
||||
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<def_id> {
|
||||
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<def_id> {
|
||||
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<def_id> {
|
||||
self.items[StartFnLangItem as uint]
|
||||
}
|
||||
pub fn opaque(&const self) -> def_id {
|
||||
self.items[OpaqueStructLangItem as uint].get()
|
||||
pub fn ty_desc(&self) -> Option<def_id> {
|
||||
self.items[TyDescStructLangItem as uint]
|
||||
}
|
||||
pub fn ty_visitor(&self) -> Option<def_id> {
|
||||
self.items[TyVisitorTraitLangItem as uint]
|
||||
}
|
||||
pub fn opaque(&self) -> Option<def_id> {
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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<def_id>) {
|
||||
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) {
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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<span>, 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); }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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;
|
||||
@ -4358,29 +4360,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<t, ~str> {
|
||||
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<t, ~str> {
|
||||
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)))
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -3541,7 +3541,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
|
||||
@ -3549,8 +3552,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
|
||||
|
@ -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;
|
||||
|
@ -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, ((),
|
||||
|
41
src/test/run-pass/smallest-hello-world.rs
Normal file
41
src/test/run-pass/smallest-hello-world.rs
Normal file
@ -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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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, U>(t: T) -> U;
|
||||
}
|
||||
|
||||
#[start]
|
||||
fn main(_: int, _: **u8, _: *u8) -> int {
|
||||
unsafe {
|
||||
let (ptr, _): (*u8, uint) = transmute("Hello!");
|
||||
puts(ptr);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user