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

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