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

SCM Repository

[diderot] Annotation of /branches/vis15/src/compiler/target-cpu/gen-strand.sml
ViewVC logotype

Annotation of /branches/vis15/src/compiler/target-cpu/gen-strand.sml

Parent Directory Parent Directory | Revision Log Revision Log


Revision 5215 - (view) (download)

1 : jhr 3864 (* gen-strand.sml
2 :     *
3 : jhr 4500 * Code generation for strands. If the program does not have strand communication,
4 :     * then we represent a strand S's state using a single struct type (S_strand).
5 :     * If there is communication, then define three struct types:
6 : jhr 3864 *
7 : jhr 4500 * S_shared, which contains those state variables that are both varying and shared
8 :     *
9 :     * S_local, which contains the state variables not in S_shared, and
10 :     *
11 :     * S_strand, which is a wrapper that contains one instance of S_local and two
12 :     * of S_shared.
13 :     *
14 : jhr 3864 * This code is part of the Diderot Project (http://diderot-language.cs.uchicago.edu)
15 :     *
16 :     * COPYRIGHT (c) 2016 The University of Chicago
17 :     * All rights reserved.
18 :     *)
19 :    
20 :     structure GenStrand : sig
21 :    
22 : jhr 3918 val gen : CodeGenEnv.t * TreeIR.strand -> {
23 : jhr 4500 structDefs : CLang.decl list, (* representation of a strand's state *)
24 :     methods : CLang.decl list (* implementation of a strand's methods *)
25 : jhr 4317 }
26 : jhr 3864
27 : jhr 5042 (* utility function for collecting together the extra parameters needed for a strand
28 :     * method.
29 :     *)
30 :     val methodParams : {
31 : jhr 5215 world : 'a -> 'b, (* make the world parameter *)
32 :     wcache : 'a -> 'b, (* make the worker_cache parameter *)
33 :     globals : 'a -> 'b (* make the globals parameter *)
34 :     } -> TargetSpec.t -> {
35 :     cxt : 'a, (* context information used to make parameters *)
36 :     needWorker : bool, (* true if the method needs the worker_cache *)
37 :     needsW : bool, (* true if the method needs the world pointer *)
38 :     hasG : bool (* true if the method refers to globals *)
39 :     } -> 'b list
40 : jhr 5042
41 : jhr 3864 end = struct
42 :    
43 :     structure IR = TreeIR
44 : jhr 3924 structure SV = TreeStateVar
45 : jhr 3864 structure CL = CLang
46 : jhr 3908 structure RN = CxxNames
47 :     structure Env = CodeGenEnv
48 : jhr 5042 structure TSpec = TargetSpec
49 : jhr 3864
50 : jhr 3917 val strandStatusTy = CL.T_Named "diderot::strand_status"
51 :    
52 : jhr 5042 fun methodParams {world, wcache, globals} spec {cxt, needWorker, needsW, hasG} = let
53 : jhr 5215 val params = if hasG then [globals cxt] else []
54 :     val params = if needWorker andalso TSpec.isParallel spec andalso TSpec.indirectState spec
55 : jhr 5042 then wcache cxt :: params
56 :     else params
57 : jhr 5215 val params = if needsW then world cxt :: params else params
58 :     in
59 :     params
60 :     end
61 : jhr 5042
62 : jhr 4516 (* generate the `pos` method for the strand state *)
63 :     fun genPosMethod (env, substruct, posV) = let
64 : jhr 5215 val realTy = RawTypes.toString(Env.rawRealTy env)
65 :     fun mkDcl s = CL.D_Verbatim[concat s]
66 :     val (addrof, select) = (case SV.ty posV
67 :     of TreeTypes.VecTy(1, 1) => ("&", "sv_pos")
68 :     | TreeTypes.TensorTy[d] => ("", "sv_pos.base()")
69 :     (* end case *))
70 :     in
71 : jhr 4357 (* FIXME: once CLang supports "const" functions, we should switch to building AST *)
72 : jhr 5215 mkDcl [
73 :     "const ", realTy, " *pos (uint32_t inIdx) const { return ",
74 :     addrof, "this->", substruct, select, "; }"
75 :     ]
76 :     end
77 : jhr 4357
78 : jhr 4500 (* is a state variable the special "pos" variable? *)
79 : jhr 5042 fun isPosVar x = (SV.name x = "pos")
80 : jhr 4500
81 : jhr 3917 (* generate the strand-state struct declaration *)
82 : jhr 4500 fun genStrandStructs (env, strandName, state) = let
83 : jhr 4357 fun mkField sv = CL.D_Var([], TreeToCxx.trType(env, SV.ty sv), [], SV.qname sv, NONE)
84 : jhr 5215 fun mkStruct (name, svs, meths) = CL.D_ClassDef{
85 :     name = name,
86 :     args = NONE, from = NONE,
87 :     public = List.foldr (fn (sv, membs) => mkField sv :: membs) meths svs,
88 :     protected = [],
89 :     private = []
90 :     }
91 :     val structName = RN.strandTyName strandName
92 :     val dualState = TargetSpec.dualState(Env.target env)
93 :     fun mkPosMeth () = if #hasCom(Env.target env)
94 :     then (case List.find isPosVar state
95 :     of SOME sv => if not dualState
96 :     then [genPosMethod (env, "", sv)]
97 :     else if SV.inSharedStruct sv
98 :     then [genPosMethod (env, "_shared[inIdx].", sv)]
99 :     else [genPosMethod (env, "_local.", sv)]
100 :     | NONE => raise Fail "impossible: missing \"pos\" state variable"
101 :     (* end case *))
102 :     else []
103 :     in
104 :     if dualState
105 :     then let
106 : jhr 4500 (* QUESTION: should we special-case the situations where either sharedSVs or localSVs is empty? *)
107 : jhr 5215 val (sharedSVs, localSVs) = List.partition SV.inSharedStruct state
108 :     val localName = RN.localTyName strandName
109 :     val localStruct = mkStruct (localName, localSVs, [])
110 :     val sharedName = RN.sharedTyName strandName
111 :     val sharedStruct = mkStruct (sharedName, sharedSVs, [])
112 :     val strandStruct = CL.D_ClassDef{
113 :     name = structName,
114 :     args = NONE, from = NONE,
115 :     public =
116 :     CL.D_Var([], CL.T_Named localName, [], "_local", NONE) ::
117 :     CL.D_Var([], CL.T_Array(CL.T_Named sharedName, SOME 2), [], "_shared", NONE) ::
118 :     mkPosMeth(),
119 :     protected = [],
120 :     private = []
121 :     }
122 : jhr 4500
123 : jhr 5215 in
124 :     [localStruct, sharedStruct, strandStruct]
125 :     end
126 :     else [mkStruct (structName, state, mkPosMeth())]
127 : jhr 4317 end
128 : jhr 3917
129 : jhr 5042 fun mkParams {spec, needWorker, needsW, hasG} = methodParams {
130 : jhr 5215 world = fn _ => RN.worldParam,
131 :     wcache = fn _ => RN.workerParam,
132 :     globals = fn _ => RN.globalsParam
133 :     } spec {
134 :     cxt = (), needWorker = needWorker, needsW = needsW, hasG = hasG
135 :     }
136 : jhr 5042
137 : jhr 3866 (* generate the strand-state initialization code. The variables are the strand
138 :     * parameters.
139 : jhr 4547 * NOTE: the calling convention generated here must match that used in GenWorld.genCreateFun
140 :     * and genNew below.
141 : jhr 3866 *)
142 : jhr 4547 fun genStateInit (env, strandName, stateParams, params, def) = let
143 : jhr 4317 val IR.Method{needsW, hasG, body} = def
144 :     val fName = strandName ^ "_init"
145 :     val (env, params) = List.foldr
146 :     (fn (x, (env, ps)) => let
147 :     val (env, p) = TreeToCxx.trParam(env, x)
148 :     in
149 :     (env, p::ps)
150 :     end)
151 :     (env, []) params
152 : jhr 5215 val params = mkParams {
153 :     spec = Env.target env, needWorker = false, needsW = needsW, hasG = hasG
154 :     } @ stateParams @ params
155 : jhr 4317 val body = TreeToCxx.trBlock (env, body)
156 :     in
157 :     CL.D_Func(["static"], CL.voidTy, [], fName, params, body)
158 :     end
159 : jhr 3866
160 : jhr 4505 (* generate the function for dynamically creating new strands (if needed) *)
161 :     fun genNew (env, strandName, strandPtrTy, params, initDef) = if #hasNew(Env.target env)
162 : jhr 5215 then let
163 :     val spec = Env.target env
164 :     val IR.Method{needsW, hasG, ...} = initDef
165 :     val fName = strandName ^ "_new"
166 :     val params' = RN.worldParam :: List.map
167 :     (fn x => CL.PARAM([], TreeToCxx.trType(env, TreeVar.ty x), TreeVar.name x))
168 :     params
169 :     (* parallel targets with indirect strands need the worker cache to implement new/die *)
170 :     val params' = if TargetSpec.isParallel spec andalso TargetSpec.indirectState spec
171 :     then RN.workerParam :: params'
172 :     else params'
173 : jhr 4934 (* access to strand states *)
174 : jhr 4935 val strandsDispatch = if TargetSpec.isParallel spec
175 :     then (fn (f, args) => CL.mkIndirectDispatch(CL.mkVar RN.workerVar, f, args))
176 :     else let val strands = RN.strandArray env
177 : jhr 5215 in
178 :     fn (f, args) => CL.mkDispatch(strands, f, args)
179 :     end
180 :     (* allocate new strand *)
181 :     val allocStm = CL.mkDeclInit(CL.autoTy, "ix",
182 :     strandsDispatch("new_strand", []))
183 :     (* arguments to init function *)
184 :     val args = List.map (fn x => CL.mkVar(TreeVar.name x)) params
185 :     (* extend args with strand *)
186 :     val args = if TargetSpec.dualState spec
187 :     then strandsDispatch("new_local_state", [CL.mkVar "ix"])
188 :     :: strandsDispatch("new_out_state", [CL.mkVar "ix"])
189 : jhr 4934 :: args
190 : jhr 5215 else strandsDispatch("new_strand_state", [CL.mkVar "ix"])
191 :     :: args
192 :     (* extend args globals (if necessary) *)
193 :     val args = if hasG
194 : jhr 4505 then CL.mkIndirect(CL.mkVar RN.worldVar, "_globals") :: args
195 :     else args
196 : jhr 5215 (* extend args and params with the world (if necessary) *)
197 :     val args = if needsW
198 :     then CL.mkVar RN.worldVar :: args
199 :     else args
200 :     (* initialize new strand *)
201 :     val initStm = CL.mkCall(strandName ^ "_init", args)
202 :     in [
203 :     CL.D_Func(["static"], CL.voidTy, [], fName, params', CL.mkBlock [allocStm, initStm])
204 :     ] end
205 :     else []
206 : jhr 4505
207 : jhr 3864 (* generate a function definition for a strand method *)
208 : jhr 5042 fun genMethodDef (env, strandName, stateParams, methTy, methName, needsWorker, needsWrld, usesGlobs, body) =
209 : jhr 4317 let
210 : jhr 5215 val spec = Env.target env
211 : jhr 4317 val fName = concat[strandName, "_", methName]
212 : jhr 5215 val params = mkParams {
213 :     spec = Env.target env, needWorker = needsWorker, needsW = needsWrld, hasG = usesGlobs
214 :     } @ stateParams
215 : jhr 4317 in
216 :     CL.D_Func(["static"], methTy, [], fName, params, body)
217 :     end
218 : jhr 3864
219 : jhr 3924 (* generate a function definition for a strand method *)
220 : jhr 4988 fun genMethod (env, strandName, stateParams, methTy, methName, needsWorker, IR.Method{needsW, hasG, body}) =
221 : jhr 4317 genMethodDef (
222 : jhr 4547 env, strandName, stateParams, methTy, methName,
223 : jhr 4988 needsWorker, needsW, hasG, TreeToCxx.trBlock (env, body))
224 : jhr 3924
225 : jhr 4500 fun genStartMethod (_, _, _, NONE) = []
226 : jhr 4547 | genStartMethod (env, strandName, stateParams, SOME meth) =
227 : jhr 4988 [genMethod (env, strandName, stateParams, strandStatusTy, "start", true, meth)]
228 : jhr 3864
229 : jhr 4547 fun genUpdateMethod (env, strandName, stateParams, meth) =
230 : jhr 4988 genMethod (env, strandName, stateParams, strandStatusTy, "update", true, meth)
231 : jhr 3864
232 : jhr 4387 fun genStabilizeMethod (_, _, _, NONE) = []
233 : jhr 4547 | genStabilizeMethod (env, strandName, stateParams, SOME meth) =
234 : jhr 4988 [genMethod (env, strandName, stateParams, CL.voidTy, "stabilize", false, meth)]
235 : jhr 3864
236 : jhr 3908 fun gen (env, strand) = let
237 : jhr 4500 val IR.Strand{name, params, state, stateInit, startM, updateM, stabilizeM, ...} = strand
238 : jhr 4317 val name = Atom.toString name
239 : jhr 4373 val strandPtrTy = CL.T_Ptr(RN.strandTy name)
240 : jhr 5215 val (initParams, updateParams) = if TargetSpec.dualState(Env.target env)
241 :     then let
242 :     fun mkParam (ty, x) = CL.PARAM([], CL.T_Ptr(CL.T_Named ty), x)
243 :     val localParam = mkParam(RN.localTyName name, RN.selfLocalVar)
244 :     val inParam = mkParam(RN.sharedTyName name, RN.selfInVar)
245 :     val outParam = mkParam(RN.sharedTyName name, RN.selfOutVar)
246 :     in
247 :     ([localParam, outParam], [localParam, inParam, outParam])
248 :     end
249 :     else let
250 :     val params = [CL.PARAM([], CL.T_Ptr(RN.strandTy name), RN.selfVar)]
251 :     in
252 :     (params, params)
253 :     end
254 : jhr 4317 in {
255 : jhr 4500 structDefs = genStrandStructs (env, name, state),
256 : jhr 4547 methods = genStateInit (env, name, initParams, params, stateInit) ::
257 : jhr 5215 genNew (env, name, strandPtrTy, params, stateInit) @
258 : jhr 4547 genStartMethod (env, name, updateParams, startM) @
259 :     genUpdateMethod (env, name, updateParams, updateM) ::
260 :     genStabilizeMethod (env, name, updateParams, stabilizeM)
261 : jhr 4317 } end
262 : jhr 3864
263 :     end

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