Skip to content

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

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 7, 2013
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions src/libcore/rt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand All @@ -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);
}
Expand All @@ -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);
}
Expand All @@ -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);
}
Expand Down
94 changes: 65 additions & 29 deletions src/librustc/middle/lang_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,43 +34,49 @@ use std::map::HashMap;
use str_eq = str::eq;

pub enum LangItem {
ConstTraitLangItem, // 0
CopyTraitLangItem, // 1
OwnedTraitLangItem, // 2
DurableTraitLangItem, // 3

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

EqTraitLangItem, // 17
OrdTraitLangItem, // 18

StrEqFnLangItem, // 19
UniqStrEqFnLangItem, // 20
AnnihilateFnLangItem, // 21
LogTypeFnLangItem, // 22
ConstTraitLangItem, // 0
CopyTraitLangItem, // 1
OwnedTraitLangItem, // 2
DurableTraitLangItem, // 3

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

EqTraitLangItem, // 17
OrdTraitLangItem, // 18

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

Expand Down Expand Up @@ -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",

_ => "???"
}
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down
113 changes: 16 additions & 97 deletions src/librustc/middle/trans/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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));
}

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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,
Expand All @@ -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);
Expand Down
7 changes: 0 additions & 7 deletions src/librustc/middle/trans/callee.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
8 changes: 5 additions & 3 deletions src/librustc/middle/trans/closure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
1 change: 0 additions & 1 deletion src/librustc/middle/trans/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
7 changes: 4 additions & 3 deletions src/librustc/middle/trans/controlflow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand All @@ -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;
}
Expand Down
Loading