Move fail upcall into rust libcore.
This commit is contained in:
parent
019a41bdb0
commit
de82a9be61
@ -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
27
src/libcore/rt.rs
Normal 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:
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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"]
|
||||
|
@ -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;
|
||||
}
|
@ -1,6 +1,3 @@
|
||||
#[no_core];
|
||||
|
||||
|
||||
#[path = "module-polymorphism2-files"]
|
||||
mod mystd {
|
||||
|
||||
|
@ -1,5 +1,3 @@
|
||||
#[no_core];
|
||||
|
||||
// Use one template module to specify in a single file the implementation
|
||||
// of functions for multiple types
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user