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 libc, os, io, run, rand, sys, unsafe, logging;
|
||||||
export arc, comm, task, future, pipes;
|
export arc, comm, task, future, pipes;
|
||||||
export extfmt;
|
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 tuple;
|
||||||
export to_str, to_bytes;
|
export to_str, to_bytes;
|
||||||
export dvec, dvec_iter;
|
export dvec, dvec_iter;
|
||||||
|
@ -206,6 +210,9 @@ mod unsafe;
|
||||||
// Exported but not part of the public interface
|
// Exported but not part of the public interface
|
||||||
|
|
||||||
mod extfmt;
|
mod extfmt;
|
||||||
|
// The test harness links against core, so don't include runtime in tests.
|
||||||
|
#[cfg(notest)]
|
||||||
|
mod rt;
|
||||||
|
|
||||||
|
|
||||||
// For internal use, not exported
|
// For internal use, not exported
|
||||||
|
|
|
@ -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);
|
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 {
|
struct s_trace_args {
|
||||||
rust_task *task;
|
rust_task *task;
|
||||||
char const *msg;
|
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
|
// If the user wants a test runner, then add the test cfg
|
||||||
let gen_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")]
|
~[attr::mk_word_item(@~"test")]
|
||||||
} else { ~[] }
|
} else {
|
||||||
|
~[attr::mk_word_item(@~"notest")]
|
||||||
|
}
|
||||||
};
|
};
|
||||||
ret vec::append(vec::append(user_cfg, gen_cfg), default_cfg);
|
ret vec::append(vec::append(user_cfg, gen_cfg), default_cfg);
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,7 @@ import link::{mangle_internal_name_by_type_only,
|
||||||
mangle_internal_name_by_path,
|
mangle_internal_name_by_path,
|
||||||
mangle_internal_name_by_path_and_seq,
|
mangle_internal_name_by_path_and_seq,
|
||||||
mangle_exported_name};
|
mangle_exported_name};
|
||||||
import metadata::{csearch, cstore, encoder};
|
import metadata::{csearch, cstore, decoder, encoder};
|
||||||
import metadata::common::link_meta;
|
import metadata::common::link_meta;
|
||||||
import util::ppaux;
|
import util::ppaux;
|
||||||
import util::ppaux::{ty_to_str, ty_to_short_str};
|
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_str = PointerCast(bcx, V_fail_str, T_ptr(T_i8()));
|
||||||
let V_filename = PointerCast(bcx, V_filename, 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 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);
|
Unreachable(bcx);
|
||||||
ret 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)
|
fn trans_break_cont(bcx: block, to_end: bool)
|
||||||
-> block {
|
-> block {
|
||||||
let _icx = bcx.insn_ctxt(~"trans_break_cont");
|
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 {
|
fn create_module_map(ccx: @crate_ctxt) -> ValueRef {
|
||||||
let elttype = T_struct(~[ccx.int_type, ccx.int_type]);
|
let elttype = T_struct(~[ccx.int_type, ccx.int_type]);
|
||||||
let maptype = T_array(elttype, ccx.module_data.size() + 1u);
|
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:
|
upcalls:
|
||||||
upcall::declare_upcalls(targ_cfg, tn, tydesc_type,
|
upcall::declare_upcalls(targ_cfg, tn, tydesc_type,
|
||||||
llmod),
|
llmod),
|
||||||
|
rtcalls: str_hash::<ast::def_id>(),
|
||||||
tydesc_type: tydesc_type,
|
tydesc_type: tydesc_type,
|
||||||
int_type: int_type,
|
int_type: int_type,
|
||||||
float_type: float_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};
|
mut do_not_commit_warning_issued: false};
|
||||||
|
|
||||||
|
|
||||||
|
gather_rtcalls(ccx, crate);
|
||||||
|
|
||||||
{
|
{
|
||||||
let _icx = ccx.insn_ctxt(~"data");
|
let _icx = ccx.insn_ctxt(~"data");
|
||||||
trans_constants(ccx, crate);
|
trans_constants(ccx, crate);
|
||||||
|
|
|
@ -118,6 +118,7 @@ type crate_ctxt = {
|
||||||
maps: astencode::maps,
|
maps: astencode::maps,
|
||||||
stats: stats,
|
stats: stats,
|
||||||
upcalls: @upcall::upcalls,
|
upcalls: @upcall::upcalls,
|
||||||
|
rtcalls: hashmap<~str, ast::def_id>,
|
||||||
tydesc_type: TypeRef,
|
tydesc_type: TypeRef,
|
||||||
int_type: TypeRef,
|
int_type: TypeRef,
|
||||||
float_type: TypeRef,
|
float_type: TypeRef,
|
||||||
|
|
|
@ -1,8 +1,5 @@
|
||||||
#[no_core];
|
|
||||||
|
|
||||||
|
|
||||||
#[path = "module-polymorphism-files"]
|
#[path = "module-polymorphism-files"]
|
||||||
mod float {
|
mod my_float {
|
||||||
|
|
||||||
// The type of the float
|
// The type of the float
|
||||||
import inst::T;
|
import inst::T;
|
||||||
|
@ -18,7 +15,7 @@ mod float {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[path = "module-polymorphism-files"]
|
#[path = "module-polymorphism-files"]
|
||||||
mod f64 {
|
mod my_f64 {
|
||||||
|
|
||||||
import inst::T;
|
import inst::T;
|
||||||
|
|
||||||
|
@ -33,7 +30,7 @@ mod f64 {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[path = "module-polymorphism-files"]
|
#[path = "module-polymorphism-files"]
|
||||||
mod f32 {
|
mod my_f32 {
|
||||||
import inst::T;
|
import inst::T;
|
||||||
|
|
||||||
#[path = "inst_f32.rs"]
|
#[path = "inst_f32.rs"]
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
fn main() {
|
fn main() {
|
||||||
// All of these functions are defined by a single module
|
// All of these functions are defined by a single module
|
||||||
// source file but instantiated for different types
|
// source file but instantiated for different types
|
||||||
assert float::template::plus(1.0f, 2.0f) == 3.0f;
|
assert my_float::template::plus(1.0f, 2.0f) == 3.0f;
|
||||||
assert f64::template::plus(1.0f64, 2.0f64) == 3.0f64;
|
assert my_f64::template::plus(1.0f64, 2.0f64) == 3.0f64;
|
||||||
assert f32::template::plus(1.0f32, 2.0f32) == 3.0f32;
|
assert my_f32::template::plus(1.0f32, 2.0f32) == 3.0f32;
|
||||||
}
|
}
|
|
@ -1,6 +1,3 @@
|
||||||
#[no_core];
|
|
||||||
|
|
||||||
|
|
||||||
#[path = "module-polymorphism2-files"]
|
#[path = "module-polymorphism2-files"]
|
||||||
mod mystd {
|
mod mystd {
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
#[no_core];
|
|
||||||
|
|
||||||
// Use one template module to specify in a single file the implementation
|
// Use one template module to specify in a single file the implementation
|
||||||
// of functions for multiple types
|
// of functions for multiple types
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue