librustc: Fold rt items into lang items. Shaves another 10% or so off hello world compile time.

This commit is contained in:
Patrick Walton 2013-01-07 12:21:34 -08:00
parent d2d1d98968
commit 9f387926fc
8 changed files with 101 additions and 143 deletions

View File

@ -38,15 +38,14 @@ extern mod rustrt {
fn rust_upcall_free(ptr: *c_char);
}
// FIXME (#2861): This needs both the attribute, and the name prefixed with
// 'rt_', otherwise the compiler won't find it. To fix this, see
// gather_rust_rtcalls.
#[rt(fail_)]
#[lang="fail_"]
pub fn rt_fail_(expr: *c_char, file: *c_char, line: size_t) -> ! {
sys::begin_unwind_(expr, file, line);
}
#[rt(fail_bounds_check)]
#[lang="fail_bounds_check"]
pub fn rt_fail_bounds_check(file: *c_char, line: size_t,
index: size_t, len: size_t) {
let msg = fmt!("index out of bounds: the len is %d but the index is %d",
@ -57,6 +56,7 @@ pub fn rt_fail_bounds_check(file: *c_char, line: size_t,
}
#[rt(exchange_malloc)]
#[lang="exchange_malloc"]
pub fn rt_exchange_malloc(td: *c_char, size: uintptr_t) -> *c_char {
return rustrt::rust_upcall_exchange_malloc(td, size);
}
@ -65,11 +65,13 @@ pub fn rt_exchange_malloc(td: *c_char, size: uintptr_t) -> *c_char {
// inside a landing pad may corrupt the state of the exception handler. If a
// problem occurs, call exit instead.
#[rt(exchange_free)]
#[lang="exchange_free"]
pub fn rt_exchange_free(ptr: *c_char) {
rustrt::rust_upcall_exchange_free(ptr);
}
#[rt(malloc)]
#[lang="malloc"]
pub fn rt_malloc(td: *c_char, size: uintptr_t) -> *c_char {
return rustrt::rust_upcall_malloc(td, size);
}
@ -78,6 +80,7 @@ pub fn rt_malloc(td: *c_char, size: uintptr_t) -> *c_char {
// inside a landing pad may corrupt the state of the exception handler. If a
// problem occurs, call exit instead.
#[rt(free)]
#[lang="free"]
pub fn rt_free(ptr: *c_char) {
rustrt::rust_upcall_free(ptr);
}

View File

@ -34,43 +34,49 @@ use std::map::HashMap;
use str_eq = str::eq;
pub enum LangItem {
ConstTraitLangItem, // 0
CopyTraitLangItem, // 1
OwnedTraitLangItem, // 2
DurableTraitLangItem, // 3
ConstTraitLangItem, // 0
CopyTraitLangItem, // 1
OwnedTraitLangItem, // 2
DurableTraitLangItem, // 3
DropTraitLangItem, // 4
DropTraitLangItem, // 4
AddTraitLangItem, // 5
SubTraitLangItem, // 6
MulTraitLangItem, // 7
DivTraitLangItem, // 8
ModuloTraitLangItem, // 9
NegTraitLangItem, // 10
BitXorTraitLangItem, // 11
BitAndTraitLangItem, // 12
BitOrTraitLangItem, // 13
ShlTraitLangItem, // 14
ShrTraitLangItem, // 15
IndexTraitLangItem, // 16
AddTraitLangItem, // 5
SubTraitLangItem, // 6
MulTraitLangItem, // 7
DivTraitLangItem, // 8
ModuloTraitLangItem, // 9
NegTraitLangItem, // 10
BitXorTraitLangItem, // 11
BitAndTraitLangItem, // 12
BitOrTraitLangItem, // 13
ShlTraitLangItem, // 14
ShrTraitLangItem, // 15
IndexTraitLangItem, // 16
EqTraitLangItem, // 17
OrdTraitLangItem, // 18
EqTraitLangItem, // 17
OrdTraitLangItem, // 18
StrEqFnLangItem, // 19
UniqStrEqFnLangItem, // 20
AnnihilateFnLangItem, // 21
LogTypeFnLangItem, // 22
StrEqFnLangItem, // 19
UniqStrEqFnLangItem, // 20
AnnihilateFnLangItem, // 21
LogTypeFnLangItem, // 22
FailFnLangItem, // 23
FailBoundsCheckFnLangItem, // 24
ExchangeMallocFnLangItem, // 25
ExchangeFreeFnLangItem, // 26
MallocFnLangItem, // 27
FreeFnLangItem, // 28
}
struct LanguageItems {
items: [ Option<def_id> * 23 ]
items: [ Option<def_id> * 29 ]
}
impl LanguageItems {
static pub fn new() -> LanguageItems {
LanguageItems {
items: [ None, ..23 ]
items: [ None, ..29 ]
}
}
@ -110,6 +116,12 @@ impl LanguageItems {
20 => "uniq_str_eq",
21 => "annihilate",
22 => "log_type",
23 => "fail_",
24 => "fail_bounds_check",
25 => "exchange_malloc",
26 => "exchange_free",
27 => "malloc",
28 => "free",
_ => "???"
}
@ -190,6 +202,24 @@ impl LanguageItems {
pub fn log_type_fn(&const self) -> def_id {
self.items[LogTypeFnLangItem as uint].get()
}
pub fn fail_fn(&const self) -> def_id {
self.items[FailFnLangItem as uint].get()
}
pub fn fail_bounds_check_fn(&const self) -> def_id {
self.items[FailBoundsCheckFnLangItem as uint].get()
}
pub fn exchange_malloc_fn(&const self) -> def_id {
self.items[ExchangeMallocFnLangItem as uint].get()
}
pub fn exchange_free_fn(&const self) -> def_id {
self.items[ExchangeFreeFnLangItem as uint].get()
}
pub fn malloc_fn(&const self) -> def_id {
self.items[MallocFnLangItem as uint].get()
}
pub fn free_fn(&const self) -> def_id {
self.items[FreeFnLangItem as uint].get()
}
}
fn LanguageItemCollector(crate: @crate,
@ -225,6 +255,12 @@ fn LanguageItemCollector(crate: @crate,
item_refs.insert(~"uniq_str_eq", UniqStrEqFnLangItem as uint);
item_refs.insert(~"annihilate", AnnihilateFnLangItem as uint);
item_refs.insert(~"log_type", LogTypeFnLangItem as uint);
item_refs.insert(~"fail_", FailFnLangItem as uint);
item_refs.insert(~"fail_bounds_check", FailBoundsCheckFnLangItem as uint);
item_refs.insert(~"exchange_malloc", ExchangeMallocFnLangItem as uint);
item_refs.insert(~"exchange_free", ExchangeFreeFnLangItem as uint);
item_refs.insert(~"malloc", MallocFnLangItem as uint);
item_refs.insert(~"free", FreeFnLangItem as uint);
LanguageItemCollector {
crate: crate,

View File

@ -262,14 +262,20 @@ fn opaque_box_body(bcx: block,
// malloc_raw_dyn: allocates a box to contain a given type, but with a
// potentially dynamic size.
fn malloc_raw_dyn(bcx: block, t: ty::t, heap: heap,
fn malloc_raw_dyn(bcx: block,
t: ty::t,
heap: heap,
size: ValueRef) -> Result {
let _icx = bcx.insn_ctxt("malloc_raw");
let ccx = bcx.ccx();
let (mk_fn, rtcall) = match heap {
heap_shared => (ty::mk_imm_box, ~"malloc"),
heap_exchange => (ty::mk_imm_uniq, ~"exchange_malloc")
let (mk_fn, langcall) = match heap {
heap_shared => {
(ty::mk_imm_box, bcx.tcx().lang_items.malloc_fn())
}
heap_exchange => {
(ty::mk_imm_uniq, bcx.tcx().lang_items.exchange_malloc_fn())
}
};
// Grab the TypeRef type of box_ptr_ty.
@ -283,8 +289,11 @@ fn malloc_raw_dyn(bcx: block, t: ty::t, heap: heap,
// Allocate space:
let tydesc = PointerCast(bcx, static_ti.tydesc, T_ptr(T_i8()));
let rval = alloca_zeroed(bcx, T_ptr(T_i8()));
let bcx = callee::trans_rtcall(bcx, rtcall, ~[tydesc, size],
expr::SaveIn(rval));
let bcx = callee::trans_rtcall_or_lang_call(
bcx,
langcall,
~[tydesc, size],
expr::SaveIn(rval));
return rslt(bcx, PointerCast(bcx, Load(bcx, rval), llty));
}
@ -2539,92 +2548,6 @@ fn trap(bcx: block) {
}
}
fn push_rtcall(ccx: @crate_ctxt, name: ~str, did: ast::def_id) {
match ccx.rtcalls.find(name) {
Some(existing_did) if did != existing_did => {
ccx.sess.fatal(fmt!("multiple definitions for runtime call %s",
name));
}
Some(_) | None => {
ccx.rtcalls.insert(name, did);
}
}
}
fn gather_local_rtcalls(ccx: @crate_ctxt, crate: @ast::crate) {
visit::visit_crate(*crate, (), visit::mk_simple_visitor(@{
visit_item: |item| match item.node {
ast::item_fn(*) => {
let attr_metas = attr::attr_metas(
attr::find_attrs_by_name(item.attrs, ~"rt"));
for vec::each(attr_metas) |attr_meta| {
match attr::get_meta_item_list(*attr_meta) {
Some(list) => {
let head = vec::head(list);
let name = attr::get_meta_item_name(head);
push_rtcall(ccx, name, {crate: ast::local_crate,
node: item.id});
}
None => ()
}
}
}
_ => ()
},
..*visit::default_simple_visitor()
}));
}
fn gather_external_rtcalls(ccx: @crate_ctxt) {
do cstore::iter_crate_data(ccx.sess.cstore) |_cnum, cmeta| {
let get_crate_data: decoder::GetCrateDataCb = |cnum| {
cstore::get_crate_data(ccx.sess.cstore, cnum)
};
do decoder::each_path(ccx.sess.intr(), cmeta, get_crate_data) |path| {
let pathname = path.path_string;
match path.def_like {
decoder::dl_def(d) => {
match d {
ast::def_fn(did, _) => {
// FIXME (#2861): This should really iterate attributes
// like gather_local_rtcalls, but we'll need to
// export attributes in metadata/encoder before we can do
// that.
let sentinel = ~"rt::rt_";
let slen = str::len(sentinel);
if str::starts_with(pathname, sentinel) {
let name = str::substr(pathname,
slen, str::len(pathname)-slen);
push_rtcall(ccx, name, did);
}
}
_ => ()
}
}
_ => ()
}
true
}
}
}
fn gather_rtcalls(ccx: @crate_ctxt, crate: @ast::crate) {
gather_local_rtcalls(ccx, crate);
gather_external_rtcalls(ccx);
// FIXME (#2861): Check for other rtcalls too, once they are
// supported. Also probably want to check type signature so we don't crash
// in some obscure place in LLVM if the user provides the wrong signature
// for an rtcall.
let expected_rtcalls =
~[~"exchange_free", ~"exchange_malloc", ~"fail_", ~"free", ~"malloc"];
for vec::each(expected_rtcalls) |name| {
if !ccx.rtcalls.contains_key(*name) {
fail fmt!("no definition for runtime call %s", *name);
}
}
}
fn decl_gc_metadata(ccx: @crate_ctxt, llmod_id: ~str) {
if !ccx.sess.opts.gc || !ccx.uses_gc {
return;
@ -2869,9 +2792,7 @@ fn trans_crate(sess: session::Session,
llvm_insn_ctxt: @mut ~[],
llvm_insns: HashMap(),
fn_times: @mut ~[]},
upcalls:
upcall::declare_upcalls(targ_cfg, llmod),
rtcalls: HashMap(),
upcalls: upcall::declare_upcalls(targ_cfg, llmod),
tydesc_type: tydesc_type,
int_type: int_type,
float_type: float_type,
@ -2885,8 +2806,6 @@ fn trans_crate(sess: session::Session,
mut do_not_commit_warning_issued: false
};
gather_rtcalls(ccx, crate);
{
let _icx = ccx.insn_ctxt("data");
trans_constants(ccx, crate);

View File

@ -333,13 +333,6 @@ fn trans_method_call(in_cx: block,
DontAutorefArg)
}
fn trans_rtcall(bcx: block, name: ~str, args: ~[ValueRef], dest: expr::Dest)
-> block
{
let did = bcx.ccx().rtcalls[name];
return trans_rtcall_or_lang_call(bcx, did, args, dest);
}
fn trans_rtcall_or_lang_call(bcx: block, did: ast::def_id, args: ~[ValueRef],
dest: expr::Dest) -> block {
let fty = if did.crate == ast::local_crate {

View File

@ -492,11 +492,13 @@ fn make_opaque_cbox_take_glue(
let sz = Add(bcx, sz, shape::llsize_of(ccx, T_box_header(ccx)));
// Allocate memory, update original ptr, and copy existing data
let malloc = ~"exchange_malloc";
let opaque_tydesc = PointerCast(bcx, tydesc, T_ptr(T_i8()));
let rval = alloca_zeroed(bcx, T_ptr(T_i8()));
let bcx = callee::trans_rtcall(bcx, malloc, ~[opaque_tydesc, sz],
expr::SaveIn(rval));
let bcx = callee::trans_rtcall_or_lang_call(
bcx,
bcx.tcx().lang_items.exchange_malloc_fn(),
~[opaque_tydesc, sz],
expr::SaveIn(rval));
let cbox_out = PointerCast(bcx, Load(bcx, rval), llopaquecboxty);
call_memcpy(bcx, cbox_out, cbox_in, sz);
Store(bcx, cbox_out, cboxptr);

View File

@ -197,7 +197,6 @@ struct crate_ctxt {
maps: astencode::maps,
stats: stats,
upcalls: @upcall::upcalls,
rtcalls: HashMap<~str, ast::def_id>,
tydesc_type: TypeRef,
int_type: TypeRef,
float_type: TypeRef,

View File

@ -368,7 +368,8 @@ fn trans_fail_value(bcx: block, sp_opt: Option<span>, V_fail_str: ValueRef)
let V_str = PointerCast(bcx, V_fail_str, T_ptr(T_i8()));
let V_filename = PointerCast(bcx, V_filename, T_ptr(T_i8()));
let args = ~[V_str, V_filename, C_int(ccx, V_line)];
let bcx = callee::trans_rtcall(bcx, ~"fail_", args, expr::Ignore);
let bcx = callee::trans_rtcall_or_lang_call(
bcx, bcx.tcx().lang_items.fail_fn(), args, expr::Ignore);
Unreachable(bcx);
return bcx;
}
@ -384,8 +385,8 @@ fn trans_fail_bounds_check(bcx: block, sp: span,
let filename = PointerCast(bcx, filename_cstr, T_ptr(T_i8()));
let args = ~[filename, line, index, len];
let bcx = callee::trans_rtcall(bcx, ~"fail_bounds_check", args,
expr::Ignore);
let bcx = callee::trans_rtcall_or_lang_call(
bcx, bcx.tcx().lang_items.fail_bounds_check_fn(), args, expr::Ignore);
Unreachable(bcx);
return bcx;
}

View File

@ -28,14 +28,19 @@ use core::str;
fn trans_free(cx: block, v: ValueRef) -> block {
let _icx = cx.insn_ctxt("trans_free");
callee::trans_rtcall(cx, ~"free", ~[PointerCast(cx, v, T_ptr(T_i8()))],
expr::Ignore)
callee::trans_rtcall_or_lang_call(
cx,
cx.tcx().lang_items.free_fn(),
~[PointerCast(cx, v, T_ptr(T_i8()))],
expr::Ignore)
}
fn trans_unique_free(cx: block, v: ValueRef) -> block {
let _icx = cx.insn_ctxt("trans_unique_free");
callee::trans_rtcall(
cx, ~"exchange_free", ~[PointerCast(cx, v, T_ptr(T_i8()))],
callee::trans_rtcall_or_lang_call(
cx,
cx.tcx().lang_items.exchange_free_fn(),
~[PointerCast(cx, v, T_ptr(T_i8()))],
expr::Ignore)
}