about summary refs log tree commit diff
diff options
context:
space:
mode:
authorGraydon Hoare <graydon@mozilla.com>2010-10-13 15:53:38 -0700
committerGraydon Hoare <graydon@mozilla.com>2010-10-13 15:53:38 -0700
commit52c2a1549c2dda91d147d20edd62f6465b90d9e4 (patch)
tree00e93fcc2a7b2c348c2beaec5c85391943b6c089
parent1e19fc969ed553934d51b565d5d9ad010cf3b569 (diff)
Fetch typarams from the outermost item frame, when inside an iter-block. One less crash in rustc.
-rw-r--r--src/Makefile1
-rw-r--r--src/boot/me/semant.ml8
-rw-r--r--src/boot/me/trans.ml80
-rw-r--r--src/test/run-pass/generic-iter-frame.rs16
4 files changed, 75 insertions, 30 deletions
diff --git a/src/Makefile b/src/Makefile
index ff9dae16602..12956baacdd 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -481,6 +481,7 @@ TEST_XFAILS_LLVM := $(TASK_XFAILS) \
                       generic-exterior-box.rs \
                       generic-fn-infer.rs \
                       generic-fn.rs \
+                      generic-iter-frame.rs \
                       generic-obj-with-derived-type.rs \
                       generic-obj.rs \
                       generic-recursive-tag.rs \
diff --git a/src/boot/me/semant.ml b/src/boot/me/semant.ml
index c8b3b45e0d5..8ff439e8b65 100644
--- a/src/boot/me/semant.ml
+++ b/src/boot/me/semant.ml
@@ -495,12 +495,18 @@ let get_callsz (cx:ctxt) (id:node_id) : size =
   else bugi cx id "missing callsz"
 ;;
 
+let get_loop_outermost_fn (cx:ctxt) (id:node_id) : node_id =
+  match Hashtbl.find cx.ctxt_all_defns id with
+      DEFN_loop_body fnid -> fnid
+    | _ -> bugi cx id "get_loop_outermost_fn on non-loop"
+;;
+
 let rec n_item_ty_params (cx:ctxt) (id:node_id) : int =
   match Hashtbl.find cx.ctxt_all_defns id with
       DEFN_item i -> Array.length i.Ast.decl_params
     | DEFN_obj_fn (oid,_) -> n_item_ty_params cx oid
     | DEFN_obj_drop oid -> n_item_ty_params cx oid
-    | DEFN_loop_body fid -> n_item_ty_params cx fid
+    | DEFN_loop_body _ -> 0
     | _ -> bugi cx id "n_item_ty_params on non-item"
 ;;
 
diff --git a/src/boot/me/trans.ml b/src/boot/me/trans.ml
index 67a96030fa6..edbfd06e364 100644
--- a/src/boot/me/trans.ml
+++ b/src/boot/me/trans.ml
@@ -624,10 +624,61 @@ let trans_visitor
         Abi.iterator_args_elt_outer_frame_ptr
   in
 
+  (*
+   * Within a for-each block, calculate the fp of an enclosing for-each block
+   * or the enclosing function by chasing static links.
+   *)
+  let get_nth_outer_frame_ptr (diff:int) : Il.cell =
+    (* All for-each block frames have the same args. *)
+    let block_args_rty = current_fn_args_rty None in
+    let current_fp = Il.Reg (abi.Abi.abi_fp_reg, Il.AddrTy Il.OpaqueTy) in
+    let rec out (n:int) (fp:Il.cell) : Il.cell =
+      if n == 0
+      then fp
+      else
+        let args = fp_to_args fp block_args_rty in
+        let iter_args = get_element_ptr args Abi.calltup_elt_iterator_args in
+        let outer_fp =
+          get_element_ptr iter_args Abi.iterator_args_elt_outer_frame_ptr
+        in
+          out (n - 1) outer_fp
+    in
+      out diff current_fp
+  in
+
+  let curr_stmt_depth _ =
+    if (Stack.is_empty curr_stmt)
+    then None
+    else
+      Some
+        (get_stmt_depth cx (Stack.top curr_stmt))
+  in
+
   let get_ty_params_of_current_frame _ : Il.cell =
     let fnid = current_fn() in
     let n_ty_params = n_item_ty_params cx fnid in
+    let local _ =
       get_ty_params_of_frame fnid abi.Abi.abi_fp_reg n_ty_params
+    in
+      if Hashtbl.mem cx.ctxt_block_is_loop_body fnid
+      then
+        begin
+          let outermost_fnid = get_loop_outermost_fn cx fnid in
+            match curr_stmt_depth() with
+                None -> local()
+              | Some depth ->
+                  iflog (fun _ ->
+                           annotate "loading outermost frame ty params");
+                  let (outermost_fp, _) =
+                    force_to_reg (Il.Cell (get_nth_outer_frame_ptr depth))
+                  in
+                    get_ty_params_of_frame
+                      outermost_fnid
+                      outermost_fp
+                      (n_item_ty_params cx outermost_fnid)
+        end
+      else
+        local()
   in
 
   let get_ty_param_in_current_frame (param_idx:int) : Il.cell =
@@ -872,35 +923,6 @@ let trans_visitor
             Il.Mem (mem, (pointee_type ptr))
   in
 
-  (*
-   * Within a for-each block, calculate the fp of an enclosing for-each block
-   * or the enclosing function by chasing static links.
-   *)
-  let get_nth_outer_frame_ptr (diff:int) : Il.cell =
-    (* All for-each block frames have the same args. *)
-    let block_args_rty = current_fn_args_rty None in
-    let current_fp = Il.Reg (abi.Abi.abi_fp_reg, Il.AddrTy Il.OpaqueTy) in
-    let rec out (n:int) (fp:Il.cell) : Il.cell =
-      if n == 0
-      then fp
-      else
-        let args = fp_to_args fp block_args_rty in
-        let iter_args = get_element_ptr args Abi.calltup_elt_iterator_args in
-        let outer_fp =
-          get_element_ptr iter_args Abi.iterator_args_elt_outer_frame_ptr
-        in
-          out (n - 1) outer_fp
-    in
-      out diff current_fp
-  in
-
-  let curr_stmt_depth _ =
-    if (Stack.is_empty curr_stmt)
-    then None
-    else
-      Some
-        (get_stmt_depth cx (Stack.top curr_stmt))
-  in
 
   let cell_of_block_slot
       ?access_depth:(access_depth=curr_stmt_depth())
diff --git a/src/test/run-pass/generic-iter-frame.rs b/src/test/run-pass/generic-iter-frame.rs
new file mode 100644
index 00000000000..a3c48d78455
--- /dev/null
+++ b/src/test/run-pass/generic-iter-frame.rs
@@ -0,0 +1,16 @@
+// Contrived example? No. It showed up in rustc's resolve pass.
+
+iter i() -> () {
+  put ();
+}
+
+fn foo[T](T t) {
+  let int x = 10;
+  for each (() j in i()) {
+    log x;
+  }
+}
+
+fn main() {
+  foo(0xdeadbeef_u);
+}