librustc: Fold rt items into lang items. Shaves another 10% or so off hello world compile time.
This commit is contained in:
parent
d2d1d98968
commit
9f387926fc
@ -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);
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user