Skip to content

Commit caaf867

Browse files
committed
Teach bind to actually bind typarams, as it claims to.
1 parent 9fc9638 commit caaf867

File tree

5 files changed

+112
-61
lines changed

5 files changed

+112
-61
lines changed

src/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -475,6 +475,7 @@ TEST_XFAILS_LLVM := $(TASK_XFAILS) \
475475
foreach-simple.rs \
476476
fun-call-variants.rs \
477477
fun-indirect-call.rs \
478+
generic-bind.rs \
478479
generic-derived-type.rs \
479480
generic-drop-glue.rs \
480481
generic-exterior-box.rs \

src/boot/be/abi.ml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,8 @@ let fn_field_code = binding_field_dispatch;;
6363
let fn_field_box = binding_field_bound_data;;
6464

6565
let closure_body_elt_bound_args_tydesc = 0;;
66-
let closure_body_elt_target_tydesc = 1;;
67-
let closure_body_elt_target = 2;;
66+
let closure_body_elt_target = 1;;
67+
let closure_body_elt_bound_ty_params = 2;;
6868
let closure_body_elt_bound_args = 3;;
6969

7070
let tag_elt_discriminant = 0;;

src/boot/me/semant.ml

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2190,7 +2190,11 @@ let obj_rty (word_bits:Il.bits) : Il.referent_ty =
21902190
r [| obj_vtbl_ptr; obj_box_ptr |]
21912191
;;
21922192

2193-
let rec closure_box_rty (cx:ctxt) (bs:Ast.slot array) : Il.referent_ty =
2193+
let rec closure_box_rty
2194+
(cx:ctxt)
2195+
(n_ty_params:int)
2196+
(bs:Ast.slot array)
2197+
: Il.referent_ty =
21942198
let s t = Il.ScalarTy t in
21952199
let p t = Il.AddrTy t in
21962200
let sp t = s (p t) in
@@ -2200,10 +2204,13 @@ let rec closure_box_rty (cx:ctxt) (bs:Ast.slot array) : Il.referent_ty =
22002204
let rc = word_rty word_bits in
22012205
let tydesc = sp (tydesc_rty word_bits) in
22022206
let targ = fn_rty cx true in
2207+
let ty_param_rtys =
2208+
r (Array.init n_ty_params (fun _ -> tydesc))
2209+
in
22032210
let bound_args = r (Array.map (slot_referent_type cx) bs) in
22042211
(* First tydesc is the one describing bound_args; second tydesc is the one
22052212
* to pass to targ when invoking it. *)
2206-
r [| rc; r [| tydesc; tydesc; targ; bound_args |] |]
2213+
r [| rc; r [| tydesc; targ; ty_param_rtys; bound_args |] |]
22072214

22082215
and fn_rty (cx:ctxt) (opaque_box_body:bool) : Il.referent_ty =
22092216
let s t = Il.ScalarTy t in
@@ -2216,7 +2223,7 @@ and fn_rty (cx:ctxt) (opaque_box_body:bool) : Il.referent_ty =
22162223
let box =
22172224
if opaque_box_body
22182225
then r [| word; Il.OpaqueTy |]
2219-
else closure_box_rty cx [||]
2226+
else closure_box_rty cx 0 [||]
22202227
in
22212228
let box_ptr = sp box in
22222229
let code_ptr = sp Il.CodeTy in

src/boot/me/trans.ml

Lines changed: 91 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1663,6 +1663,7 @@ let trans_visitor
16631663
(* FIXME (issue #2): this should eventually use tail calling logic *)
16641664

16651665
and emit_fn_thunk_glue
1666+
(n_ty_params:int)
16661667
(arg_slots:Ast.slot array)
16671668
(arg_bound_flags:bool array)
16681669
(fix:fixup)
@@ -1683,14 +1684,14 @@ let trans_visitor
16831684
let (self_ty:Ast.ty) = mk_simple_ty_fn unbound_slots in
16841685
let (callee_ty:Ast.ty) = mk_simple_ty_fn arg_slots in
16851686

1686-
let self_box_rty = closure_box_rty cx bound_slots in
1687+
let self_box_rty = closure_box_rty cx n_ty_params bound_slots in
16871688

16881689
let self_args_rty =
16891690
call_args_referent_type cx 0 self_ty (Some self_box_rty)
16901691
in
16911692

16921693
let callee_args_rty =
1693-
call_args_referent_type cx 0 callee_ty (Some Il.OpaqueTy)
1694+
call_args_referent_type cx n_ty_params callee_ty (Some Il.OpaqueTy)
16941695
in
16951696

16961697
let callsz = Il.referent_ty_size word_bits callee_args_rty in
@@ -1729,6 +1730,7 @@ let trans_visitor
17291730
in
17301731

17311732
merge_bound_args
1733+
n_ty_params
17321734
self_args_rty callee_args_rty
17331735
arg_slots arg_bound_flags;
17341736
iflog (fun _ -> annotate "call through to closure target fn");
@@ -1747,6 +1749,7 @@ let trans_visitor
17471749

17481750
and get_fn_thunk_glue
17491751
(bind_id:node_id)
1752+
(n_ty_params:int)
17501753
(arg_slots:Ast.slot array)
17511754
(arg_bound_flags:bool array)
17521755
: fixup =
@@ -1755,7 +1758,7 @@ let trans_visitor
17551758
Some code -> code.code_fixup
17561759
| None ->
17571760
let fix = new_fixup (glue_str cx g) in
1758-
emit_fn_thunk_glue arg_slots arg_bound_flags fix g;
1761+
emit_fn_thunk_glue n_ty_params arg_slots arg_bound_flags fix g;
17591762
fix
17601763

17611764

@@ -4186,6 +4189,7 @@ let trans_visitor
41864189
(closure_cell:Il.cell)
41874190
(target_fn_ptr:Il.operand)
41884191
(target_binding_ptr:Il.operand)
4192+
(ty_params:Ast.ty array)
41894193
(bound_arg_slots:Ast.slot array)
41904194
(bound_args:Ast.atom array)
41914195
: unit =
@@ -4196,6 +4200,9 @@ let trans_visitor
41964200
let bound_args_tydesc_cell =
41974201
get_element_ptr body_cell Abi.closure_body_elt_bound_args_tydesc
41984202
in
4203+
let bound_ty_params_cell =
4204+
get_element_ptr body_cell Abi.closure_body_elt_bound_ty_params
4205+
in
41994206
let args_cell =
42004207
get_element_ptr body_cell Abi.closure_body_elt_bound_args
42014208
in
@@ -4219,6 +4226,16 @@ let trans_visitor
42194226
(get_element_ptr targ_cell Abi.fn_field_box)
42204227
(reify_ptr target_binding_ptr);
42214228

4229+
iflog (fun _ -> annotate "set closure bound tydescs");
4230+
Array.iteri
4231+
begin
4232+
fun i ty ->
4233+
mov
4234+
(get_element_ptr bound_ty_params_cell i)
4235+
(Il.Cell (get_tydesc None ty))
4236+
end
4237+
ty_params;
4238+
42224239
iflog (fun _ -> annotate "set closure bound args");
42234240
copy_bound_args args_cell bound_arg_slots bound_args
42244241

@@ -4233,6 +4250,12 @@ let trans_visitor
42334250
: unit =
42344251
let (dst_cell, _) = trans_lval_maybe_init initializing dst in
42354252
let (target_ptr, _) = trans_callee flv in
4253+
let ty_params =
4254+
match htab_search cx.ctxt_call_lval_params (lval_base_id flv) with
4255+
Some params -> params
4256+
| None -> [| |]
4257+
in
4258+
let n_ty_params = Array.length ty_params in
42364259
let arg_bound_flags = Array.map bool_of_option args in
42374260
let arg_slots =
42384261
arr_map2
@@ -4244,11 +4267,12 @@ let trans_visitor
42444267
let bound_arg_slots = arr_filter_some arg_slots in
42454268
let bound_args = arr_filter_some args in
42464269
let thunk_fixup =
4247-
get_fn_thunk_glue bind_id fn_sig.Ast.sig_input_slots arg_bound_flags
4270+
get_fn_thunk_glue bind_id n_ty_params
4271+
fn_sig.Ast.sig_input_slots arg_bound_flags
42484272
in
42494273
let target_code_ptr = callee_code_ptr target_ptr cc in
42504274
let target_box_ptr = callee_box_ptr flv cc in
4251-
let closure_box_rty = closure_box_rty cx bound_arg_slots in
4275+
let closure_box_rty = closure_box_rty cx n_ty_params bound_arg_slots in
42524276
let closure_box_sz =
42534277
calculate_sz_in_current_frame
42544278
(Il.referent_ty_size word_bits closure_box_rty)
@@ -4268,6 +4292,7 @@ let trans_visitor
42684292
(deref pair_box_cell)
42694293
target_code_ptr
42704294
target_box_ptr
4295+
ty_params
42714296
bound_arg_slots
42724297
bound_args
42734298

@@ -4466,14 +4491,15 @@ let trans_visitor
44664491
bound_arg_slots
44674492

44684493
and merge_bound_args
4494+
(n_ty_params:int)
44694495
(all_self_args_rty:Il.referent_ty)
44704496
(all_callee_args_rty:Il.referent_ty)
44714497
(arg_slots:Ast.slot array)
44724498
(arg_bound_flags:bool array)
44734499
: unit =
44744500
begin
44754501
(*
4476-
* NB: 'all_*_args', both self and callee, are always 4-tuples:
4502+
* NB: 'all_*_args', both self and callee, are always 5-tuples:
44774503
*
44784504
* [out_ptr, task_ptr, indirect_args, ty_params, [args]]
44794505
*
@@ -4486,17 +4512,31 @@ let trans_visitor
44864512
let self_args_cell =
44874513
get_element_ptr all_self_args_cell Abi.calltup_elt_args
44884514
in
4489-
let self_ty_params_cell =
4490-
get_element_ptr all_self_args_cell Abi.calltup_elt_ty_params
4515+
let self_indirect_args_cell =
4516+
get_element_ptr all_self_args_cell Abi.calltup_elt_indirect_args
4517+
in
4518+
let closure_box_cell =
4519+
deref (get_element_ptr self_indirect_args_cell
4520+
Abi.indirect_args_elt_closure)
4521+
in
4522+
let closure_cell =
4523+
get_element_ptr closure_box_cell Abi.box_rc_field_body
4524+
in
4525+
let closure_args_cell =
4526+
get_element_ptr closure_cell Abi.closure_body_elt_bound_args
4527+
in
4528+
let closure_ty_params_cell =
4529+
get_element_ptr closure_cell Abi.closure_body_elt_bound_ty_params
4530+
in
4531+
let callee_ty_params_cell =
4532+
get_element_ptr all_callee_args_cell Abi.calltup_elt_ty_params
44914533
in
44924534
let callee_args_cell =
44934535
(* FIXME (issue #81): Once we've actually got proper ty_params,
44944536
* we should GEP dynamically here to get the args, since they may
44954537
* be aligned dynamically if they have parameterized type. *)
4496-
get_element_ptr all_callee_args_cell Abi.calltup_elt_args
4497-
in
4498-
let self_indirect_args_cell =
4499-
get_element_ptr all_self_args_cell Abi.calltup_elt_indirect_args
4538+
get_element_ptr_dyn closure_ty_params_cell
4539+
all_callee_args_cell Abi.calltup_elt_args
45004540
in
45014541

45024542
let n_args = Array.length arg_bound_flags in
@@ -4515,51 +4555,46 @@ let trans_visitor
45154555
(Il.Cell (get_element_ptr all_self_args_cell
45164556
Abi.calltup_elt_task_ptr));
45174557

4518-
iflog (fun _ -> annotate "extract closure indirect-arg");
4519-
let closure_box_cell =
4520-
deref (get_element_ptr self_indirect_args_cell
4521-
Abi.indirect_args_elt_closure)
4522-
in
4523-
let closure_cell =
4524-
get_element_ptr closure_box_cell Abi.box_rc_field_body
4525-
in
4526-
4527-
let closure_args_cell =
4528-
get_element_ptr closure_cell Abi.closure_body_elt_bound_args
4529-
in
4558+
iflog (fun _ -> annotate "copy ty-params");
4559+
for ty_i = 0 to (n_ty_params - 1) do
4560+
mov
4561+
(get_element_ptr callee_ty_params_cell ty_i)
4562+
(Il.Cell (get_element_ptr closure_ty_params_cell ty_i))
4563+
done;
45304564

4531-
for arg_i = 0 to (n_args - 1) do
4532-
let dst_cell = get_element_ptr callee_args_cell arg_i in
4533-
let slot = arg_slots.(arg_i) in
4534-
let is_bound = arg_bound_flags.(arg_i) in
4535-
let src_cell =
4536-
if is_bound then
4537-
begin
4538-
iflog (fun _ -> annotate
4539-
(Printf.sprintf
4540-
"extract bound arg %d as actual arg %d"
4541-
!bound_i arg_i));
4542-
get_element_ptr closure_args_cell (!bound_i)
4543-
end
4544-
else
4545-
begin
4546-
iflog (fun _ -> annotate
4547-
(Printf.sprintf
4548-
"extract unbound arg %d as actual arg %d"
4549-
!unbound_i arg_i));
4550-
get_element_ptr self_args_cell (!unbound_i);
4551-
end
4552-
in
4553-
iflog (fun _ -> annotate
4554-
(Printf.sprintf
4555-
"copy into actual-arg %d" arg_i));
4556-
trans_init_slot_from_cell
4557-
self_ty_params_cell CLONE_none
4558-
dst_cell slot
4559-
(deref_slot false src_cell slot) (slot_ty slot);
4560-
incr (if is_bound then bound_i else unbound_i);
4561-
done;
4562-
assert ((!bound_i + !unbound_i) == n_args)
4565+
iflog (fun _ -> annotate "copy args");
4566+
for arg_i = 0 to (n_args - 1) do
4567+
let dst_cell = get_element_ptr callee_args_cell arg_i in
4568+
let slot = arg_slots.(arg_i) in
4569+
let is_bound = arg_bound_flags.(arg_i) in
4570+
let src_cell =
4571+
if is_bound then
4572+
begin
4573+
iflog (fun _ -> annotate
4574+
(Printf.sprintf
4575+
"extract bound arg %d as actual arg %d"
4576+
!bound_i arg_i));
4577+
get_element_ptr closure_args_cell (!bound_i)
4578+
end
4579+
else
4580+
begin
4581+
iflog (fun _ -> annotate
4582+
(Printf.sprintf
4583+
"extract unbound arg %d as actual arg %d"
4584+
!unbound_i arg_i));
4585+
get_element_ptr self_args_cell (!unbound_i);
4586+
end
4587+
in
4588+
iflog (fun _ -> annotate
4589+
(Printf.sprintf
4590+
"copy into actual-arg %d" arg_i));
4591+
trans_init_slot_from_cell
4592+
closure_ty_params_cell CLONE_none
4593+
dst_cell slot
4594+
(deref_slot false src_cell slot) (slot_ty slot);
4595+
incr (if is_bound then bound_i else unbound_i);
4596+
done;
4597+
assert ((!bound_i + !unbound_i) == n_args)
45634598
end
45644599

45654600

src/test/run-pass/generic-bind.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
fn id[T](T t) -> T {
2+
ret t;
3+
}
4+
5+
fn main() {
6+
auto f = bind id[int](_);
7+
check (f(10) == 10);
8+
}

0 commit comments

Comments
 (0)