auto merge of #7828 : alexcrichton/rust/lang-opt, r=graydon

Whenever a lang_item is required, some relevant message is displayed, often with
a span of what triggered the usage of the lang item.

Now "hello word" is as small as:

```rust
#[no_std];

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;
}
```
This commit is contained in:
bors 2013-07-16 23:10:44 -07:00
commit af54f633fd
18 changed files with 309 additions and 194 deletions

View File

@ -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) => {

View File

@ -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();
}
}

View File

@ -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) {

View File

@ -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,

View File

@ -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);

View File

@ -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);

View File

@ -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); }
}
}
}
}

View File

@ -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;
}

View File

@ -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

View File

@ -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,

View File

@ -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 {

View File

@ -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
}

View File

@ -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<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)))
}

View File

@ -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 {

View File

@ -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

View File

@ -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;

View File

@ -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, ((),

View 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;
}