Skip to content

Commit

Permalink
Teach bind to actually bind typarams, as it claims to.
Browse files Browse the repository at this point in the history
  • Loading branch information
graydon committed Oct 10, 2010
1 parent 9fc9638 commit caaf867
Show file tree
Hide file tree
Showing 5 changed files with 112 additions and 61 deletions.
1 change: 1 addition & 0 deletions src/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -475,6 +475,7 @@ TEST_XFAILS_LLVM := $(TASK_XFAILS) \
foreach-simple.rs \
fun-call-variants.rs \
fun-indirect-call.rs \
generic-bind.rs \
generic-derived-type.rs \
generic-drop-glue.rs \
generic-exterior-box.rs \
Expand Down
4 changes: 2 additions & 2 deletions src/boot/be/abi.ml
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,8 @@ let fn_field_code = binding_field_dispatch;;
let fn_field_box = binding_field_bound_data;;

let closure_body_elt_bound_args_tydesc = 0;;
let closure_body_elt_target_tydesc = 1;;
let closure_body_elt_target = 2;;
let closure_body_elt_target = 1;;
let closure_body_elt_bound_ty_params = 2;;
let closure_body_elt_bound_args = 3;;

let tag_elt_discriminant = 0;;
Expand Down
13 changes: 10 additions & 3 deletions src/boot/me/semant.ml
Original file line number Diff line number Diff line change
Expand Up @@ -2190,7 +2190,11 @@ let obj_rty (word_bits:Il.bits) : Il.referent_ty =
r [| obj_vtbl_ptr; obj_box_ptr |]
;;

let rec closure_box_rty (cx:ctxt) (bs:Ast.slot array) : Il.referent_ty =
let rec closure_box_rty
(cx:ctxt)
(n_ty_params:int)
(bs:Ast.slot array)
: Il.referent_ty =
let s t = Il.ScalarTy t in
let p t = Il.AddrTy t in
let sp t = s (p t) in
Expand All @@ -2200,10 +2204,13 @@ let rec closure_box_rty (cx:ctxt) (bs:Ast.slot array) : Il.referent_ty =
let rc = word_rty word_bits in
let tydesc = sp (tydesc_rty word_bits) in
let targ = fn_rty cx true in
let ty_param_rtys =
r (Array.init n_ty_params (fun _ -> tydesc))
in
let bound_args = r (Array.map (slot_referent_type cx) bs) in
(* First tydesc is the one describing bound_args; second tydesc is the one
* to pass to targ when invoking it. *)
r [| rc; r [| tydesc; tydesc; targ; bound_args |] |]
r [| rc; r [| tydesc; targ; ty_param_rtys; bound_args |] |]

and fn_rty (cx:ctxt) (opaque_box_body:bool) : Il.referent_ty =
let s t = Il.ScalarTy t in
Expand All @@ -2216,7 +2223,7 @@ and fn_rty (cx:ctxt) (opaque_box_body:bool) : Il.referent_ty =
let box =
if opaque_box_body
then r [| word; Il.OpaqueTy |]
else closure_box_rty cx [||]
else closure_box_rty cx 0 [||]
in
let box_ptr = sp box in
let code_ptr = sp Il.CodeTy in
Expand Down
147 changes: 91 additions & 56 deletions src/boot/me/trans.ml
Original file line number Diff line number Diff line change
Expand Up @@ -1663,6 +1663,7 @@ let trans_visitor
(* FIXME (issue #2): this should eventually use tail calling logic *)

and emit_fn_thunk_glue
(n_ty_params:int)
(arg_slots:Ast.slot array)
(arg_bound_flags:bool array)
(fix:fixup)
Expand All @@ -1683,14 +1684,14 @@ let trans_visitor
let (self_ty:Ast.ty) = mk_simple_ty_fn unbound_slots in
let (callee_ty:Ast.ty) = mk_simple_ty_fn arg_slots in

let self_box_rty = closure_box_rty cx bound_slots in
let self_box_rty = closure_box_rty cx n_ty_params bound_slots in

let self_args_rty =
call_args_referent_type cx 0 self_ty (Some self_box_rty)
in

let callee_args_rty =
call_args_referent_type cx 0 callee_ty (Some Il.OpaqueTy)
call_args_referent_type cx n_ty_params callee_ty (Some Il.OpaqueTy)
in

let callsz = Il.referent_ty_size word_bits callee_args_rty in
Expand Down Expand Up @@ -1729,6 +1730,7 @@ let trans_visitor
in

merge_bound_args
n_ty_params
self_args_rty callee_args_rty
arg_slots arg_bound_flags;
iflog (fun _ -> annotate "call through to closure target fn");
Expand All @@ -1747,6 +1749,7 @@ let trans_visitor

and get_fn_thunk_glue
(bind_id:node_id)
(n_ty_params:int)
(arg_slots:Ast.slot array)
(arg_bound_flags:bool array)
: fixup =
Expand All @@ -1755,7 +1758,7 @@ let trans_visitor
Some code -> code.code_fixup
| None ->
let fix = new_fixup (glue_str cx g) in
emit_fn_thunk_glue arg_slots arg_bound_flags fix g;
emit_fn_thunk_glue n_ty_params arg_slots arg_bound_flags fix g;
fix


Expand Down Expand Up @@ -4186,6 +4189,7 @@ let trans_visitor
(closure_cell:Il.cell)
(target_fn_ptr:Il.operand)
(target_binding_ptr:Il.operand)
(ty_params:Ast.ty array)
(bound_arg_slots:Ast.slot array)
(bound_args:Ast.atom array)
: unit =
Expand All @@ -4196,6 +4200,9 @@ let trans_visitor
let bound_args_tydesc_cell =
get_element_ptr body_cell Abi.closure_body_elt_bound_args_tydesc
in
let bound_ty_params_cell =
get_element_ptr body_cell Abi.closure_body_elt_bound_ty_params
in
let args_cell =
get_element_ptr body_cell Abi.closure_body_elt_bound_args
in
Expand All @@ -4219,6 +4226,16 @@ let trans_visitor
(get_element_ptr targ_cell Abi.fn_field_box)
(reify_ptr target_binding_ptr);

iflog (fun _ -> annotate "set closure bound tydescs");
Array.iteri
begin
fun i ty ->
mov
(get_element_ptr bound_ty_params_cell i)
(Il.Cell (get_tydesc None ty))
end
ty_params;

iflog (fun _ -> annotate "set closure bound args");
copy_bound_args args_cell bound_arg_slots bound_args

Expand All @@ -4233,6 +4250,12 @@ let trans_visitor
: unit =
let (dst_cell, _) = trans_lval_maybe_init initializing dst in
let (target_ptr, _) = trans_callee flv in
let ty_params =
match htab_search cx.ctxt_call_lval_params (lval_base_id flv) with
Some params -> params
| None -> [| |]
in
let n_ty_params = Array.length ty_params in
let arg_bound_flags = Array.map bool_of_option args in
let arg_slots =
arr_map2
Expand All @@ -4244,11 +4267,12 @@ let trans_visitor
let bound_arg_slots = arr_filter_some arg_slots in
let bound_args = arr_filter_some args in
let thunk_fixup =
get_fn_thunk_glue bind_id fn_sig.Ast.sig_input_slots arg_bound_flags
get_fn_thunk_glue bind_id n_ty_params
fn_sig.Ast.sig_input_slots arg_bound_flags
in
let target_code_ptr = callee_code_ptr target_ptr cc in
let target_box_ptr = callee_box_ptr flv cc in
let closure_box_rty = closure_box_rty cx bound_arg_slots in
let closure_box_rty = closure_box_rty cx n_ty_params bound_arg_slots in
let closure_box_sz =
calculate_sz_in_current_frame
(Il.referent_ty_size word_bits closure_box_rty)
Expand All @@ -4268,6 +4292,7 @@ let trans_visitor
(deref pair_box_cell)
target_code_ptr
target_box_ptr
ty_params
bound_arg_slots
bound_args

Expand Down Expand Up @@ -4466,14 +4491,15 @@ let trans_visitor
bound_arg_slots

and merge_bound_args
(n_ty_params:int)
(all_self_args_rty:Il.referent_ty)
(all_callee_args_rty:Il.referent_ty)
(arg_slots:Ast.slot array)
(arg_bound_flags:bool array)
: unit =
begin
(*
* NB: 'all_*_args', both self and callee, are always 4-tuples:
* NB: 'all_*_args', both self and callee, are always 5-tuples:
*
* [out_ptr, task_ptr, indirect_args, ty_params, [args]]
*
Expand All @@ -4486,17 +4512,31 @@ let trans_visitor
let self_args_cell =
get_element_ptr all_self_args_cell Abi.calltup_elt_args
in
let self_ty_params_cell =
get_element_ptr all_self_args_cell Abi.calltup_elt_ty_params
let self_indirect_args_cell =
get_element_ptr all_self_args_cell Abi.calltup_elt_indirect_args
in
let closure_box_cell =
deref (get_element_ptr self_indirect_args_cell
Abi.indirect_args_elt_closure)
in
let closure_cell =
get_element_ptr closure_box_cell Abi.box_rc_field_body
in
let closure_args_cell =
get_element_ptr closure_cell Abi.closure_body_elt_bound_args
in
let closure_ty_params_cell =
get_element_ptr closure_cell Abi.closure_body_elt_bound_ty_params
in
let callee_ty_params_cell =
get_element_ptr all_callee_args_cell Abi.calltup_elt_ty_params
in
let callee_args_cell =
(* FIXME (issue #81): Once we've actually got proper ty_params,
* we should GEP dynamically here to get the args, since they may
* be aligned dynamically if they have parameterized type. *)
get_element_ptr all_callee_args_cell Abi.calltup_elt_args
in
let self_indirect_args_cell =
get_element_ptr all_self_args_cell Abi.calltup_elt_indirect_args
get_element_ptr_dyn closure_ty_params_cell
all_callee_args_cell Abi.calltup_elt_args
in

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

iflog (fun _ -> annotate "extract closure indirect-arg");
let closure_box_cell =
deref (get_element_ptr self_indirect_args_cell
Abi.indirect_args_elt_closure)
in
let closure_cell =
get_element_ptr closure_box_cell Abi.box_rc_field_body
in

let closure_args_cell =
get_element_ptr closure_cell Abi.closure_body_elt_bound_args
in
iflog (fun _ -> annotate "copy ty-params");
for ty_i = 0 to (n_ty_params - 1) do
mov
(get_element_ptr callee_ty_params_cell ty_i)
(Il.Cell (get_element_ptr closure_ty_params_cell ty_i))
done;

for arg_i = 0 to (n_args - 1) do
let dst_cell = get_element_ptr callee_args_cell arg_i in
let slot = arg_slots.(arg_i) in
let is_bound = arg_bound_flags.(arg_i) in
let src_cell =
if is_bound then
begin
iflog (fun _ -> annotate
(Printf.sprintf
"extract bound arg %d as actual arg %d"
!bound_i arg_i));
get_element_ptr closure_args_cell (!bound_i)
end
else
begin
iflog (fun _ -> annotate
(Printf.sprintf
"extract unbound arg %d as actual arg %d"
!unbound_i arg_i));
get_element_ptr self_args_cell (!unbound_i);
end
in
iflog (fun _ -> annotate
(Printf.sprintf
"copy into actual-arg %d" arg_i));
trans_init_slot_from_cell
self_ty_params_cell CLONE_none
dst_cell slot
(deref_slot false src_cell slot) (slot_ty slot);
incr (if is_bound then bound_i else unbound_i);
done;
assert ((!bound_i + !unbound_i) == n_args)
iflog (fun _ -> annotate "copy args");
for arg_i = 0 to (n_args - 1) do
let dst_cell = get_element_ptr callee_args_cell arg_i in
let slot = arg_slots.(arg_i) in
let is_bound = arg_bound_flags.(arg_i) in
let src_cell =
if is_bound then
begin
iflog (fun _ -> annotate
(Printf.sprintf
"extract bound arg %d as actual arg %d"
!bound_i arg_i));
get_element_ptr closure_args_cell (!bound_i)
end
else
begin
iflog (fun _ -> annotate
(Printf.sprintf
"extract unbound arg %d as actual arg %d"
!unbound_i arg_i));
get_element_ptr self_args_cell (!unbound_i);
end
in
iflog (fun _ -> annotate
(Printf.sprintf
"copy into actual-arg %d" arg_i));
trans_init_slot_from_cell
closure_ty_params_cell CLONE_none
dst_cell slot
(deref_slot false src_cell slot) (slot_ty slot);
incr (if is_bound then bound_i else unbound_i);
done;
assert ((!bound_i + !unbound_i) == n_args)
end


Expand Down
8 changes: 8 additions & 0 deletions src/test/run-pass/generic-bind.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
fn id[T](T t) -> T {
ret t;
}

fn main() {
auto f = bind id[int](_);
check (f(10) == 10);
}

0 comments on commit caaf867

Please sign in to comment.