Move fail upcall into rust libcore.

This commit is contained in:
Elliott Slaughter 2012-07-10 15:52:05 -07:00
parent 019a41bdb0
commit de82a9be61
10 changed files with 147 additions and 19 deletions

View File

@ -41,6 +41,10 @@ export either, option, result, iter;
export libc, os, io, run, rand, sys, unsafe, logging;
export arc, comm, task, future, pipes;
export extfmt;
// The test harness links against core, so don't include runtime in tests.
// FIXME (#2861): Uncomment this after snapshot gets updated.
//#[cfg(notest)]
export rt;
export tuple;
export to_str, to_bytes;
export dvec, dvec_iter;
@ -206,6 +210,9 @@ mod unsafe;
// Exported but not part of the public interface
mod extfmt;
// The test harness links against core, so don't include runtime in tests.
#[cfg(notest)]
mod rt;
// For internal use, not exported

27
src/libcore/rt.rs Normal file
View File

@ -0,0 +1,27 @@
//! Runtime calls emitted by the compiler.
import libc::c_char;
import libc::size_t;
type rust_task = libc::c_void;
extern mod rustrt {
#[rust_stack]
fn rust_upcall_fail(expr: *c_char, file: *c_char, line: size_t);
}
// 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)]
fn rt_fail(expr: *c_char, file: *c_char, line: size_t) {
rustrt::rust_upcall_fail(expr, file, line);
}
// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:

View File

@ -98,6 +98,16 @@ upcall_fail(char const *expr,
UPCALL_SWITCH_STACK(task, &args, upcall_s_fail);
}
// FIXME (#2861): Alias used by libcore/rt.rs to avoid naming conflicts with
// autogenerated wrappers for upcall_fail. Remove this when we fully move away
// away from the C upcall path.
extern "C" CDECL void
rust_upcall_fail(char const *expr,
char const *file,
size_t line) {
upcall_fail(expr, file, line);
}
struct s_trace_args {
rust_task *task;
char const *msg;

View File

@ -69,10 +69,11 @@ fn build_configuration(sess: session, argv0: ~str, input: input) ->
// If the user wants a test runner, then add the test cfg
let gen_cfg =
{
if sess.opts.test && !attr::contains_name(user_cfg, ~"test")
{
if sess.opts.test && !attr::contains_name(user_cfg, ~"test") {
~[attr::mk_word_item(@~"test")]
} else { ~[] }
} else {
~[attr::mk_word_item(@~"notest")]
}
};
ret vec::append(vec::append(user_cfg, gen_cfg), default_cfg);
}

View File

@ -37,7 +37,7 @@
mangle_internal_name_by_path,
mangle_internal_name_by_path_and_seq,
mangle_exported_name};
import metadata::{csearch, cstore, encoder};
import metadata::{csearch, cstore, decoder, encoder};
import metadata::common::link_meta;
import util::ppaux;
import util::ppaux::{ty_to_str, ty_to_short_str};
@ -3942,11 +3942,25 @@ fn trans_fail_value(bcx: block, sp_opt: option<span>,
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 = invoke(bcx, bcx.ccx().upcalls._fail, args);
let bcx = trans_rtcall(bcx, ~"fail", args);
Unreachable(bcx);
ret bcx;
}
fn trans_rtcall(bcx: block, name: ~str, args: ~[ValueRef]) -> block {
let did = bcx.ccx().rtcalls[name];
let fty = if did.crate == ast::local_crate {
ty::node_id_to_type(bcx.ccx().tcx, did.node)
} else {
csearch::get_type(bcx.ccx().tcx, did).ty
};
let rty = ty::ty_fn_ret(fty);
ret trans_call_inner(
bcx, none, fty, rty,
|bcx| lval_static_fn_inner(bcx, did, 0, ~[], none),
arg_vals(args), ignore);
}
fn trans_break_cont(bcx: block, to_end: bool)
-> block {
let _icx = bcx.insn_ctxt(~"trans_break_cont");
@ -5314,6 +5328,79 @@ fn trap(bcx: block) {
}
}
fn push_rtcall(ccx: @crate_ctxt, name: ~str, did: ast::def_id) {
if ccx.rtcalls.contains_key(name) {
fail #fmt("multiple definitions for runtime call %s", name);
}
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| alt item.node {
ast::item_fn(decl, _, _) {
let attr_metas = attr::attr_metas(
attr::find_attrs_by_name(item.attrs, ~"rt"));
do vec::iter(attr_metas) |attr_meta| {
alt attr::get_meta_item_list(attr_meta) {
some(list) {
let name = *attr::get_meta_item_name(vec::head(list));
push_rtcall(ccx, name, {crate: ast::local_crate,
node: item.id});
}
none {}
}
}
}
_ {}
}
with *visit::default_simple_visitor()
}));
}
fn gather_external_rtcalls(ccx: @crate_ctxt) {
do cstore::iter_crate_data(ccx.sess.cstore) |_cnum, cmeta| {
do decoder::each_path(cmeta) |path| {
let pathname = path.path_string;
alt path.def_like {
decoder::dl_def(d) {
alt 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.
if !ccx.rtcalls.contains_key(~"fail") {
fail ~"no definition for runtime call fail";
}
}
fn create_module_map(ccx: @crate_ctxt) -> ValueRef {
let elttype = T_struct(~[ccx.int_type, ccx.int_type]);
let maptype = T_array(elttype, ccx.module_data.size() + 1u);
@ -5544,6 +5631,7 @@ fn trans_crate(sess: session::session, crate: @ast::crate, tcx: ty::ctxt,
upcalls:
upcall::declare_upcalls(targ_cfg, tn, tydesc_type,
llmod),
rtcalls: str_hash::<ast::def_id>(),
tydesc_type: tydesc_type,
int_type: int_type,
float_type: float_type,
@ -5557,6 +5645,8 @@ fn trans_crate(sess: session::session, crate: @ast::crate, tcx: ty::ctxt,
mut do_not_commit_warning_issued: false};
gather_rtcalls(ccx, crate);
{
let _icx = ccx.insn_ctxt(~"data");
trans_constants(ccx, crate);

View File

@ -118,6 +118,7 @@ fn new_namegen() -> namegen {
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

@ -1,8 +1,5 @@
#[no_core];
#[path = "module-polymorphism-files"]
mod float {
mod my_float {
// The type of the float
import inst::T;
@ -18,7 +15,7 @@ mod float {
}
#[path = "module-polymorphism-files"]
mod f64 {
mod my_f64 {
import inst::T;
@ -33,7 +30,7 @@ mod f64 {
}
#[path = "module-polymorphism-files"]
mod f32 {
mod my_f32 {
import inst::T;
#[path = "inst_f32.rs"]

View File

@ -5,7 +5,7 @@
fn main() {
// All of these functions are defined by a single module
// source file but instantiated for different types
assert float::template::plus(1.0f, 2.0f) == 3.0f;
assert f64::template::plus(1.0f64, 2.0f64) == 3.0f64;
assert f32::template::plus(1.0f32, 2.0f32) == 3.0f32;
assert my_float::template::plus(1.0f, 2.0f) == 3.0f;
assert my_f64::template::plus(1.0f64, 2.0f64) == 3.0f64;
assert my_f32::template::plus(1.0f32, 2.0f32) == 3.0f32;
}

View File

@ -1,6 +1,3 @@
#[no_core];
#[path = "module-polymorphism2-files"]
mod mystd {

View File

@ -1,5 +1,3 @@
#[no_core];
// Use one template module to specify in a single file the implementation
// of functions for multiple types