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 4369 - (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 3902
24 : jhr 3905 val openCxxOut = Out.openOut {ext = "cxx", ppDecl = PrintAsCxx.output}
25 :    
26 : jhr 3908 fun mkEnv spec = if TargetSpec.dualState spec
27 : jhr 4317 then Env.new {
28 :     world = RN.worldVar,
29 :     global = RN.globalsVar,
30 :     selfIn = RN.selfInVar,
31 :     selfOut = RN.selfOutVar,
32 :     spec = spec
33 :     }
34 :     else Env.new {
35 :     world = RN.worldVar,
36 :     global = RN.globalsVar,
37 :     selfIn = RN.selfVar,
38 :     selfOut = RN.selfVar,
39 :     spec = spec
40 :     }
41 : jhr 3908
42 : jhr 3905 (* create the target-specific substitution list *)
43 : jhr 4045 fun mkSubs (spec, strand, create) = let
44 : jhr 4317 val IR.Strand{name, stateInit, initM, updateM, stabilizeM, ...} = strand
45 :     fun mkMethodArgs (name, NONE) = (name, "")
46 :     | mkMethodArgs (name, SOME(IR.Method{needsW, hasG, ...})) = let
47 :     val value = if needsW
48 :     then if TargetSpec.isParallel spec then "wrld, " else "this, "
49 :     else ""
50 :     val value = if hasG then value ^ "glob, " else value
51 :     in
52 :     (name, value)
53 :     end
54 :     in [
55 :     ("CFILE", OS.Path.joinBaseExt{base= #outBase spec, ext= SOME "c"}),
56 :     ("CXXFILE", OS.Path.joinBaseExt{base= #outBase spec, ext= SOME "cxx"}),
57 :     ("H_FILE", OS.Path.joinBaseExt{base= #outBase spec, ext= SOME "h"}),
58 :     ("PREFIX", #namespace spec),
59 :     ("SRCFILE", #srcFile spec),
60 :     ("PROG_NAME", #outBase spec),
61 :     ("STRAND", Atom.toString name),
62 :     ("STRANDTY", Atom.toString name ^ "_strand"),
63 :     ("IS_GRID", Bool.toString(#isGrid spec)),
64 :     ("NUM_AXES", Int.toString(Option.getOpt(Create.gridDim create, 1))),
65 : jhr 4369 ("SPATIAL_DIM", Int.toString(Option.getOpt(#spatialDim spec, 0))),
66 : jhr 4317 ("DIDEROTC_CMD", #diderotc spec),
67 :     ("DIDEROTC_ARGV", String.concatWith " " (#argv spec)),
68 :     ("DIDEROTC_VERSION", #version spec),
69 :     ("DIDEROT_FLOAT_PRECISION", TargetSpec.floatPrecisionDef spec),
70 :     ("DIDEROT_INT_PRECISION", TargetSpec.intPrecisionDef spec),
71 :     ("DIDEROT_TARGET", TargetSpec.targetDef spec),
72 :     ("REALTY", if #double spec then "double" else "float"),
73 :     ("INTTY", if #longint spec then "int64_t" else "int32_t"),
74 :     ("BOOLTY", SizeOf.c_bool),
75 :     mkMethodArgs ("STATE_INIT_ARGS", SOME stateInit),
76 :     mkMethodArgs ("INITIALLY_ARGS", initM),
77 :     mkMethodArgs ("UPDATE_ARGS", SOME updateM),
78 :     mkMethodArgs ("STABILIZE_ARGS", stabilizeM)
79 :     ] end
80 : jhr 3905
81 :     fun condCons (true, x, xs) = x::xs
82 :     | condCons (false, _, xs) = xs
83 :    
84 : jhr 3906 fun verbFrag (spec, parFrag, seqFrag, subs) =
85 : jhr 4317 CL.verbatimDcl [if (TargetSpec.isParallel spec) then parFrag else seqFrag] subs
86 : jhr 3905
87 : jhr 3917 (* generate the struct declaration for the global variables *)
88 : jhr 3918 (* FIXME: what about constants? *)
89 :     fun genGlobalStruct (env, consts, inputs, globals) =
90 : jhr 4317 if #hasGlobals(Env.target env)
91 :     then let
92 :     fun mkField gv = (TreeToCxx.trType(env, GV.ty gv), GV.qname gv)
93 :     val fields = List.map (mkField o Inputs.varOf) inputs
94 :     val fields = fields @ List.map mkField globals
95 :     in
96 :     [CL.D_StructDef(SOME "globals", fields, NONE)]
97 :     end
98 :     else []
99 : jhr 3917
100 : jhr 4174 (* generate code for a user-defined function *)
101 :     fun genFunc spec (IR.Func{name, params, body}) = let
102 : jhr 4317 val (resTy, _) = TreeFunc.ty name
103 :     val (env, params) = List.foldr
104 :     (fn (x, (env, ps)) => let
105 :     val (env, p) = TreeToCxx.trParam(env, x)
106 :     in
107 :     (env, p::ps)
108 :     end)
109 :     (Env.empty spec, []) params
110 :     val (env, params) = if TreeFunc.hasGlobals name
111 :     then (
112 :     Env.insert(env, PseudoVars.global, RN.globalsVar),
113 :     CL.PARAM([], RN.globalPtrTy, RN.globalsVar) :: params
114 :     )
115 :     else (env, params)
116 :     val (env, params) = if TreeFunc.needsWorld name
117 :     then (
118 :     Env.insert(env, PseudoVars.world, RN.worldVar),
119 :     CL.PARAM([], RN.worldPtrTy, RN.worldVar) :: params
120 :     )
121 :     else (env, params)
122 :     in
123 :     CL.D_Func([], TreeToCxx.trType(env, resTy), [], TreeFunc.qname name, params,
124 :     TreeToCxx.trBlock (env, body))
125 :     end
126 : jhr 4174
127 : jhr 4131 (* QUESTION: should init_globals be a member of the world struct? *)
128 : jhr 4168 fun genInitGlobals (env, IR.Block{locals, body}) = let
129 : jhr 4317 (* the init_globals function should return false on success *)
130 :     val body = IR.Block{
131 :     locals=locals,
132 :     body=body@[IR.S_Return(IR.E_Lit(Literal.Bool false))]
133 :     }
134 :     in
135 :     CL.D_Func(["static"], CL.boolTy, [], "init_globals",
136 :     [RN.worldParam],
137 : jhr 4364 GenUtil.genBodyWithGlobPtr (env, body))
138 : jhr 4317 end
139 : jhr 3931
140 : jhr 4131 (* generate the global initially code, which runs after the initial strands have been
141 :     * created, but before the first super-step.
142 :     *)
143 :     fun genGlobalInitially (env, body) = let
144 : jhr 4317 val env = Env.insert(env, PseudoVars.world, "this")
145 :     in
146 :     CL.D_Func([], CL.voidTy, [], "world::global_initially",
147 :     [],
148 : jhr 4364 GenUtil.genBodyWithGlobPtr (env, body))
149 : jhr 4317 end
150 : jhr 4131
151 : jhr 3917 fun runFrag (spec, subs) = if TargetSpec.noBSP spec
152 : jhr 4317 then verbFrag (spec, CPUFragments.parallelRunNoBSP, CPUFragments.sequentialRunNoBSP, subs)
153 :     else verbFrag (spec, CPUFragments.parallelRun, CPUFragments.sequentialRun, subs)
154 : jhr 3917
155 : jhr 3905 fun compile (spec : TargetSpec.t, basename) = let
156 : jhr 4317 (* generate the C compiler flags *)
157 :     val cflags = ["-I" ^ Paths.diderotInclude(), "-I" ^ Paths.teemInclude()]
158 :     val cflags = condCons (TargetSpec.isParallel spec, #pthread Paths.cxxflags, cflags)
159 :     val cflags = if #debug spec
160 :     then #debug Paths.cxxflags :: cflags
161 :     else #ndebug Paths.cxxflags :: cflags
162 :     val cflags = #base Paths.cxxflags :: cflags
163 :     in
164 :     RunCC.compile (basename, cflags)
165 :     end
166 : jhr 3905
167 : jhr 3906 fun ldFlags (spec : TargetSpec.t) = if #exec spec
168 : jhr 4317 then let
169 :     val extraLibs = condCons (TargetSpec.isParallel spec, #pthread Paths.extraLibs, [])
170 :     val extraLibs = Paths.teemLinkFlags() @ #base Paths.extraLibs :: extraLibs
171 :     val rtLib = TargetSpec.runtimeLibName spec
172 :     in
173 :     condCons (TargetSpec.isParallel spec, #pthread Paths.cxxflags, rtLib :: extraLibs)
174 :     end
175 :     else [TargetSpec.runtimeLibName spec]
176 : jhr 3905
177 : jhr 4367 (* generate defines that control specialization of the code for various features (e.g.,
178 :     * parallelism, global updates, ...
179 :     *)
180 :     fun outputDefines (outS, spec, substitutions) = let
181 : jhr 4369 val ppDecl = Out.decl outS
182 :     fun pp (true, dcl) = ppDecl (CL.D_Verbatim [dcl])
183 :     | pp _ = ()
184 :     in
185 : jhr 4367 if (TargetSpec.isParallel spec)
186 :     then ppDecl (CL.verbatimDcl [CPUFragments.parallelExtras] substitutions)
187 :     else ();
188 :     pp (TargetSpec.dualState spec, "#define DIDEROT_DUAL_STATE\n");
189 :     pp (not(#hasGlobals spec), "#define DIDEROT_NO_GLOBALS\n");
190 :     pp (not(#hasInputs spec), "#define DIDEROT_NO_INPUTS\n");
191 :     pp (#hasCom spec, "#define DIDEROT_HAS_STRAND_COMMUNICATION\n");
192 :     pp (#hasGlobalUpdate spec, "#define DIDEROT_HAS_GLOBAL_UPDATE\n")
193 : jhr 4369 end
194 : jhr 4367
195 : jhr 3912 (* generate source code that is common to both libraries and standalone executables *)
196 : jhr 3917 fun outputSrc (outS, env, spec, prog, strand, substitutions, genInputCode) = let
197 : jhr 4317 val IR.Program{consts, inputs, globals, funcs, globInit, create, init, update, ...} = prog
198 :     val IR.Strand{name=strandName, ...} = strand
199 :     val dim = Create.gridDim create
200 :     val ppDecl = Out.decl outS
201 :     val {structDef, methods} = GenStrand.gen (env, strand)
202 :     val outputs = OutputUtil.gatherOutputs prog
203 :     in
204 :     List.app ppDecl (genGlobalStruct (env, consts, inputs, globals));
205 :     ppDecl structDef;
206 : jhr 4349 ppDecl (GenWorld.genStruct(env, strandName, Option.getOpt(dim, 1)));
207 : jhr 4317 List.app ppDecl (genInputCode());
208 :     List.app (ppDecl o genFunc spec) funcs;
209 :     if #hasGlobalInit spec
210 :     then ppDecl (genInitGlobals (env, globInit))
211 :     else ();
212 :     List.app ppDecl methods;
213 :     List.app ppDecl (GenOutputs.gen (env, dim, outputs));
214 :     ppDecl (CL.verbatimDcl [CPUFragments.worldMethods] substitutions);
215 :     ppDecl (GenWorld.genInitiallyFun (env, globInit, strand, create));
216 :     ppDecl (runFrag (spec, substitutions));
217 :     Option.app (fn blk => ppDecl (genGlobalInitially (env, blk))) init;
218 : jhr 4364 Option.app (fn blk => ppDecl (GenGlobalUpdate.gen (env, blk))) update
219 : jhr 4317 end
220 : jhr 3931
221 : jhr 3990 fun exec (spec : TargetSpec.t, prog) = let
222 : jhr 4317 val IR.Program{inputs, strand, create, ...} = prog
223 :     val env = mkEnv spec
224 :     val baseName = OS.Path.joinDirFile{dir = #outDir spec, file = #outBase spec}
225 :     val substitutions = mkSubs (spec, strand, create)
226 :     (* output to C++ file *)
227 :     val outS = openCxxOut baseName
228 :     val ppDecl = Out.decl outS
229 :     val fragment = Out.fragment substitutions outS
230 : jhr 4369 val {preWorld, postWorld} = GenTysAndOps.gen (env, CollectInfo.collect prog)
231 : jhr 4317 in
232 :     ppDecl (CL.verbatimDcl [CxxFragments.execHead] substitutions);
233 : jhr 4369 outputDefines (outS, spec, substitutions);
234 : jhr 4367 ppDecl (CL.verbatimDcl [CxxFragments.execIncl] substitutions);
235 : jhr 4351 List.app ppDecl preWorld;
236 : jhr 4317 ppDecl (CL.verbatimDcl [CxxFragments.namespaceOpen] substitutions);
237 :     ppDecl (CL.verbatimDcl [CxxFragments.nrrdSaveHelper] substitutions);
238 :     outputSrc (outS, env, spec, prog, strand, substitutions,
239 :     fn () => (
240 : jhr 4369 postWorld @
241 : jhr 4317 GenInputs.genInputsStruct (env, inputs) @
242 :     GenInputs.genExecInputFuns (env, prog) @
243 :     GenOutputsUtil.genRegisterOutputOpts (env, OutputUtil.gatherOutputs prog)));
244 :     ppDecl (CL.verbatimDcl [CxxFragments.namespaceClose] substitutions);
245 :     (* generate main function after closing off the namespace *)
246 :     ppDecl (verbFrag (spec, CPUFragments.parallelMain, CPUFragments.sequentialMain, substitutions));
247 :     Out.closeOut outS;
248 :     compile (spec, baseName);
249 :     RunCC.linkExec (baseName, ldFlags spec)
250 :     end
251 : jhr 3990
252 :     fun library (spec : TargetSpec.t, prog) = let
253 : jhr 4317 val IR.Program{inputs, strand, create, ...} = prog
254 :     val env = mkEnv spec
255 :     val baseName = OS.Path.joinDirFile{dir = #outDir spec, file = #outBase spec}
256 :     val substitutions = mkSubs (spec, strand, create)
257 :     (* output to C++ file *)
258 :     val outS = openCxxOut baseName
259 :     val ppDecl = Out.decl outS
260 :     val fragment = Out.fragment substitutions outS
261 :     (* gather the outputs *)
262 :     val outputs = OutputUtil.gatherOutputs prog
263 : jhr 4369 val {preWorld, postWorld} = GenTysAndOps.gen (env, CollectInfo.collect prog)
264 : jhr 4317 in
265 :     (* generate the library .h file *)
266 :     GenLibraryInterface.gen {
267 :     subs = substitutions,
268 :     env = env,
269 :     rt = NONE, (* ?? *)
270 :     inputs = inputs,
271 :     outputs = outputs
272 :     };
273 :     ppDecl (CL.verbatimDcl [CxxFragments.libCXXHead] substitutions);
274 : jhr 4369 outputDefines (outS, spec, substitutions);
275 : jhr 4367 ppDecl (CL.verbatimDcl [CxxFragments.libCXXIncl] 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 :     List.app ppDecl (GenInputs.genDefinedInpStruct inputs);
280 :     outputSrc (outS, env, spec, prog, strand, substitutions,
281 : jhr 4351 fn () => (postWorld @ GenInputs.genLibraryInputFuns (env, prog)));
282 : jhr 4317 ppDecl (CL.verbatimDcl [CxxFragments.namespaceClose] substitutions);
283 :     ppDecl (CL.verbatimDcl [CPUFragments.cWrappers] substitutions);
284 :     Out.closeOut outS;
285 :     (* compile and link *)
286 :     compile (spec, baseName);
287 :     RunCC.linkLib (baseName, ldFlags spec)
288 :     end
289 : jhr 3908
290 : jhr 3902 end

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