Home My Page Projects Code Snippets Project Openings diderot
Summary Activity Tracker Tasks SCM

SCM Repository

[diderot] Annotation of /branches/vis12/src/compiler/c-target/gen-output.sml
ViewVC logotype

Annotation of /branches/vis12/src/compiler/c-target/gen-output.sml

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1734 - (view) (download)

1 : jhr 1707 (* gen-output.sml
2 :     *
3 :     * COPYRIGHT (c) 2012 The Diderot Project (http://diderot-language.cs.uchicago.edu)
4 :     * All rights reserved.
5 :     *
6 : jhr 1710 * Generate strand output functions. There are four cases that we handle:
7 :     *
8 :     * grid, fixed-size elements:
9 :     * nrrd has object dimensions followed by axes
10 :     *
11 :     * collection, fixed-size elements
12 :     * nrrd has object dims followed by a single axis
13 :     *
14 :     * grid, dynamic-size elements
15 : jhr 1722 * nLengths nrrd has size 2 for objects (offset, length) followed by axes
16 :     * nData nrrd has object dimensions followed by a single axis
17 : jhr 1710 *
18 :     * collection, dynamic-size elements
19 : jhr 1722 * nLengths nrrd has size 2 for objects (offset, length) followed by a single axis
20 :     * nData nrrd has object dimensions followed by a single axis
21 : jhr 1707 *)
22 :    
23 :     structure GenOutput : sig
24 :    
25 :     val gen : TargetUtil.target_desc * int option -> (TreeIL.Ty.ty * string) -> CLang.decl
26 :    
27 :     end = struct
28 :    
29 :     structure IL = TreeIL
30 :     structure V = IL.Var
31 :     structure Ty = IL.Ty
32 :     structure CL = CLang
33 :     structure N = CNames
34 :    
35 :     fun mapi f l = let
36 :     fun mapf (i, [], l) = List.rev l
37 :     | mapf (i, x::xs, l) = mapf (i+1, xs, f(i, x)::l)
38 :     in
39 :     mapf (0, l, [])
40 :     end
41 :    
42 :     val nrrdPtrTy = CL.T_Ptr(CL.T_Named "Nrrd")
43 :     val sizeTy = CL.T_Named "size_t"
44 :    
45 :     fun mkInt i = CL.mkInt(IntInf.fromInt i)
46 :    
47 :     fun infoOf (tgt : TargetUtil.target_desc, ty) = (case ty
48 :     of Ty.IntTy => if #longint tgt
49 :     then (CL.int64, "nrrdTypeLLong", [1])
50 :     else (CL.int32, "nrrdTypeInt", [1])
51 :     | Ty.TensorTy [] => if #double tgt
52 :     then (CL.double, "nrrdTypeDouble", [1])
53 :     else (CL.float, "nrrdTypeFloat", [1])
54 :     | Ty.TensorTy dims => if #double tgt
55 :     then (CL.double, "nrrdTypeDouble", dims)
56 :     else (CL.float, "nrrdTypeFloat", dims)
57 :     | Ty.SeqTy(ty, n) => let
58 :     val (elemTy, nrrdTy, dims) = infoOf (tgt, ty)
59 :     in
60 :     (elemTy, nrrdTy, n::dims)
61 :     end
62 :     | _ => raise Fail(concat["GetOutput.infoOf(", Ty.toString ty, ")"])
63 :     (* end case *))
64 :    
65 :     (* variables in the generated code *)
66 :     val wrldV = CL.mkVar "wrld"
67 :     val sizesV = CL.mkVar "sizes"
68 :     val iV = CL.mkVar "i"
69 : jhr 1710 val nV = CL.mkVar "n"
70 : jhr 1715 val cpV = CL.mkVar "cp"
71 :     val ipV = CL.mkVar "ip"
72 : jhr 1710 val offsetV = CL.mkVar "offset"
73 : jhr 1722 val nDataV = CL.mkVar "nData"
74 :     val nLengthsV = CL.mkVar "nLengths"
75 : jhr 1708 val numStableV = CL.mkVar "numStable"
76 :     val numElemsV = CL.mkVar "numElems"
77 : jhr 1707 val DIDEROT_STABLE = CL.mkVar "DIDEROT_STABLE"
78 : jhr 1708 val NRRD = CL.mkVar "NRRD"
79 : jhr 1707
80 : jhr 1708 (* dymanic sequence operations *)
81 :     fun seqLength arg = CL.mkApply("Diderot_DynSeqLength", [arg])
82 :     fun seqCopy (elemSz, dst, seq) = CL.mkApply("Diderot_DynSeqCopy", [elemSz, dst, seq])
83 :    
84 : jhr 1709 (* utility functions for initializing the sizes array *)
85 :     fun sizes i = CL.mkSubscript(sizesV, mkInt i)
86 :     fun setSizes (i, v) = CL.mkAssign(sizes i, v)
87 :    
88 : jhr 1708 (* code to access state variable
89 :     wrld->outState[i].name
90 :     *)
91 :     fun stateVar name = CL.mkIndirect(CL.mkSubscript(CL.mkIndirect(wrldV, "outState"), iV), name)
92 :    
93 :     (* code fragment to loop over strands
94 :     for (unsigned int i = 0; i < wrld->numStrands; i++) ...
95 :     *)
96 :     fun forStrands stm = CL.mkFor(
97 :     [(CL.uint32, "i", mkInt 0)],
98 :     CL.mkBinOp(iV, CL.#<, CL.mkIndirect(wrldV, "numStrands")),
99 : jhr 1718 [CL.mkPostOp(iV, CL.^++)],
100 : jhr 1708 stm)
101 :    
102 :     (* code fragment to test for stable strands in a loop
103 :     if (wrld->status[i] == DIDEROT_STABLE)
104 :     ...
105 :     *)
106 :     fun ifStable stm = CL.mkIfThen(
107 :     CL.mkBinOp(CL.mkSubscript(CL.mkIndirect(wrldV, "status"), iV), CL.#==, DIDEROT_STABLE),
108 :     stm)
109 :    
110 :     (* code fragment to allocate nrrd data and check for errors
111 :     if (nrrdMaybeAlloc_nva(<nrrdVar>, <nrrdType>, <nDims>, sizes) != 0) {
112 :     wrld->err = biffGetDone(NRRD);
113 :     return true;
114 : jhr 1707 }
115 : jhr 1708 *)
116 :     fun maybeAlloc (nrrdVar, nrrdType, nDims) =
117 :     CL.mkIfThen(
118 :     CL.mkBinOp(
119 :     CL.mkApply("nrrdMaybeAlloc_nva", [
120 :     nrrdVar, CL.mkVar nrrdType, mkInt nDims, sizesV
121 :     ]),
122 :     CL.#!=,
123 :     CL.mkInt 0),
124 :     (* then *)
125 :     CL.mkBlock[
126 :     CL.mkAssign(CL.mkIndirect(wrldV, "err"),
127 :     CL.mkApply("biffGetDone", [NRRD])),
128 :     CL.mkReturn(SOME(CL.mkVar "true"))
129 :     ]
130 :     (* endif*))
131 : jhr 1707
132 : jhr 1708 (* create the body of an output function for dynamic-size outputs. The structure of the
133 :     * function body is:
134 :     *
135 :     * declarations
136 : jhr 1722 * compute sizes array for nLengths
137 :     * allocate nrrd for nLengths
138 :     * compute sizes array for nData
139 :     * allocate nrrd for nData
140 : jhr 1708 * copy data from strands to nrrd
141 :     *)
142 :     fun genDynOutput (tgt, nAxes, ty, name) = let
143 :     val (elemCTy, nrrdType, dims) = infoOf (tgt, ty)
144 :     val nDims = List.length dims
145 :     val nElems = List.foldl Int.* 1 dims
146 :     val (isArray, nAxes) = (case nAxes of NONE => (false, 1) | SOME n => (true, n))
147 :     (* declarations *)
148 : jhr 1715 val sizesDecl = CL.mkDecl(CL.T_Array(sizeTy, SOME(nDims+nAxes)), "sizes", NONE)
149 : jhr 1708 (* count number of elements (and stable strands) *)
150 :     val countElems = let
151 : jhr 1715 val nElemsInit = CL.mkDeclInit(CL.uint32, "numElems", CL.mkInt 0)
152 : jhr 1708 val cntElems = CL.S_Exp(CL.mkAssignOp(numElemsV, CL.+=, seqLength(stateVar name)))
153 :     in
154 :     if isArray
155 :     then [
156 :     CL.mkComment["count number of elements"],
157 :     nElemsInit, forStrands cntElems
158 :     ]
159 :     else [
160 : jhr 1710 CL.mkComment["count number of output elements and stable strands"],
161 : jhr 1715 CL.mkDeclInit(CL.uint32, "numStable", CL.mkInt 0),
162 :     nElemsInit,
163 : jhr 1708 forStrands(ifStable(CL.mkBlock[cntElems, CL.S_Exp(CL.mkPostOp(numStableV, CL.^++))]))
164 :     ]
165 :     end
166 : jhr 1722 (* generate code to allocate the nLengths nrrd *)
167 : jhr 1708 val lengthsNrrd = let
168 : jhr 1722 val dimSizes = setSizes(0, CL.mkInt 2) (* nLengths is 2-element vector *)
169 : jhr 1708 in
170 : jhr 1722 CL.mkComment["allocate nLengths nrrd"] ::
171 : jhr 1709 (if isArray
172 : jhr 1708 then dimSizes ::
173 :     List.tabulate (nAxes, fn i =>
174 : jhr 1718 setSizes(i+1, CL.mkSubscript(CL.mkIndirect(wrldV, "size"), mkInt(nAxes-i-1)))) @
175 : jhr 1722 [maybeAlloc (nLengthsV, "nrrdTypeInt", nAxes+1)]
176 : jhr 1708 else [
177 : jhr 1709 dimSizes, setSizes(nDims, numStableV),
178 : jhr 1722 maybeAlloc (nLengthsV, "nrrdTypeInt", 2)
179 : jhr 1709 ])
180 : jhr 1708 end
181 : jhr 1709 (* generate code to allocate the data nrrd *)
182 :     val dataNrrd = let
183 :     val dimSizes = mapi (fn (i, d) => setSizes(i, mkInt d)) dims
184 :     val sizes = setSizes(nDims, numElemsV)
185 :     in
186 : jhr 1722 CL.mkComment["allocate nData nrrd"] ::
187 : jhr 1709 dimSizes @ [
188 :     sizes,
189 : jhr 1722 maybeAlloc (nDataV, nrrdType, nDims+1)
190 : jhr 1709 ]
191 :     end
192 : jhr 1722 (* generate the nLengths copy code *)
193 : jhr 1709 val copyLengths = let
194 : jhr 1715 val pInit = CL.mkDeclInit(CL.T_Ptr CL.uint32, "ip",
195 : jhr 1722 CL.mkCast(CL.T_Ptr(CL.uint32), CL.mkIndirect(nLengthsV, "data")))
196 : jhr 1715 val offsetDecl = CL.mkDeclInit(CL.uint32, "offset", CL.mkInt 0)
197 : jhr 1710 val copyBlk = CL.mkBlock[
198 : jhr 1715 CL.mkDeclInit(CL.uint32, "n", seqLength(stateVar name)),
199 :     CL.mkAssign(CL.mkUnOp(CL.%*, CL.mkPostOp(ipV, CL.^++)), offsetV),
200 :     CL.mkAssign(CL.mkUnOp(CL.%*, CL.mkPostOp(ipV, CL.^++)), nV),
201 : jhr 1710 CL.S_Exp(CL.mkAssignOp(offsetV, CL.+=, nV))
202 :     ]
203 :     val copyStm = if isArray
204 :     then copyBlk
205 :     else ifStable copyBlk
206 : jhr 1709 in
207 : jhr 1722 [CL.mkComment["initialize nLengths nrrd"], pInit, offsetDecl, forStrands copyStm]
208 : jhr 1709 end
209 : jhr 1722 (* generate the nData copy code *)
210 : jhr 1709 val copyData = let
211 : jhr 1715 val pInit = CL.mkDeclInit(CL.charPtr, "cp",
212 : jhr 1722 CL.mkCast(CL.charPtr, CL.mkIndirect(nDataV, "data")))
213 : jhr 1715 val copyStm = CL.mkAssign(cpV, seqCopy(
214 :     CL.mkBinOp(mkInt nElems, CL.#*, CL.mkSizeof(elemCTy)), cpV, stateVar name))
215 : jhr 1710 val copyStm = if isArray
216 :     then copyStm
217 :     else ifStable copyStm
218 : jhr 1709 in
219 : jhr 1722 [CL.mkComment["initialize nLengths nrrd"], pInit, forStrands copyStm]
220 : jhr 1709 end
221 : jhr 1708 (* the function body *)
222 :     val stms =
223 : jhr 1715 sizesDecl ::
224 : jhr 1708 countElems @
225 :     lengthsNrrd @
226 :     dataNrrd @
227 :     copyLengths @
228 :     copyData @
229 :     [CL.mkReturn(SOME(CL.mkVar "false"))]
230 :     in
231 : jhr 1722 ([CL.PARAM([], nrrdPtrTy, "nLengths"), CL.PARAM([], nrrdPtrTy, "nData")], CL.mkBlock stms)
232 : jhr 1708 end
233 : jhr 1707
234 :     (* create the body of an output function for fixed-size outputs. The structure of the
235 :     * function body is:
236 :     *
237 :     * declare and compute sizes array
238 : jhr 1722 * allocate nrrd nData
239 : jhr 1707 * copy data from strands to nrrd
240 :     *)
241 :     fun genFixedOutput (tgt, nAxes, ty, name) = let
242 :     val (elemCTy, nrrdType, dims) = infoOf (tgt, ty)
243 :     val nDims = List.length dims
244 :     val nElems = List.foldl Int.* 1 dims
245 :     val (isArray, nAxes) = (case nAxes of NONE => (false, 1) | SOME n => (true, n))
246 :     (* generate the sizes initialization code *)
247 :     val initSizes = let
248 :     val sizesDcl = CL.mkDecl(CL.T_Array(sizeTy, SOME(nDims+nAxes)), "sizes", NONE)
249 :     val dimSizes = sizesDcl :: mapi (fn (i, d) => setSizes(i, mkInt d)) dims
250 :     in
251 :     if isArray
252 :     then dimSizes @
253 :     List.tabulate (nAxes, fn i =>
254 : jhr 1718 setSizes(nDims+i, CL.mkSubscript(CL.mkIndirect(wrldV, "size"), mkInt(nAxes-i-1))))
255 : jhr 1708 else
256 : jhr 1715 CL.mkDeclInit(sizeTy, "numStable", mkInt 0) ::
257 : jhr 1708 forStrands (ifStable(CL.S_Exp(CL.mkPostOp(numStableV, CL.^++)))) ::
258 :     dimSizes @ [setSizes(nDims, numStableV)]
259 : jhr 1707 end
260 :     (* generate the copy code *)
261 :     val copyCode = let
262 : jhr 1715 val pDecl = CL.mkDeclInit(CL.charPtr, "cp",
263 : jhr 1722 CL.mkCast(CL.charPtr, CL.mkIndirect(nDataV, "data")))
264 : jhr 1711 val copyBlk = CL.mkBlock[
265 : jhr 1707 CL.mkCall("memcpy", [
266 : jhr 1715 cpV,
267 : jhr 1708 CL.mkUnOp(CL.%&, stateVar name),
268 : jhr 1734 CL.mkBinOp(mkInt nElems, CL.#*, CL.mkSizeof elemCTy)
269 : jhr 1707 ]),
270 : jhr 1734 CL.mkExpStm(CL.mkAssignOp(cpV, CL.+=,
271 :     CL.mkBinOp(mkInt nElems, CL.#*, CL.mkSizeof elemCTy)))
272 : jhr 1707 ]
273 : jhr 1711 val copyStm = if isArray
274 :     then copyBlk
275 :     else ifStable copyBlk
276 : jhr 1707 in
277 : jhr 1711 [pDecl, forStrands copyStm]
278 : jhr 1707 end
279 :     (* the function body *)
280 :     val stms =
281 :     CL.mkComment["Compute sizes of nrrd file"] ::
282 :     initSizes @
283 : jhr 1722 CL.mkComment["Allocate nData nrrd"] ::
284 :     maybeAlloc (nDataV, nrrdType, nDims+nAxes) ::
285 : jhr 1707 CL.mkComment["copy data to output nrrd"] ::
286 :     copyCode @
287 : jhr 1708 [CL.mkReturn(SOME(CL.mkVar "false"))]
288 : jhr 1707 in
289 : jhr 1722 ([CL.PARAM([], nrrdPtrTy, "nData")], CL.mkBlock stms)
290 : jhr 1707 end
291 :    
292 :     fun gen (tgt : TargetUtil.target_desc, nAxes) (ty, name) = let
293 :     val funcName = String.concat[#namespace tgt, "Get_", name]
294 :     val wrldPtr = CL.T_Ptr(CL.T_Named(#namespace tgt ^ "World_t"))
295 :     fun mkFunc (params, body) =
296 :     CL.D_Func([], CL.boolTy, funcName, CL.PARAM([], wrldPtr, "wrld")::params, body)
297 :     in
298 :     case ty
299 :     of Ty.DynSeqTy ty' => mkFunc (genDynOutput(tgt, nAxes, ty', name))
300 :     | _ => mkFunc (genFixedOutput(tgt, nAxes, ty, name))
301 :     (* end case *)
302 :     end
303 :    
304 :     end

root@smlnj-gforge.cs.uchicago.edu
ViewVC Help
Powered by ViewVC 1.0.0