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.sml
ViewVC logotype

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 4797 - (view) (download)

1 : jhr 3902 (* gen.sml
2 :     *
3 :     * Code generation for the sequential and parallel targets.
4 :     *
5 :     * COPYRIGHT (c) 2016 The Diderot Project (http://diderot-language.cs.uchicago.edu)
6 :     * All rights reserved.
7 :     *)
8 :    
9 :     structure Gen : sig
10 :    
11 :     val exec : TargetSpec.t * TreeIR.program -> unit
12 :    
13 :     val library : TargetSpec.t * TreeIR.program -> unit
14 :    
15 :     end = struct
16 :    
17 :     structure IR = TreeIR
18 : jhr 3924 structure GV = TreeGlobalVar
19 : jhr 3902 structure CL = CLang
20 : jhr 3905 structure Env = CodeGenEnv
21 :     structure Out = CodeOutput
22 : jhr 3906 structure RN = CxxNames
23 : jhr 4407 structure Frags = CPUFragments
24 : jhr 3902
25 : jhr 3905 val openCxxOut = Out.openOut {ext = "cxx", ppDecl = PrintAsCxx.output}
26 :    
27 : jhr 3908 fun mkEnv spec = if TargetSpec.dualState spec
28 : jhr 4317 then Env.new {
29 :     world = RN.worldVar,
30 :     global = RN.globalsVar,
31 : jhr 4500 selfLocal = RN.selfLocalVar,
32 : jhr 4317 selfIn = RN.selfInVar,
33 :     selfOut = RN.selfOutVar,
34 :     spec = spec
35 :     }
36 :     else Env.new {
37 :     world = RN.worldVar,
38 :     global = RN.globalsVar,
39 : jhr 4500 selfLocal = RN.selfVar,
40 : jhr 4317 selfIn = RN.selfVar,
41 :     selfOut = RN.selfVar,
42 :     spec = spec
43 :     }
44 : jhr 3908
45 : jhr 3905 (* create the target-specific substitution list *)
46 : jhr 4045 fun mkSubs (spec, strand, create) = let
47 : jhr 4500 val IR.Strand{name, stateInit, startM, updateM, stabilizeM, ...} = strand
48 :     fun mkMethodParams (name, NONE) = (name, "")
49 :     | mkMethodParams (name, SOME(IR.Method{needsW, hasG, ...})) = let
50 :     val value = if needsW
51 :     then "world *wrld, "
52 :     else ""
53 :     val value = if hasG then value ^ "globals *glob, " else value
54 :     in
55 :     (name, value)
56 :     end
57 : jhr 4501 fun mkMethodArgs (_, name, NONE) = (name, "")
58 :     | mkMethodArgs (inWrld, name, SOME(IR.Method{needsW, hasG, ...})) = let
59 :     val value = if not needsW
60 : jhr 4628 then ""
61 :     else if not inWrld orelse TargetSpec.isParallel spec
62 :     then "wrld, "
63 :     else "this, "
64 : jhr 4317 val value = if hasG then value ^ "glob, " else value
65 :     in
66 :     (name, value)
67 :     end
68 :     in [
69 :     ("CFILE", OS.Path.joinBaseExt{base= #outBase spec, ext= SOME "c"}),
70 :     ("CXXFILE", OS.Path.joinBaseExt{base= #outBase spec, ext= SOME "cxx"}),
71 :     ("H_FILE", OS.Path.joinBaseExt{base= #outBase spec, ext= SOME "h"}),
72 :     ("PREFIX", #namespace spec),
73 :     ("SRCFILE", #srcFile spec),
74 :     ("PROG_NAME", #outBase spec),
75 :     ("STRAND", Atom.toString name),
76 :     ("STRANDTY", Atom.toString name ^ "_strand"),
77 :     ("IS_GRID", Bool.toString(#isGrid spec)),
78 : jhr 4500 ("NUM_AXES", Int.toString(Option.getOpt(Create.arrayDim create, 1))),
79 : jhr 4369 ("SPATIAL_DIM", Int.toString(Option.getOpt(#spatialDim spec, 0))),
80 : jhr 4317 ("DIDEROTC_CMD", #diderotc spec),
81 :     ("DIDEROTC_ARGV", String.concatWith " " (#argv spec)),
82 :     ("DIDEROTC_VERSION", #version spec),
83 :     ("DIDEROT_FLOAT_PRECISION", TargetSpec.floatPrecisionDef spec),
84 :     ("DIDEROT_INT_PRECISION", TargetSpec.intPrecisionDef spec),
85 :     ("DIDEROT_TARGET", TargetSpec.targetDef spec),
86 :     ("REALTY", if #double spec then "double" else "float"),
87 :     ("INTTY", if #longint spec then "int64_t" else "int32_t"),
88 :     ("BOOLTY", SizeOf.c_bool),
89 : jhr 4501 mkMethodArgs (true, "STATE_INIT_ARGS", SOME stateInit),
90 :     mkMethodParams ("START_PARAMS", startM),
91 :     mkMethodArgs (true, "START_ARGS_IN_WRLD", startM),
92 :     mkMethodArgs (false, "START_ARGS", startM),
93 :     mkMethodParams ("UPDATE_PARAMS", SOME updateM),
94 :     mkMethodArgs (true, "UPDATE_ARGS_IN_WRLD", SOME updateM),
95 :     mkMethodArgs (false, "UPDATE_ARGS", SOME updateM),
96 : jhr 4500 mkMethodParams ("STABILIZE_PARAMS", stabilizeM),
97 : jhr 4501 mkMethodArgs (true, "STABILIZE_ARGS_IN_WRLD", stabilizeM),
98 :     mkMethodArgs (false, "STABILIZE_ARGS", stabilizeM)
99 : jhr 4317 ] end
100 : jhr 3905
101 :     fun condCons (true, x, xs) = x::xs
102 :     | condCons (false, _, xs) = xs
103 :    
104 : jhr 3906 fun verbFrag (spec, parFrag, seqFrag, subs) =
105 : jhr 4317 CL.verbatimDcl [if (TargetSpec.isParallel spec) then parFrag else seqFrag] subs
106 : jhr 3905
107 : jhr 3917 (* generate the struct declaration for the global variables *)
108 : jhr 3918 (* FIXME: what about constants? *)
109 :     fun genGlobalStruct (env, consts, inputs, globals) =
110 : jhr 4317 if #hasGlobals(Env.target env)
111 :     then let
112 :     fun mkField gv = (TreeToCxx.trType(env, GV.ty gv), GV.qname gv)
113 :     val fields = List.map (mkField o Inputs.varOf) inputs
114 :     val fields = fields @ List.map mkField globals
115 :     in
116 :     [CL.D_StructDef(SOME "globals", fields, NONE)]
117 :     end
118 :     else []
119 : jhr 3917
120 : jhr 4547 (* translate function parameters and initialize the environment *)
121 :     fun trParams (spec, params) = List.foldr
122 : jhr 4628 (fn (x, (env, ps)) => let
123 :     val (env, p) = TreeToCxx.trParam(env, x)
124 :     in
125 :     (env, p::ps)
126 :     end)
127 :     (Env.empty spec, []) params
128 : jhr 4547
129 : jhr 4174 (* generate code for a user-defined function *)
130 :     fun genFunc spec (IR.Func{name, params, body}) = let
131 : jhr 4317 val (resTy, _) = TreeFunc.ty name
132 : jhr 4547 val (env, params) = trParams (spec, params)
133 : jhr 4317 val (env, params) = if TreeFunc.hasGlobals name
134 :     then (
135 :     Env.insert(env, PseudoVars.global, RN.globalsVar),
136 :     CL.PARAM([], RN.globalPtrTy, RN.globalsVar) :: params
137 :     )
138 :     else (env, params)
139 :     val (env, params) = if TreeFunc.needsWorld name
140 :     then (
141 :     Env.insert(env, PseudoVars.world, RN.worldVar),
142 :     CL.PARAM([], RN.worldPtrTy, RN.worldVar) :: params
143 :     )
144 :     else (env, params)
145 :     in
146 :     CL.D_Func([], TreeToCxx.trType(env, resTy), [], TreeFunc.qname name, params,
147 :     TreeToCxx.trBlock (env, body))
148 :     end
149 : jhr 4174
150 : jhr 4131 (* QUESTION: should init_globals be a member of the world struct? *)
151 : jhr 4168 fun genInitGlobals (env, IR.Block{locals, body}) = let
152 : jhr 4317 (* the init_globals function should return false on success *)
153 :     val body = IR.Block{
154 :     locals=locals,
155 :     body=body@[IR.S_Return(IR.E_Lit(Literal.Bool false))]
156 :     }
157 :     in
158 :     CL.D_Func(["static"], CL.boolTy, [], "init_globals",
159 :     [RN.worldParam],
160 : jhr 4364 GenUtil.genBodyWithGlobPtr (env, body))
161 : jhr 4317 end
162 : jhr 3931
163 : jhr 4500 (* specialize the fragments that implement the run and run_start_methods world methods *)
164 : jhr 4407 fun runFrag (spec, subs) = let
165 : jhr 4500 val code = if TargetSpec.noBSP spec
166 : jhr 4407 then [verbFrag (spec, Frags.parRunNoBSP, Frags.seqRunNoBSP, subs)]
167 :     else [verbFrag (spec, Frags.parRun, Frags.seqRun, subs)]
168 : jhr 4500 in
169 :     if #hasStartMeth spec
170 :     then verbFrag (spec, Frags.parRunStartMethods, Frags.seqRunStartMethods, subs) :: code
171 :     else code
172 :     end
173 : jhr 3917
174 : jhr 3905 fun compile (spec : TargetSpec.t, basename) = let
175 : jhr 4317 (* generate the C compiler flags *)
176 :     val cflags = ["-I" ^ Paths.diderotInclude(), "-I" ^ Paths.teemInclude()]
177 : jhr 4637 val cflags = #simd Paths.cxxFlags :: cflags
178 : jhr 4417 val cflags = condCons (TargetSpec.isParallel spec, #parallel Paths.cxxFlags, cflags)
179 : jhr 4317 val cflags = if #debug spec
180 : jhr 4417 then #debug Paths.cxxFlags :: cflags
181 :     else #ndebug Paths.cxxFlags :: cflags
182 :     val cflags = #base Paths.cxxFlags :: cflags
183 : jhr 4317 in
184 :     RunCC.compile (basename, cflags)
185 :     end
186 : jhr 3905
187 : jhr 3906 fun ldFlags (spec : TargetSpec.t) = if #exec spec
188 : jhr 4317 then let
189 : jhr 4417 val extraLibs = condCons (TargetSpec.isParallel spec, #parallel Paths.extraLibs, [])
190 : jhr 4317 val extraLibs = Paths.teemLinkFlags() @ #base Paths.extraLibs :: extraLibs
191 :     val rtLib = TargetSpec.runtimeLibName spec
192 :     in
193 : jhr 4417 condCons (TargetSpec.isParallel spec, #parallel Paths.cxxFlags, rtLib :: extraLibs)
194 : jhr 4317 end
195 :     else [TargetSpec.runtimeLibName spec]
196 : jhr 3905
197 : jhr 4367 (* generate defines that control specialization of the code for various features (e.g.,
198 :     * parallelism, global updates, ...
199 :     *)
200 :     fun outputDefines (outS, spec, substitutions) = let
201 : jhr 4369 val ppDecl = Out.decl outS
202 : jhr 4387 fun pp (true, dcl) = ppDecl (CL.D_Verbatim ["#define " ^ dcl])
203 : jhr 4369 | pp _ = ()
204 :     in
205 : jhr 4661 pp (#exec spec andalso #snapshot spec, "DIDEROT_EXEC_SNAPSHOT");
206 : jhr 4628 pp (#hasStartMeth spec, "DIDEROT_HAS_START_METHOD");
207 : jhr 4500 pp (#hasStabilizeMeth spec, "DIDEROT_HAS_STABILIZE_METHOD");
208 : jhr 4387 pp (TargetSpec.dualState spec, "DIDEROT_DUAL_STATE");
209 : jhr 4451 pp (TargetSpec.indirectState spec, "DIDEROT_INDIRECT_STATE");
210 : jhr 4387 pp (not(#hasGlobals spec), "DIDEROT_NO_GLOBALS");
211 :     pp (not(#hasInputs spec), "DIDEROT_NO_INPUTS");
212 : jhr 4628 pp (#hasDie spec orelse #hasKillAll spec, "DIDEROT_HAS_STRAND_DIE");
213 : jhr 4500 pp (#hasNew spec, "DIDEROT_HAS_STRAND_NEW");
214 : jhr 4753 pp (#isGrid spec, "DIDEROT_STRAND_ARRAY");
215 : jhr 4387 pp (#hasCom spec, "DIDEROT_HAS_STRAND_COMMUNICATION");
216 : jhr 4589 pp (not(#useKDTree spec), "DIDEROT_NO_SPACE_PARTITION");
217 : jhr 4500 pp (#hasGlobalStart spec, "DIDEROT_HAS_GLOBAL_START");
218 : jhr 4387 pp (#hasGlobalUpdate spec, "DIDEROT_HAS_GLOBAL_UPDATE");
219 : jhr 4753 pp (TargetSpec.killAll spec, "DIDEROT_HAS_KILL_ALL");
220 : jhr 4500 pp (#hasStabilizeAll spec, "DIDEROT_HAS_STABILIZE_ALL");
221 : jhr 4387 pp (#hasReduce spec, "DIDEROT_HAS_MAPREDUCE")
222 : jhr 4369 end
223 : jhr 4367
224 : jhr 4500 (* include the appropriate definition of the strand_array type based on the target *)
225 :     fun strandArrayDcl spec = (
226 :     case (TargetSpec.isParallel spec, TargetSpec.dualState spec, TargetSpec.indirectState spec)
227 : jhr 4766 of (true, false, false) => CPUFragments.parSArrayDir
228 :     | (true, _, _) => raise Fail "FIXME: parallel strand_array"
229 : jhr 4500 | (_, false, false) => CPUFragments.seqSArrayDir
230 :     | (_, true, false) => CPUFragments.seqSArrayDualDir
231 :     | (_, false, true) => CPUFragments.seqSArrayInd
232 :     | (_, true, true) => CPUFragments.seqSArrayDualInd
233 :     (* end case *))
234 :    
235 : jhr 3912 (* generate source code that is common to both libraries and standalone executables *)
236 : jhr 4500 fun outputSrc (outS, env, spec, prog, strand, outputs, substitutions, genInputCode) = let
237 :     val IR.Program{consts, inputs, globals, funcs, globInit, create, start, update, ...} = prog
238 : jhr 4317 val IR.Strand{name=strandName, ...} = strand
239 : jhr 4500 val dim = Create.arrayDim create
240 : jhr 4317 val ppDecl = Out.decl outS
241 : jhr 4500 val {structDefs, methods} = GenStrand.gen (env, strand)
242 : jhr 4317 in
243 :     List.app ppDecl (genGlobalStruct (env, consts, inputs, globals));
244 : jhr 4500 List.app ppDecl structDefs;
245 :     ppDecl (CL.verbatimDcl [strandArrayDcl spec] substitutions);
246 : jhr 4349 ppDecl (GenWorld.genStruct(env, strandName, Option.getOpt(dim, 1)));
247 : jhr 4317 List.app ppDecl (genInputCode());
248 :     List.app (ppDecl o genFunc spec) funcs;
249 :     if #hasGlobalInit spec
250 :     then ppDecl (genInitGlobals (env, globInit))
251 :     else ();
252 :     List.app ppDecl methods;
253 :     List.app ppDecl (GenOutputs.gen (env, dim, outputs));
254 : jhr 4407 ppDecl (CL.verbatimDcl [Frags.worldMethods] substitutions);
255 :     ppDecl (GenWorld.genCreateFun (env, globInit, strand, create));
256 :     List.app ppDecl (runFrag (spec, substitutions));
257 : jhr 4500 Option.app (fn blk => ppDecl (GenGlobalUpdate.gen (env, "start", blk))) start;
258 : jhr 4386 Option.app (fn blk => ppDecl (GenGlobalUpdate.gen (env, "update", blk))) update
259 : jhr 4317 end
260 : jhr 3931
261 : jhr 3990 fun exec (spec : TargetSpec.t, prog) = let
262 : jhr 4317 val IR.Program{inputs, strand, create, ...} = prog
263 :     val env = mkEnv spec
264 :     val baseName = OS.Path.joinDirFile{dir = #outDir spec, file = #outBase spec}
265 :     val substitutions = mkSubs (spec, strand, create)
266 :     (* output to C++ file *)
267 :     val outS = openCxxOut baseName
268 :     val ppDecl = Out.decl outS
269 :     val fragment = Out.fragment substitutions outS
270 : jhr 4369 val {preWorld, postWorld} = GenTysAndOps.gen (env, CollectInfo.collect prog)
271 : jhr 4500 val outputs = OutputUtil.gatherOutputs (spec, prog)
272 : jhr 4317 in
273 :     ppDecl (CL.verbatimDcl [CxxFragments.execHead] substitutions);
274 : jhr 4369 outputDefines (outS, spec, substitutions);
275 : jhr 4367 ppDecl (CL.verbatimDcl [CxxFragments.execIncl] substitutions);
276 : jhr 4351 List.app ppDecl preWorld;
277 : jhr 4317 ppDecl (CL.verbatimDcl [CxxFragments.namespaceOpen] substitutions);
278 :     ppDecl (CL.verbatimDcl [CxxFragments.nrrdSaveHelper] substitutions);
279 : jhr 4500 outputSrc (outS, env, spec, prog, strand, outputs, substitutions,
280 : jhr 4317 fn () => (
281 : jhr 4369 postWorld @
282 : jhr 4317 GenInputs.genInputsStruct (env, inputs) @
283 :     GenInputs.genExecInputFuns (env, prog) @
284 : jhr 4500 GenOutputsUtil.genRegisterOutputOpts (env, outputs)));
285 : jhr 4317 ppDecl (CL.verbatimDcl [CxxFragments.namespaceClose] substitutions);
286 :     (* generate main function after closing off the namespace *)
287 : jhr 4407 ppDecl (verbFrag (spec, Frags.parMain, Frags.seqMain, substitutions));
288 : jhr 4317 Out.closeOut outS;
289 :     compile (spec, baseName);
290 :     RunCC.linkExec (baseName, ldFlags spec)
291 :     end
292 : jhr 3990
293 :     fun library (spec : TargetSpec.t, prog) = let
294 : jhr 4317 val IR.Program{inputs, strand, create, ...} = prog
295 :     val env = mkEnv spec
296 :     val baseName = OS.Path.joinDirFile{dir = #outDir spec, file = #outBase spec}
297 :     val substitutions = mkSubs (spec, strand, create)
298 :     (* output to C++ file *)
299 :     val outS = openCxxOut baseName
300 :     val ppDecl = Out.decl outS
301 :     val fragment = Out.fragment substitutions outS
302 :     (* gather the outputs *)
303 : jhr 4500 val outputs = OutputUtil.gatherOutputs (spec, prog)
304 : jhr 4369 val {preWorld, postWorld} = GenTysAndOps.gen (env, CollectInfo.collect prog)
305 : jhr 4317 in
306 :     (* generate the library .h file *)
307 :     GenLibraryInterface.gen {
308 :     subs = substitutions,
309 :     env = env,
310 :     rt = NONE, (* ?? *)
311 :     inputs = inputs,
312 :     outputs = outputs
313 :     };
314 :     ppDecl (CL.verbatimDcl [CxxFragments.libCXXHead] substitutions);
315 : jhr 4369 outputDefines (outS, spec, substitutions);
316 : jhr 4367 ppDecl (CL.verbatimDcl [CxxFragments.libCXXIncl] substitutions);
317 : jhr 4351 List.app ppDecl preWorld;
318 : jhr 4317 ppDecl (CL.verbatimDcl [CxxFragments.namespaceOpen] substitutions);
319 :     ppDecl (CL.verbatimDcl [CxxFragments.nrrdSaveHelper] substitutions);
320 :     List.app ppDecl (GenInputs.genDefinedInpStruct inputs);
321 : jhr 4500 outputSrc (outS, env, spec, prog, strand, outputs, substitutions,
322 : jhr 4351 fn () => (postWorld @ GenInputs.genLibraryInputFuns (env, prog)));
323 : jhr 4317 ppDecl (CL.verbatimDcl [CxxFragments.namespaceClose] substitutions);
324 : jhr 4407 ppDecl (CL.verbatimDcl [Frags.cWrappers] substitutions);
325 : jhr 4317 Out.closeOut outS;
326 :     (* compile and link *)
327 :     compile (spec, baseName);
328 :     RunCC.linkLib (baseName, ldFlags spec)
329 :     end
330 : jhr 3908
331 : jhr 3902 end

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