Taddeus Kroes 12 лет назад
Родитель
Сommit
98f34c1ac8
2 измененных файлов с 72 добавлено и 5 удалено
  1. 8 5
      phases/dimreduce.ml
  2. 64 0
      phases/dimreduce.mli

+ 8 - 5
phases/dimreduce.ml

@@ -1,6 +1,7 @@
 open Types
 open Util
 
+(* Pass array dimensions explicitly to functions *)
 let rec expand_dims = function
   (* Flatten Block nodes returned by transformations below *)
   | FunDef (export, ret_type, name, params, body, ann) ->
@@ -28,7 +29,7 @@ let rec expand_dims = function
   | Arg (VarUse (VarDec (ArrayDims (ctype, dims), name, None, decann), None, ann)) ->
     let rec do_expand = function
       | [] ->
-        (* Remove the (now obsolete dimensions fromt the type) *)
+        (* Remove the (now obsolete dimensions from the type) *)
         let dec = VarDec (Array ctype, name, None, decann) in
         [VarUse (dec, None, ann)]
       | hd :: tl ->
@@ -40,10 +41,6 @@ let rec expand_dims = function
     in
     Block (do_expand dims)
 
-  (* Simplify array types in declarations *)
-  | VarDec (ArrayDims (ctype, _), name, None, ann) ->
-    VarDec (Array ctype, name, None, ann)
-
   | node -> transform_children expand_dims node
 
 let rec multiply = function
@@ -71,10 +68,16 @@ let rec expand depth dims =
   in
   do_expand (List.map use_dim (List.tl dims))
 
+(* Transform multi-dimensional arrays into one-dimensional arrays in row-major
+ * order *)
 and dim_reduce depth = function
   | Allocate (dec, dims, ann) ->
     Allocate (dec, [multiply dims], ann)
 
+  (* Simplify array types in declarations *)
+  | VarDec (ArrayDims (ctype, _), name, None, ann) ->
+    VarDec (Array ctype, name, None, ann)
+
   (* Increase nesting depth when goiing into function *)
   | FunDef (export, ret_type, name, params, body, ann) ->
     let trav = dim_reduce (depth + 1) in

+ 64 - 0
phases/dimreduce.mli

@@ -1 +1,65 @@
+(** Dimension reduction: transform multi-dimensional arrays to one-dimensional
+    arrays, and pass original array dimensions in function calls. *)
+
+(**
+    This phase lowers multi-dimensional ararys to one-dimensional arrays. This
+    transformation is done in two steps.
+
+    In the first step, function calls and function parameter lists are modified.
+    For function calls, array dimensions are passed as explicit arguments before
+    the array argument itself. Naturally, function declarations need to be
+    modified accordingly, adding explicit parameters for array dimensions.
+
+    Note that we need not create new variable declarations for array
+    declarations here. This is already done during the desugaring phase
+    ({!Desug} explains the reason for this).
+
+    In the second step, statements and expressions involving multi-dimensional
+    array referencing are transformed such that they reference a one-dimensional
+    array. Variable declarations with type [ArrayDims] are transformed into
+    variables of type [Array], thus removing the dimensionality information.
+    Allocation statements become one-dimensional allocations with a length that
+    is the product of all array dimensions. Indexing multi-dimensional arrays is
+    changed such that arrays are accessed in row-major order.
+
+{v void foo(int[a, b, c] p) \{
+    int n; int m; int k; int[n, m, k] q;  // n, m, k are added during desugaring
+    n = 5;
+    m = 10;
+    k = 3;
+    q = __allocate(n, m, k);
+    q[x, y, z] = p[x, y, z];
+    foo(q);
+\} v}
+
+    step 1:
+
+{v void foo(int a, int b, int c, int[] p) \{  // Array parameter
+    int n; int m; int k; int[n, m, k] q;
+    n = 5;
+    m = 10;
+    k = 3;
+    q = __allocate(n, m, k);
+    q[x, y, z] = p[x, y, z];
+    foo(n, m, k, q);                      // Array argument
+\} v}
+
+    step 2:
+
+{v void foo(int[a, b, c] p) \{
+    int n; int m; int k; int[] q;  // Removing dimension information
+    n = 5;
+    m = 10;
+    k = 3;
+    q = __allocate(n * m * k);                            // Allocation
+    q[((x * m) + y) * k + z] = p[((x * b) + y) * c + z];  // Indexing
+    foo(n, m, k, q);
+\} v}
+
+    Note that when array dimensions are constant integer values, an array index
+    may be simplified to a single constant value during contant propagation.
+    *)
+
+
+(** Main phase function, called by {!Main}. *)
 val phase : Main.phase_func