@@ -1594,7 +1594,7 @@ fn declare_tydesc(@crate_ctxt cx, @ty.t t) {
1594
1594
}
1595
1595
1596
1596
auto glue_fn_ty = T_ptr ( T_glue_fn ( cx. tn) ) ;
1597
-
1597
+
1598
1598
auto name = sanitize( cx. names. next( "tydesc_" + ty. ty_to_str( t) ) ) ;
1599
1599
auto gvar = llvm. LLVMAddGlobal ( cx. llmod, T_tydesc ( cx. tn) ,
1600
1600
_str. buf( name) ) ;
@@ -1655,13 +1655,17 @@ fn make_generic_glue(@crate_ctxt cx, @ty.t t, ValueRef llfn,
1655
1655
1656
1656
auto re;
1657
1657
if ( !ty. type_is_scalar( t) ) {
1658
+
1659
+ // Any nontrivial glue is with values passed *by alias*; this is a
1660
+ // requirement since in many contexts glue is invoked indirectly and
1661
+ // the caller has no idea if it's dealing with something that can be
1662
+ // passed by value.
1663
+
1658
1664
auto llty;
1659
1665
if ( ty. type_has_dynamic_size( t) ) {
1660
1666
llty = T_ptr ( T_i8( ) ) ;
1661
- } else if ( ty. type_is_structural( t) ) {
1662
- llty = T_ptr ( type_of( cx, t) ) ;
1663
1667
} else {
1664
- llty = type_of( cx, t) ;
1668
+ llty = T_ptr ( type_of( cx, t) ) ;
1665
1669
}
1666
1670
1667
1671
auto lltyparams = llvm. LLVMGetParam ( llfn, 3 u) ;
@@ -1690,8 +1694,9 @@ fn make_generic_glue(@crate_ctxt cx, @ty.t t, ValueRef llfn,
1690
1694
}
1691
1695
1692
1696
fn make_take_glue( @block_ctxt cx, ValueRef v, @ty. t t) -> result {
1697
+ // NB: v is an *alias* of type t here, not a direct value.
1693
1698
if ( ty. type_is_boxed( t) ) {
1694
- ret incr_refcnt_of_boxed( cx, v ) ;
1699
+ ret incr_refcnt_of_boxed( cx, cx . build . Load ( v ) ) ;
1695
1700
1696
1701
} else if ( ty. type_is_structural( t) ) {
1697
1702
ret iter_structural_ty( cx, v, t,
@@ -1719,9 +1724,11 @@ fn incr_refcnt_of_boxed(@block_ctxt cx, ValueRef box_ptr) -> result {
1719
1724
ret res( next_cx, C_nil ( ) ) ;
1720
1725
}
1721
1726
1722
- fn make_drop_glue( @block_ctxt cx, ValueRef v, @ty. t t) -> result {
1727
+ fn make_drop_glue( @block_ctxt cx, ValueRef v0, @ty. t t) -> result {
1728
+ // NB: v0 is an *alias* of type t here, not a direct value.
1723
1729
alt ( t. struct ) {
1724
1730
case ( ty. ty_str) {
1731
+ auto v = cx. build. Load ( v0) ;
1725
1732
ret decr_refcnt_and_if_zero
1726
1733
( cx, v, bind trans_non_gc_free( _, v) ,
1727
1734
"free string" ,
@@ -1736,6 +1743,7 @@ fn make_drop_glue(@block_ctxt cx, ValueRef v, @ty.t t) -> result {
1736
1743
// FIXME: switch gc/non-gc on layer of the type.
1737
1744
ret trans_non_gc_free( res. bcx, v) ;
1738
1745
}
1746
+ auto v = cx. build. Load ( v0) ;
1739
1747
ret decr_refcnt_and_if_zero( cx, v,
1740
1748
bind hit_zero( _, v, t) ,
1741
1749
"free vector" ,
@@ -1749,11 +1757,12 @@ fn make_drop_glue(@block_ctxt cx, ValueRef v, @ty.t t) -> result {
1749
1757
vec( C_int ( 0 ) ,
1750
1758
C_int ( abi. box_rc_field_body) ) ) ;
1751
1759
1752
- auto body_val = load_scalar_or_boxed ( cx, body, body_ty) ;
1760
+ auto body_val = load_if_immediate ( cx, body, body_ty) ;
1753
1761
auto res = drop_ty( cx, body_val, body_ty) ;
1754
1762
// FIXME: switch gc/non-gc on layer of the type.
1755
1763
ret trans_non_gc_free( res. bcx, v) ;
1756
1764
}
1765
+ auto v = cx. build. Load ( v0) ;
1757
1766
ret decr_refcnt_and_if_zero( cx, v,
1758
1767
bind hit_zero( _, v, body_mt. ty) ,
1759
1768
"free box" ,
@@ -1765,6 +1774,7 @@ fn make_drop_glue(@block_ctxt cx, ValueRef v, @ty.t t) -> result {
1765
1774
ret trans_upcall( cx, "upcall_del_port" ,
1766
1775
vec( vp2i( cx, v) ) ) ;
1767
1776
}
1777
+ auto v = cx. build. Load ( v0) ;
1768
1778
ret decr_refcnt_and_if_zero( cx, v,
1769
1779
bind hit_zero( _, v) ,
1770
1780
"free port" ,
@@ -1776,6 +1786,7 @@ fn make_drop_glue(@block_ctxt cx, ValueRef v, @ty.t t) -> result {
1776
1786
ret trans_upcall( cx, "upcall_del_chan" ,
1777
1787
vec( vp2i( cx, v) ) ) ;
1778
1788
}
1789
+ auto v = cx. build. Load ( v0) ;
1779
1790
ret decr_refcnt_and_if_zero( cx, v,
1780
1791
bind hit_zero( _, v) ,
1781
1792
"free chan" ,
@@ -1804,7 +1815,7 @@ fn make_drop_glue(@block_ctxt cx, ValueRef v, @ty.t t) -> result {
1804
1815
ret trans_non_gc_free( cx, v) ;
1805
1816
}
1806
1817
auto box_cell =
1807
- cx. build. GEP ( v ,
1818
+ cx. build. GEP ( v0 ,
1808
1819
vec( C_int ( 0 ) ,
1809
1820
C_int ( abi. obj_field_box) ) ) ;
1810
1821
@@ -1843,7 +1854,7 @@ fn make_drop_glue(@block_ctxt cx, ValueRef v, @ty.t t) -> result {
1843
1854
ret trans_non_gc_free( cx, v) ;
1844
1855
}
1845
1856
auto box_cell =
1846
- cx. build. GEP ( v ,
1857
+ cx. build. GEP ( v0 ,
1847
1858
vec( C_int ( 0 ) ,
1848
1859
C_int ( abi. fn_field_box) ) ) ;
1849
1860
@@ -1857,7 +1868,7 @@ fn make_drop_glue(@block_ctxt cx, ValueRef v, @ty.t t) -> result {
1857
1868
1858
1869
case ( _) {
1859
1870
if ( ty. type_is_structural( t) ) {
1860
- ret iter_structural_ty( cx, v , t,
1871
+ ret iter_structural_ty( cx, v0 , t,
1861
1872
bind drop_ty( _, _, _) ) ;
1862
1873
1863
1874
} else if ( ty. type_is_scalar( t) ||
@@ -2039,8 +2050,8 @@ fn iter_structural_ty_full(@block_ctxt cx,
2039
2050
r = GEP_tup_like ( r. bcx, t, bv, vec( 0 , i) ) ;
2040
2051
auto elt_b = r. val;
2041
2052
r = f( r. bcx,
2042
- load_scalar_or_boxed ( r. bcx, elt_a, arg. ty) ,
2043
- load_scalar_or_boxed ( r. bcx, elt_b, arg. ty) ,
2053
+ load_if_immediate ( r. bcx, elt_a, arg. ty) ,
2054
+ load_if_immediate ( r. bcx, elt_b, arg. ty) ,
2044
2055
arg. ty) ;
2045
2056
i += 1 ;
2046
2057
}
@@ -2053,8 +2064,8 @@ fn iter_structural_ty_full(@block_ctxt cx,
2053
2064
r = GEP_tup_like ( r. bcx, t, bv, vec( 0 , i) ) ;
2054
2065
auto llfld_b = r. val;
2055
2066
r = f( r. bcx,
2056
- load_scalar_or_boxed ( r. bcx, llfld_a, fld. mt. ty) ,
2057
- load_scalar_or_boxed ( r. bcx, llfld_b, fld. mt. ty) ,
2067
+ load_if_immediate ( r. bcx, llfld_a, fld. mt. ty) ,
2068
+ load_if_immediate ( r. bcx, llfld_b, fld. mt. ty) ,
2058
2069
fld. mt. ty) ;
2059
2070
i += 1 ;
2060
2071
}
@@ -2126,12 +2137,12 @@ fn iter_structural_ty_full(@block_ctxt cx,
2126
2137
ty_params, tps, a. ty) ;
2127
2138
2128
2139
auto llfld_a =
2129
- load_scalar_or_boxed ( variant_cx,
2140
+ load_if_immediate ( variant_cx,
2130
2141
llfldp_a,
2131
2142
ty_subst) ;
2132
2143
2133
2144
auto llfld_b =
2134
- load_scalar_or_boxed ( variant_cx,
2145
+ load_if_immediate ( variant_cx,
2135
2146
llfldp_b,
2136
2147
ty_subst) ;
2137
2148
@@ -2252,7 +2263,7 @@ fn iter_sequence_inner(@block_ctxt cx,
2252
2263
}
2253
2264
2254
2265
auto p = cx. build. PointerCast ( src, llptrty) ;
2255
- ret f( cx, load_scalar_or_boxed ( cx, p, elt_ty) , elt_ty) ;
2266
+ ret f( cx, load_if_immediate ( cx, p, elt_ty) , elt_ty) ;
2256
2267
}
2257
2268
2258
2269
auto elt_sz = size_of( cx, elt_ty) ;
@@ -2333,12 +2344,12 @@ fn call_tydesc_glue_full(@block_ctxt cx, ValueRef v,
2333
2344
2334
2345
fn call_tydesc_glue( @block_ctxt cx, ValueRef v, @ty. t t, int field) {
2335
2346
auto td = get_tydesc( cx, t) ;
2336
- call_tydesc_glue_full( td. bcx, v, td. val, field) ;
2347
+ call_tydesc_glue_full( td. bcx,
2348
+ spill_if_immediate( td. bcx, v, t) ,
2349
+ td. val, field) ;
2337
2350
}
2338
2351
2339
- fn take_ty( @block_ctxt cx,
2340
- ValueRef v,
2341
- @ty. t t) -> result {
2352
+ fn take_ty( @block_ctxt cx, ValueRef v, @ty. t t) -> result {
2342
2353
if ( !ty. type_is_scalar( t) ) {
2343
2354
call_tydesc_glue( cx, v, t, abi. tydesc_field_take_glue) ;
2344
2355
}
@@ -2348,7 +2359,7 @@ fn take_ty(@block_ctxt cx,
2348
2359
fn drop_slot( @block_ctxt cx,
2349
2360
ValueRef slot,
2350
2361
@ty. t t) -> result {
2351
- auto llptr = load_scalar_or_boxed ( cx, slot, t) ;
2362
+ auto llptr = load_if_immediate ( cx, slot, t) ;
2352
2363
auto re = drop_ty( cx, llptr, t) ;
2353
2364
2354
2365
auto llty = val_ty( slot) ;
@@ -2692,8 +2703,8 @@ fn trans_compare(@block_ctxt cx0, ast.binop op, @ty.t t0,
2692
2703
auto av = av0;
2693
2704
auto bv = bv0;
2694
2705
if ( load_inner) {
2695
- av = load_scalar_or_boxed ( cx, av, t) ;
2696
- bv = load_scalar_or_boxed ( cx, bv, t) ;
2706
+ av = load_if_immediate ( cx, av, t) ;
2707
+ bv = load_if_immediate ( cx, bv, t) ;
2697
2708
}
2698
2709
2699
2710
// First 'eq' comparison: if so, continue to next elts.
@@ -2839,7 +2850,7 @@ fn trans_vec_add(@block_ctxt cx, @ty.t t,
2839
2850
auto tmp = r. val;
2840
2851
r = copy_ty( r. bcx, INIT , tmp, lhs, t) ;
2841
2852
auto bcx = trans_vec_append( r. bcx, t, tmp, rhs) . bcx;
2842
- tmp = load_scalar_or_boxed ( bcx, tmp, t) ;
2853
+ tmp = load_if_immediate ( bcx, tmp, t) ;
2843
2854
find_scope_cx( cx) . cleanups +=
2844
2855
vec( clean( bind drop_ty( _, tmp, t) ) ) ;
2845
2856
ret res( bcx, tmp) ;
@@ -2946,7 +2957,7 @@ fn autoderef(@block_ctxt cx, ValueRef v, @ty.t t) -> result {
2946
2957
v1 = body;
2947
2958
}
2948
2959
2949
- v1 = load_scalar_or_boxed ( cx, v1, t1) ;
2960
+ v1 = load_if_immediate ( cx, v1, t1) ;
2950
2961
}
2951
2962
case ( _) {
2952
2963
ret res( cx, v1) ;
@@ -3495,7 +3506,7 @@ fn trans_pat_match(@block_ctxt cx, @ast.pat pat, ValueRef llval,
3495
3506
auto llsubvalptr = rslt. val;
3496
3507
matched_cx = rslt. bcx;
3497
3508
3498
- auto llsubval = load_scalar_or_boxed ( matched_cx,
3509
+ auto llsubval = load_if_immediate ( matched_cx,
3499
3510
llsubvalptr,
3500
3511
pat_ty( subpat) ) ;
3501
3512
auto subpat_res = trans_pat_match( matched_cx, subpat,
@@ -3550,7 +3561,7 @@ fn trans_pat_binding(@block_ctxt cx, @ast.pat pat, ValueRef llval)
3550
3561
this_cx = rslt. bcx;
3551
3562
auto llsubvalptr = rslt. val;
3552
3563
3553
- auto llsubval = load_scalar_or_boxed ( this_cx, llsubvalptr,
3564
+ auto llsubval = load_if_immediate ( this_cx, llsubvalptr,
3554
3565
pat_ty( subpat) ) ;
3555
3566
auto subpat_res = trans_pat_binding( this_cx, subpat,
3556
3567
llsubval) ;
@@ -4417,10 +4428,7 @@ fn trans_args(@block_ctxt cx,
4417
4428
} else {
4418
4429
// Non-mem but we're trying to alias; synthesize an
4419
4430
// alloca, spill to it and pass its address.
4420
- auto llty = val_ty( lv. res. val) ;
4421
- auto llptr = alloca( lv. res. bcx, llty) ;
4422
- lv. res. bcx. build. Store ( lv. res. val, llptr) ;
4423
- val = llptr;
4431
+ val = do_spill( lv. res. bcx, lv. res. val) ;
4424
4432
}
4425
4433
4426
4434
} else {
@@ -4496,7 +4504,7 @@ fn trans_call(@block_ctxt cx, @ast.expr f,
4496
4504
// self-call
4497
4505
fn_ty = meth;
4498
4506
}
4499
-
4507
+
4500
4508
case ( _) {
4501
4509
fn_ty = ty. expr_ty( f) ;
4502
4510
@@ -4527,7 +4535,7 @@ fn trans_call(@block_ctxt cx, @ast.expr f,
4527
4535
auto retval = C_nil ( ) ;
4528
4536
4529
4537
if ( !ty. type_is_nil( ret_ty) ) {
4530
- retval = load_scalar_or_boxed ( bcx, llretslot, ret_ty) ;
4538
+ retval = load_if_immediate ( bcx, llretslot, ret_ty) ;
4531
4539
// Retval doesn't correspond to anything really tangible in the frame,
4532
4540
// but it's a ref all the same, so we put a note here to drop it when
4533
4541
// we're done in this scope.
@@ -4680,7 +4688,7 @@ fn trans_rec(@block_ctxt cx, vec[ast.field] fields,
4680
4688
if ( !expr_provided) {
4681
4689
src_res = GEP_tup_like ( bcx, t, base_val, vec( 0 , i) ) ;
4682
4690
src_res = res( src_res. bcx,
4683
- load_scalar_or_boxed ( bcx, src_res. val, e_ty) ) ;
4691
+ load_if_immediate ( bcx, src_res. val, e_ty) ) ;
4684
4692
}
4685
4693
4686
4694
bcx = src_res. bcx;
@@ -4757,7 +4765,7 @@ fn trans_expr(@block_ctxt cx, @ast.expr e) -> result {
4757
4765
auto t = node_ann_type( cx. fcx. ccx, ann) ;
4758
4766
auto lhs_res = trans_lval( cx, dst) ;
4759
4767
check ( lhs_res. is_mem) ;
4760
- auto lhs_val = load_scalar_or_boxed ( lhs_res. res. bcx,
4768
+ auto lhs_val = load_if_immediate ( lhs_res. res. bcx,
4761
4769
lhs_res. res. val, t) ;
4762
4770
auto rhs_res = trans_expr( lhs_res. res. bcx, src) ;
4763
4771
auto v = trans_eager_binop( rhs_res. bcx, op, t,
@@ -4853,21 +4861,38 @@ fn trans_expr(@block_ctxt cx, @ast.expr e) -> result {
4853
4861
4854
4862
auto t = ty. expr_ty( e) ;
4855
4863
auto sub = trans_lval( cx, e) ;
4856
- ret res( sub. res. bcx, load_scalar_or_boxed ( sub. res. bcx, sub. res. val, t) ) ;
4864
+ ret res( sub. res. bcx, load_if_immediate ( sub. res. bcx, sub. res. val, t) ) ;
4857
4865
}
4858
4866
4859
4867
// We pass structural values around the compiler "by pointer" and
4860
- // non-structural values (scalars and boxes) "by value". This function selects
4861
- // whether to load a pointer or pass it.
4868
+ // non-structural values (scalars, boxes, pointers) "by value". We call the
4869
+ // latter group "immediates" and, in some circumstances when we know we have a
4870
+ // pointer (or need one), perform load/store operations based on the
4871
+ // immediate-ness of the type.
4872
+
4873
+ fn type_is_immediate( @ty. t t) -> bool {
4874
+ ret ty. type_is_scalar( t) || ty. type_is_boxed( t) || ty. type_is_native( t) ;
4875
+ }
4876
+
4877
+ fn do_spill( @block_ctxt cx, ValueRef v) -> ValueRef {
4878
+ // We have a value but we have to spill it to pass by alias.
4879
+ auto llptr = alloca( cx, val_ty( v) ) ;
4880
+ cx. build. Store ( v, llptr) ;
4881
+ ret llptr;
4882
+ }
4862
4883
4863
- fn load_scalar_or_boxed( @block_ctxt cx,
4864
- ValueRef v,
4865
- @ty. t t) -> ValueRef {
4866
- if ( ty. type_is_scalar( t) || ty. type_is_boxed( t) || ty. type_is_native( t) ) {
4884
+ fn spill_if_immediate( @block_ctxt cx, ValueRef v, @ty. t t) -> ValueRef {
4885
+ if ( type_is_immediate( t) ) {
4886
+ ret do_spill( cx, v) ;
4887
+ }
4888
+ ret v;
4889
+ }
4890
+
4891
+ fn load_if_immediate( @block_ctxt cx, ValueRef v, @ty. t t) -> ValueRef {
4892
+ if ( type_is_immediate( t) ) {
4867
4893
ret cx. build. Load ( v) ;
4868
- } else {
4869
- ret v;
4870
4894
}
4895
+ ret v;
4871
4896
}
4872
4897
4873
4898
fn trans_log( @block_ctxt cx, @ast. expr e) -> result {
@@ -5180,7 +5205,7 @@ fn recv_val(@block_ctxt cx, ValueRef lhs, @ast.expr rhs,
5180
5205
vp2i( bcx, prt. val) ) ) ;
5181
5206
bcx = sub. bcx;
5182
5207
5183
- auto data_load = load_scalar_or_boxed ( bcx, lhs, unit_ty) ;
5208
+ auto data_load = load_if_immediate ( bcx, lhs, unit_ty) ;
5184
5209
auto cp = copy_ty( bcx, action, lhs, data_load, unit_ty) ;
5185
5210
bcx = cp. bcx;
5186
5211
@@ -5437,7 +5462,7 @@ fn trans_block(@block_ctxt cx, &ast.block b) -> result {
5437
5462
fn drop_hoisted_ty( @block_ctxt cx,
5438
5463
ValueRef alloca_val,
5439
5464
@ty. t t) -> result {
5440
- auto reg_val = load_scalar_or_boxed ( cx,
5465
+ auto reg_val = load_if_immediate ( cx,
5441
5466
alloca_val, t) ;
5442
5467
ret drop_ty( cx, reg_val, t) ;
5443
5468
}
@@ -5881,7 +5906,7 @@ fn trans_obj(@crate_ctxt cx, &ast._obj ob, ast.def_id oid,
5881
5906
i = 0 ;
5882
5907
for ( ast. obj_field f in ob. fields) {
5883
5908
auto arg = bcx. fcx. llargs. get( f. id) ;
5884
- arg = load_scalar_or_boxed ( bcx, arg, arg_tys. ( i) . ty) ;
5909
+ arg = load_if_immediate ( bcx, arg, arg_tys. ( i) . ty) ;
5885
5910
auto field = GEP_tup_like ( bcx, fields_ty, body_fields. val,
5886
5911
vec( 0 , i) ) ;
5887
5912
bcx = field. bcx;
0 commit comments