@@ -37,7 +37,7 @@ import link::{mangle_internal_name_by_type_only,
37
37
mangle_internal_name_by_path,
38
38
mangle_internal_name_by_path_and_seq,
39
39
mangle_exported_name} ;
40
- import metadata:: { csearch, cstore, encoder} ;
40
+ import metadata:: { csearch, cstore, decoder , encoder} ;
41
41
import metadata:: common:: link_meta;
42
42
import util:: ppaux;
43
43
import util:: ppaux:: { ty_to_str, ty_to_short_str} ;
@@ -3942,11 +3942,25 @@ fn trans_fail_value(bcx: block, sp_opt: option<span>,
3942
3942
let V_str = PointerCast(bcx, V_fail_str, T_ptr(T_i8()));
3943
3943
let V_filename = PointerCast(bcx, V_filename, T_ptr(T_i8()));
3944
3944
let args = ~[V_str, V_filename, C_int(ccx, V_line)];
3945
- let bcx = invoke (bcx, bcx.ccx().upcalls._fail , args);
3945
+ let bcx = trans_rtcall (bcx, ~" fail" , args) ;
3946
3946
Unreachable ( bcx) ;
3947
3947
ret bcx;
3948
3948
}
3949
3949
3950
+ fn trans_rtcall ( bcx : block , name : ~str , args : ~[ ValueRef ] ) -> block {
3951
+ let did = bcx. ccx ( ) . rtcalls [ name] ;
3952
+ let fty = if did. crate == ast:: local_crate {
3953
+ ty:: node_id_to_type ( bcx. ccx ( ) . tcx , did. node )
3954
+ } else {
3955
+ csearch:: get_type ( bcx. ccx ( ) . tcx , did) . ty
3956
+ } ;
3957
+ let rty = ty:: ty_fn_ret ( fty) ;
3958
+ ret trans_call_inner (
3959
+ bcx, none, fty, rty,
3960
+ |bcx| lval_static_fn_inner ( bcx, did, 0 , ~[ ] , none) ,
3961
+ arg_vals ( args) , ignore) ;
3962
+ }
3963
+
3950
3964
fn trans_break_cont ( bcx : block , to_end : bool )
3951
3965
-> block {
3952
3966
let _icx = bcx. insn_ctxt ( ~"trans_break_cont") ;
@@ -5314,6 +5328,79 @@ fn trap(bcx: block) {
5314
5328
}
5315
5329
}
5316
5330
5331
+ fn push_rtcall ( ccx : @crate_ctxt , name : ~str , did : ast:: def_id ) {
5332
+ if ccx. rtcalls . contains_key ( name) {
5333
+ fail #fmt( "multiple definitions for runtime call %s" , name) ;
5334
+ }
5335
+ ccx. rtcalls . insert ( name, did) ;
5336
+ }
5337
+
5338
+ fn gather_local_rtcalls ( ccx : @crate_ctxt , crate : @ast:: crate ) {
5339
+ visit:: visit_crate ( * crate , ( ) , visit:: mk_simple_visitor ( @{
5340
+ visit_item: |item| alt item. node {
5341
+ ast:: item_fn ( decl, _, _) {
5342
+ let attr_metas = attr:: attr_metas (
5343
+ attr:: find_attrs_by_name ( item. attrs , ~"rt") ) ;
5344
+ do vec:: iter ( attr_metas) |attr_meta| {
5345
+ alt attr:: get_meta_item_list ( attr_meta) {
5346
+ some ( list) {
5347
+ let name = * attr:: get_meta_item_name ( vec:: head ( list) ) ;
5348
+ push_rtcall ( ccx, name, { crate : ast:: local_crate,
5349
+ node: item. id } ) ;
5350
+ }
5351
+ none { }
5352
+ }
5353
+ }
5354
+ }
5355
+ _ { }
5356
+ }
5357
+ with * visit:: default_simple_visitor ( )
5358
+ } ) ) ;
5359
+ }
5360
+
5361
+ fn gather_external_rtcalls ( ccx : @crate_ctxt ) {
5362
+ do cstore:: iter_crate_data ( ccx. sess . cstore ) |_cnum, cmeta| {
5363
+ do decoder:: each_path ( cmeta) |path| {
5364
+ let pathname = path. path_string ;
5365
+ alt path. def_like {
5366
+ decoder:: dl_def ( d) {
5367
+ alt d {
5368
+ ast : : def_fn ( did, _) {
5369
+ // FIXME (#2861): This should really iterate attributes
5370
+ // like gather_local_rtcalls, but we'll need to
5371
+ // export attributes in metadata/encoder before we can do
5372
+ // that.
5373
+ let sentinel = "rt::rt_" ;
5374
+ let slen = str:: len ( sentinel) ;
5375
+ if str:: starts_with ( pathname, sentinel) {
5376
+ let name = str:: substr ( pathname,
5377
+ slen, str:: len ( pathname) -slen) ;
5378
+ push_rtcall ( ccx, name, did) ;
5379
+ }
5380
+ }
5381
+ _ { }
5382
+ }
5383
+ }
5384
+ _ { }
5385
+ }
5386
+ true
5387
+ }
5388
+ }
5389
+ }
5390
+
5391
+ fn gather_rtcalls( ccx: @crate_ctxt, crate : @ast:: crate) {
5392
+ gather_local_rtcalls ( ccx, crate ) ;
5393
+ gather_external_rtcalls ( ccx) ;
5394
+
5395
+ // FIXME (#2861): Check for other rtcalls too, once they are
5396
+ // supported. Also probably want to check type signature so we don't crash
5397
+ // in some obscure place in LLVM if the user provides the wrong signature
5398
+ // for an rtcall.
5399
+ if !ccx. rtcalls . contains_key ( ~"fail") {
5400
+ fail ~"no definition for runtime call fail";
5401
+ }
5402
+ }
5403
+
5317
5404
fn create_module_map ( ccx : @crate_ctxt ) -> ValueRef {
5318
5405
let elttype = T_struct ( ~[ ccx. int_type , ccx. int_type ] ) ;
5319
5406
let maptype = T_array ( elttype, ccx. module_data . size ( ) + 1 u) ;
@@ -5544,6 +5631,7 @@ fn trans_crate(sess: session::session, crate: @ast::crate, tcx: ty::ctxt,
5544
5631
upcalls:
5545
5632
upcall:: declare_upcalls ( targ_cfg, tn, tydesc_type,
5546
5633
llmod) ,
5634
+ rtcalls: str_hash :: < ast:: def_id > ( ) ,
5547
5635
tydesc_type: tydesc_type,
5548
5636
int_type: int_type,
5549
5637
float_type: float_type,
@@ -5557,6 +5645,8 @@ fn trans_crate(sess: session::session, crate: @ast::crate, tcx: ty::ctxt,
5557
5645
mut do_not_commit_warning_issued: false } ;
5558
5646
5559
5647
5648
+ gather_rtcalls ( ccx, crate ) ;
5649
+
5560
5650
{
5561
5651
let _icx = ccx. insn_ctxt ( ~"data") ;
5562
5652
trans_constants ( ccx, crate ) ;
0 commit comments