@@ -118,6 +118,7 @@ state type crate_ctxt = rec(session::session sess,
118118 hashmap[ ast:: def_id,
119119 @ast:: native_item] native_items ,
120120 hashmap[ ast:: def_id, str] item_symbols ,
121+ mutable option:: t[ ValueRef ] main_fn ,
121122 // TODO: hashmap[tup(tag_id,subtys), @tag_info]
122123 hashmap[ ty:: t, uint] tag_sizes ,
123124 hashmap[ ast:: def_id, ValueRef ] discrims ,
@@ -308,19 +309,10 @@ tag block_parent {
308309state type result = rec ( @block_ctxt bcx,
309310 ValueRef val) ;
310311
311- fn sep ( ) -> str {
312- ret "_" ;
313- }
314-
315312fn extend_path ( @local_ctxt cx , & str name ) -> @local_ctxt {
316313 ret @rec( path = cx. path + [ name] with * cx) ;
317314}
318315
319- fn path_name ( & vec[ str] path ) -> str {
320- ret str:: connect ( path, sep ( ) ) ;
321- }
322-
323-
324316fn get_type_sha1 ( & @crate_ctxt ccx , & ty:: t t) -> str {
325317 auto hash = "" ;
326318 alt ( ccx. type_sha1s . find ( t) ) {
@@ -336,15 +328,31 @@ fn get_type_sha1(&@crate_ctxt ccx, &ty::t t) -> str {
336328
337329 ccx. sha . input_str ( metadata:: Encode :: ty_str ( cx, t) ) ;
338330 hash = str:: substr ( ccx. sha . result_str ( ) , 0 u, 16 u) ;
331+ // Prefix with _ so that it never blends into adjacent digits
332+ hash = "_" + hash;
339333 ccx. type_sha1s . insert ( t, hash) ;
340334 }
341335 }
342336 ret hash;
343337}
344338
339+ fn mangle ( & vec[ str] ss ) -> str {
340+
341+ // Follow C++ namespace-mangling style
342+
343+ auto n = "_ZN" ; // Begin name-sequence.
344+
345+ for ( str s in ss) {
346+ n += #fmt ( "%u%s" , str:: byte_len ( s) , s) ;
347+ }
348+
349+ n += "E" ; // End name-sequence.
350+ ret n;
351+ }
352+
345353fn mangle_name_by_type ( & @crate_ctxt ccx , & vec[ str] path , & ty:: t t) -> str {
346354 auto hash = get_type_sha1 ( ccx, t) ;
347- ret sep ( ) + "rust" + sep ( ) + hash + sep ( ) + path_name ( path ) ;
355+ ret mangle ( path + [ hash] ) ;
348356}
349357
350358fn mangle_name_by_type_only ( & @crate_ctxt ccx , & ty:: t t, & str name ) -> str {
@@ -353,14 +361,20 @@ fn mangle_name_by_type_only(&@crate_ctxt ccx, &ty::t t, &str name) -> str {
353361 auto s = ty:: ty_to_short_str ( ccx. tcx , t) ;
354362
355363 auto hash = get_type_sha1 ( ccx, t) ;
356- ret sep( ) + "rust" + sep ( ) + hash + sep ( ) + name + "_" + s;
364+ ret mangle( [ name, s, hash] ) ;
365+ }
366+
367+ fn mangle_name_by_path_and_seq ( & @crate_ctxt ccx , & vec[ str] path ,
368+ & str flav ) -> str {
369+ ret mangle ( path + [ ccx. names . next ( flav) ] ) ;
370+ }
371+
372+ fn mangle_name_by_path ( & @crate_ctxt ccx , & vec[ str] path ) -> str {
373+ ret mangle ( path) ;
357374}
358375
359- fn mangle_name_by_seq ( & @crate_ctxt ccx , & vec[ str] path ,
360- & str flav ) -> str {
361- ret sep ( ) + "rust" + sep ( )
362- + ccx. names . next ( flav) + sep ( )
363- + path_name ( path) ;
376+ fn mangle_name_by_seq ( & @crate_ctxt ccx , & str flav ) -> str {
377+ ret ccx. names . next ( flav) ;
364378}
365379
366380fn res ( @block_ctxt bcx , ValueRef val) -> result {
@@ -1903,7 +1917,7 @@ fn declare_tydesc(&@local_ctxt cx, &span sp, &ty::t t,
19031917 name = mangle_name_by_type_only( cx. ccx, t, "tydesc" ) ;
19041918 name = sanitize( name) ;
19051919 } else {
1906- name = mangle_name_by_seq( cx. ccx, cx . path , "tydesc" ) ;
1920+ name = mangle_name_by_seq( cx. ccx, "tydesc" ) ;
19071921 }
19081922
19091923 auto gvar = llvm:: LLVMAddGlobal ( ccx. llmod, T_tydesc ( ccx. tn) ,
@@ -1937,7 +1951,7 @@ fn declare_generic_glue(&@local_ctxt cx,
19371951 fn_nm = mangle_name_by_type_only( cx. ccx, t, "glue_" + name) ;
19381952 fn_nm = sanitize( fn_nm) ;
19391953 } else {
1940- fn_nm = mangle_name_by_seq( cx. ccx, cx . path , "glue_" + name) ;
1954+ fn_nm = mangle_name_by_seq( cx. ccx, "glue_" + name) ;
19411955 }
19421956 auto llfn = decl_fastcall_fn( cx. ccx. llmod, fn_nm, llfnty) ;
19431957 set_glue_inlining( cx, llfn, t) ;
@@ -4093,7 +4107,7 @@ fn trans_for_each(&@block_ctxt cx,
40934107
40944108 // Step 2: Declare foreach body function.
40954109
4096- let str s = mangle_name_by_seq ( lcx. ccx, lcx. path, "foreach" ) ;
4110+ let str s = mangle_name_by_path_and_seq ( lcx. ccx, lcx. path, "foreach" ) ;
40974111
40984112 // The 'env' arg entering the body function is a fake env member (as in
40994113 // the env-part of the normal rust calling convention) that actually
@@ -4792,7 +4806,7 @@ fn trans_bind_thunk(&@local_ctxt cx,
47924806 // Construct a thunk-call with signature incoming_fty, and that copies
47934807 // args forward into a call to outgoing_fty:
47944808
4795- let str s = mangle_name_by_seq ( cx. ccx , cx. path , "thunk" ) ;
4809+ let str s = mangle_name_by_path_and_seq ( cx. ccx , cx. path , "thunk" ) ;
47964810 let TypeRef llthunk_ty = get_pair_fn_ty ( type_of ( cx. ccx , sp,
47974811 incoming_fty) ) ;
47984812 let ValueRef llthunk = decl_internal_fastcall_fn ( cx. ccx . llmod ,
@@ -6225,9 +6239,10 @@ fn mk_spawn_wrapper(&@block_ctxt cx,
62256239 0 u) ;
62266240
62276241 // TODO: construct a name based on tname
6228- let str wrap_name = mangle_name_by_seq ( cx. fcx . lcx . ccx ,
6229- [ "" ] ,
6230- "spawn_wrapper" ) ;
6242+ let str wrap_name =
6243+ mangle_name_by_path_and_seq ( cx. fcx . lcx . ccx ,
6244+ cx. fcx . lcx . path ,
6245+ "spawn_wrapper" ) ;
62316246 auto llfndecl = decl_fastcall_fn ( llmod, wrap_name,
62326247 wrapper_fn_type) ;
62336248
@@ -7078,8 +7093,9 @@ fn create_vtbl(@local_ctxt cx,
70787093 }
70797094 }
70807095
7081- let @local_ctxt mcx = extend_path( cx, m. node. ident) ;
7082- let str s = mangle_name_by_seq( mcx. ccx, mcx. path, "method" ) ;
7096+ let @local_ctxt mcx = @rec( path = cx. path + [ "method" ,
7097+ m. node. ident] with * cx) ;
7098+ let str s = mangle_name_by_path( mcx. ccx, mcx. path) ;
70837099 let ValueRef llfn = decl_internal_fastcall_fn( cx. ccx. llmod, s,
70847100 llfnty) ;
70857101 cx. ccx. item_ids. insert( m. node. id, llfn) ;
@@ -7091,7 +7107,7 @@ fn create_vtbl(@local_ctxt cx,
70917107 methods += [ llfn] ;
70927108 }
70937109 auto vtbl = C_struct ( methods) ;
7094- auto vtbl_name = mangle_name_by_seq ( cx. ccx, cx. path, "vtbl" ) ;
7110+ auto vtbl_name = mangle_name_by_path ( cx. ccx, cx. path + [ "vtbl" ] ) ;
70957111 auto gvar = llvm:: LLVMAddGlobal ( cx. ccx. llmod, val_ty( vtbl) ,
70967112 str:: buf( vtbl_name) ) ;
70977113 llvm:: LLVMSetInitializer ( gvar, vtbl) ;
@@ -7108,13 +7124,12 @@ fn trans_dtor(@local_ctxt cx,
71087124 & @ast:: method dtor) -> ValueRef {
71097125
71107126 auto llfnty = T_dtor ( cx. ccx, dtor. span, llself_ty) ;
7111- let @local_ctxt dcx = extend_path( cx, "drop") ;
7112- let str s = mangle_name_by_seq( dcx. ccx, dcx. path, "drop") ;
7127+ let str s = mangle_name_by_path( cx. ccx, cx. path + [ "drop"] ) ;
71137128 let ValueRef llfn = decl_internal_fastcall_fn( cx. ccx. llmod, s, llfnty) ;
71147129 cx. ccx. item_ids. insert( dtor. node. id, llfn) ;
71157130 cx. ccx. item_symbols. insert( dtor. node. id, s) ;
71167131
7117- trans_fn( dcx , dtor. span, dtor. node. meth, dtor. node. id,
7132+ trans_fn( cx , dtor. span, dtor. node. meth, dtor. node. id,
71187133 some[ ty_self_pair] ( tup( llself_ty, self_ty) ) ,
71197134 ty_params, dtor. node. ann) ;
71207135
@@ -7503,13 +7518,22 @@ fn decl_fn_and_pair(&@crate_ctxt ccx, &span sp,
75037518 }
75047519
75057520 // Declare the function itself.
7506- let str s = mangle_name_by_seq ( ccx, path, flav ) ;
7521+ let str s = mangle_name_by_path ( ccx, path) ;
75077522 let ValueRef llfn = decl_internal_fastcall_fn( ccx. llmod, s, llfty) ;
75087523
75097524 // Declare the global constant pair that points to it.
75107525 let str ps = mangle_name_by_type( ccx, path, node_ann_type( ccx, ann) ) ;
75117526
75127527 register_fn_pair( ccx, ps, llpairty, llfn, id) ;
7528+
7529+ if ( str:: eq( vec:: top( path) , "main" ) &&
7530+ !ccx. sess. get_opts( ) . shared) {
7531+ if ( ccx. main_fn != none[ ValueRef ] ) {
7532+ ccx. sess. span_err( sp, "multiple 'main' functions" ) ;
7533+ }
7534+ log #fmt( "registering %s as main function for crate" , ps) ;
7535+ ccx. main_fn = some( llfn) ;
7536+ }
75137537}
75147538
75157539fn register_fn_pair( & @crate_ctxt cx, str ps, TypeRef llpairty, ValueRef llfn,
@@ -7569,7 +7593,7 @@ fn decl_native_fn_and_pair(&@crate_ctxt ccx,
75697593 // Declare the wrapper.
75707594 auto t = node_ann_type( ccx, ann) ;
75717595 auto wrapper_type = native_fn_wrapper_type( ccx, sp, num_ty_param, t) ;
7572- let str s = mangle_name_by_seq ( ccx, path, "wrapper" ) ;
7596+ let str s = mangle_name_by_path ( ccx, path) ;
75737597 let ValueRef wrapper_fn = decl_internal_fastcall_fn( ccx. llmod, s,
75747598 wrapper_type) ;
75757599
@@ -7912,9 +7936,8 @@ fn trans_constant(&@crate_ctxt ccx, @walk_ctxt wcx, &@ast::item it) {
79127936
79137937 auto discrim_val = C_int ( i as int ) ;
79147938
7915- auto s = mangle_name_by_seq ( ccx, wcx. path ,
7916- #fmt ( "_rust_tag_discrim_%s_%u" ,
7917- ident, i) ) ;
7939+ auto p = wcx. path + [ ident, variant. node . name , "discrim" ] ;
7940+ auto s = mangle_name_by_type ( ccx, p, ty:: mk_int ( ccx. tcx ) ) ;
79187941 auto discrim_gvar = llvm:: LLVMAddGlobal ( ccx. llmod , T_int ( ) ,
79197942 str:: buf ( s) ) ;
79207943
@@ -7973,29 +7996,6 @@ fn create_typedefs(&@crate_ctxt cx) {
79737996 llvm:: LLVMAddTypeName ( cx. llmod , str:: buf ( "tydesc" ) , T_tydesc ( cx. tn ) ) ;
79747997}
79757998
7976- fn find_main_fn ( & @crate_ctxt cx ) -> ValueRef {
7977- auto e = sep ( ) + "main" ;
7978- let ValueRef v = C_nil ( ) ;
7979- let uint n = 0 u;
7980- for each ( @tup( ast:: def_id, str) i in cx. item_symbols . items ( ) ) {
7981- if ( str:: ends_with ( i. _1 , e) ) {
7982- n += 1 u;
7983- v = cx. item_ids . get ( i. _0 ) ;
7984- }
7985- }
7986- alt ( n) {
7987- case ( 0 u) {
7988- cx. sess . err ( "main fn not found" ) ;
7989- }
7990- case ( 1 u) {
7991- ret v;
7992- }
7993- case ( _) {
7994- cx. sess . err ( "multiple main fns found" ) ;
7995- }
7996- }
7997- }
7998-
79997999fn trans_main_fn ( @local_ctxt cx , ValueRef crate_map ) {
80008000 auto T_main_args = [ T_int ( ) , T_int ( ) ] ;
80018001 auto T_rust_start_args = [ T_int ( ) , T_int ( ) , T_int ( ) , T_int ( ) ] ;
@@ -8015,7 +8015,14 @@ fn trans_main_fn(@local_ctxt cx, ValueRef crate_map) {
80158015
80168016 auto llargc = llvm:: LLVMGetParam ( llmain, 0 u) ;
80178017 auto llargv = llvm:: LLVMGetParam ( llmain, 1 u) ;
8018- auto llrust_main = find_main_fn ( cx. ccx ) ;
8018+ auto llrust_main = alt ( cx. ccx . main_fn ) {
8019+ case ( none) {
8020+ cx. ccx . sess . err ( "missing 'main' function" ) ;
8021+ // FIXME: shouldn't sess.err's ! result unify with f?
8022+ C_nil ( )
8023+ }
8024+ case ( some ( ?f) ) { f }
8025+ } ;
80198026
80208027 //
80218028 // Emit the moral equivalent of:
@@ -8283,6 +8290,7 @@ fn trans_crate(&session::session sess, &@ast::crate crate,
82838290 items = new_def_hash[ @ast:: item] ( ) ,
82848291 native_items = new_def_hash[ @ast:: native_item] ( ) ,
82858292 item_symbols = new_def_hash[ str] ( ) ,
8293+ mutable main_fn = none[ ValueRef ] ,
82868294 tag_sizes = tag_sizes,
82878295 discrims = new_def_hash[ ValueRef ] ( ) ,
82888296 discrim_symbols = new_def_hash[ str] ( ) ,
0 commit comments