SCM Repository
Annotation of /branches/vis12/src/compiler/c-target/c-target.sml
Parent Directory
|
Revision Log
Revision 1716 - (view) (download)
1 : | jhr | 1115 | (* c-target.sml |
2 : | * | ||
3 : | * COPYRIGHT (c) 2011 The Diderot Project (http://diderot-language.cs.uchicago.edu) | ||
4 : | * All rights reserved. | ||
5 : | *) | ||
6 : | |||
7 : | structure CTarget : TARGET = | ||
8 : | struct | ||
9 : | |||
10 : | structure IL = TreeIL | ||
11 : | structure V = IL.Var | ||
12 : | structure Ty = IL.Ty | ||
13 : | structure CL = CLang | ||
14 : | jhr | 1376 | structure N = CNames |
15 : | jhr | 1115 | |
16 : | jhr | 1716 | type target_desc = TargetUtil.target_desc |
17 : | |||
18 : | jhr | 1640 | (* variable translation *) |
19 : | structure TrVar = | ||
20 : | struct | ||
21 : | type env = CL.typed_var TreeIL.Var.Map.map | ||
22 : | fun lookup (env, x) = (case V.Map.find (env, x) | ||
23 : | of SOME(CL.V(_, x')) => x' | ||
24 : | | NONE => raise Fail(concat["lookup(_, ", V.name x, ")"]) | ||
25 : | (* end case *)) | ||
26 : | (* translate a variable that occurs in an l-value context (i.e., as the target of an assignment) *) | ||
27 : | jhr | 1706 | fun lvalueVar (env, x) = CL.mkVar(lookup(env, x)) |
28 : | jhr | 1640 | (* translate a variable that occurs in an r-value context *) |
29 : | jhr | 1706 | fun rvalueVar (env, x) = CL.mkVar(lookup(env, x)) |
30 : | jhr | 1640 | (* translate a strand state variable that occurs in an l-value context *) |
31 : | fun lvalueStateVar x = CL.mkIndirect(CL.mkVar "selfOut", IL.StateVar.name x) | ||
32 : | (* translate a strand state variable that occurs in an r-value context *) | ||
33 : | fun rvalueStateVar x = CL.mkIndirect(CL.mkVar "selfIn", IL.StateVar.name x) | ||
34 : | end | ||
35 : | |||
36 : | structure ToC = TreeToCFn (TrVar) | ||
37 : | |||
38 : | type var = CL.typed_var | ||
39 : | jhr | 1115 | type exp = CL.exp |
40 : | type stm = CL.stm | ||
41 : | |||
42 : | datatype strand = Strand of { | ||
43 : | jhr | 1375 | name : string, |
44 : | tyName : string, | ||
45 : | jhr | 1640 | state : var list, |
46 : | output : (Ty.ty * CL.var), (* the strand's output variable (only one for now) *) | ||
47 : | jhr | 1375 | code : CL.decl list ref |
48 : | jhr | 1115 | } |
49 : | |||
50 : | datatype program = Prog of { | ||
51 : | jhr | 1716 | tgt : target_desc, (* info about target *) |
52 : | jhr | 1375 | globals : CL.decl list ref, |
53 : | topDecls : CL.decl list ref, | ||
54 : | strands : strand AtomTable.hash_table, | ||
55 : | jhr | 1713 | nAxes : int option ref, (* number of axes in initial grid (NONE means collection) *) |
56 : | jhr | 1375 | initially : CL.decl ref |
57 : | jhr | 1115 | } |
58 : | |||
59 : | datatype env = ENV of { | ||
60 : | jhr | 1375 | info : env_info, |
61 : | vMap : var V.Map.map, | ||
62 : | scope : scope | ||
63 : | jhr | 1115 | } |
64 : | |||
65 : | and env_info = INFO of { | ||
66 : | jhr | 1375 | prog : program |
67 : | jhr | 1115 | } |
68 : | |||
69 : | and scope | ||
70 : | = NoScope | ||
71 : | | GlobalScope | ||
72 : | | InitiallyScope | ||
73 : | jhr | 1640 | | StrandScope (* strand initialization *) |
74 : | | MethodScope of StrandUtil.method_name (* method body; vars are state variables *) | ||
75 : | jhr | 1115 | |
76 : | (* the supprted widths of vectors of reals on the target. For the GNU vector extensions, | ||
77 : | * the supported sizes are powers of two, but float2 is broken. | ||
78 : | * NOTE: we should also consider the AVX vector hardware, which has 256-bit registers. | ||
79 : | *) | ||
80 : | jhr | 1376 | fun vectorWidths () = if !N.doublePrecision |
81 : | jhr | 1375 | then [2, 4, 8] |
82 : | else [4, 8] | ||
83 : | jhr | 1115 | |
84 : | jhr | 1640 | (* we support printing in the sequential C target *) |
85 : | val supportsPrinting = true | ||
86 : | |||
87 : | jhr | 1115 | (* tests for whether various expression forms can appear inline *) |
88 : | jhr | 1375 | fun inlineCons n = (n < 2) (* vectors are inline, but not matrices *) |
89 : | val inlineMatrixExp = false (* can matrix-valued expressions appear inline? *) | ||
90 : | jhr | 1115 | |
91 : | (* TreeIL to target translations *) | ||
92 : | structure Tr = | ||
93 : | struct | ||
94 : | jhr | 1375 | fun fragment (ENV{info, vMap, scope}, blk) = let |
95 : | val (vMap, stms) = ToC.trFragment (vMap, blk) | ||
96 : | in | ||
97 : | (ENV{info=info, vMap=vMap, scope=scope}, stms) | ||
98 : | end | ||
99 : | jhr | 1640 | (* NOTE: we may be able to simplify the interface to ToC.trBlock! *) |
100 : | fun block (ENV{vMap, ...}, blk) = ToC.trBlock (vMap, blk) | ||
101 : | jhr | 1375 | fun exp (ENV{vMap, ...}, e) = ToC.trExp(vMap, e) |
102 : | jhr | 1115 | end |
103 : | |||
104 : | (* variables *) | ||
105 : | structure Var = | ||
106 : | struct | ||
107 : | jhr | 1640 | fun name (CL.V(_, name)) = name |
108 : | jhr | 1375 | fun global (Prog{globals, ...}, name, ty) = let |
109 : | val ty' = ToC.trType ty | ||
110 : | in | ||
111 : | globals := CL.D_Var([], ty', name, NONE) :: !globals; | ||
112 : | jhr | 1640 | CL.V(ty', name) |
113 : | jhr | 1375 | end |
114 : | jhr | 1640 | fun param x = CL.V(ToC.trType(V.ty x), V.name x) |
115 : | jhr | 1115 | end |
116 : | |||
117 : | (* environments *) | ||
118 : | structure Env = | ||
119 : | struct | ||
120 : | (* create a new environment *) | ||
121 : | jhr | 1375 | fun new prog = ENV{ |
122 : | info=INFO{prog = prog}, | ||
123 : | vMap = V.Map.empty, | ||
124 : | scope = NoScope | ||
125 : | } | ||
126 : | jhr | 1115 | (* define the current translation context *) |
127 : | jhr | 1375 | fun setScope scope (ENV{info, vMap, ...}) = ENV{info=info, vMap=vMap, scope=scope} |
128 : | val scopeGlobal = setScope GlobalScope | ||
129 : | val scopeInitially = setScope InitiallyScope | ||
130 : | jhr | 1640 | fun scopeStrand env = setScope StrandScope env |
131 : | fun scopeMethod (env, name) = setScope (MethodScope name) env | ||
132 : | jhr | 1115 | (* bind a TreeIL varaiable to a target variable *) |
133 : | jhr | 1375 | fun bind (ENV{info, vMap, scope}, x, x') = ENV{ |
134 : | info = info, | ||
135 : | vMap = V.Map.insert(vMap, x, x'), | ||
136 : | scope = scope | ||
137 : | } | ||
138 : | jhr | 1115 | end |
139 : | |||
140 : | (* programs *) | ||
141 : | structure Program = | ||
142 : | struct | ||
143 : | jhr | 1716 | fun new (tgt : target_desc) = let |
144 : | (* | ||
145 : | jhr | 1705 | val includes = if #exec tgt |
146 : | then ["#include \"Diderot/diderot.h\"\n"] | ||
147 : | else [ | ||
148 : | "#include \"", | ||
149 : | OS.Path.joinBaseExt{base= #outBase tgt, ext= SOME "h"}, | ||
150 : | "\"\n" | ||
151 : | ] | ||
152 : | jhr | 1716 | *) |
153 : | jhr | 1705 | in |
154 : | N.initTargetSpec {double= #double tgt, long=false}; | ||
155 : | Prog{ | ||
156 : | tgt = tgt, | ||
157 : | jhr | 1716 | globals = ref [ |
158 : | CL.D_Var(["static"], CL.charPtr, "ProgramName", | ||
159 : | SOME(CL.I_Exp(CL.mkStr(#srcFile tgt)))) | ||
160 : | ], | ||
161 : | (* | ||
162 : | jhr | 1705 | globals = ref [ (* NOTE: in reverse order! *) |
163 : | CL.D_Var(["static"], CL.charPtr, "ProgramName", | ||
164 : | SOME(CL.I_Exp(CL.mkStr(#srcFile tgt)))), | ||
165 : | CL.D_Verbatim([ | ||
166 : | jhr | 1706 | concat["#define " ^ TargetUtil.floatPrecisionDef tgt, "\n"], |
167 : | concat["#define " ^ TargetUtil.intPrecisionDef tgt, "\n"], | ||
168 : | concat["#define " ^ TargetUtil.targetDef tgt, "\n"] | ||
169 : | jhr | 1705 | ] @ includes) |
170 : | ], | ||
171 : | jhr | 1716 | *) |
172 : | jhr | 1705 | topDecls = ref [], |
173 : | strands = AtomTable.mkTable (16, Fail "strand table"), | ||
174 : | jhr | 1713 | nAxes = ref(SOME ~1), |
175 : | jhr | 1705 | initially = ref(CL.D_Comment["missing initially"]) |
176 : | } | ||
177 : | end | ||
178 : | jhr | 1301 | (* register the code that is used to register command-line options for input variables *) |
179 : | jhr | 1375 | fun inputs (Prog{topDecls, ...}, stm) = let |
180 : | val inputsFn = CL.D_Func( | ||
181 : | jhr | 1376 | [], CL.voidTy, N.registerOpts, |
182 : | [CL.PARAM([], CL.T_Ptr(CL.T_Named N.optionsTy), "opts")], | ||
183 : | jhr | 1375 | stm) |
184 : | in | ||
185 : | topDecls := inputsFn :: !topDecls | ||
186 : | end | ||
187 : | jhr | 1115 | (* register the global initialization part of a program *) |
188 : | jhr | 1375 | fun init (Prog{topDecls, ...}, init) = let |
189 : | jhr | 1376 | val initFn = CL.D_Func([], CL.voidTy, N.initGlobals, [], init) |
190 : | jhr | 1375 | val shutdownFn = CL.D_Func( |
191 : | jhr | 1376 | [], CL.voidTy, N.shutdown, |
192 : | [CL.PARAM([], CL.T_Ptr(CL.T_Named N.worldTy), "wrld")], | ||
193 : | jhr | 1375 | CL.S_Block[]) |
194 : | in | ||
195 : | topDecls := shutdownFn :: initFn :: !topDecls | ||
196 : | end | ||
197 : | jhr | 1115 | (* create and register the initially function for a program *) |
198 : | jhr | 1375 | fun initially { |
199 : | jhr | 1713 | prog = Prog{strands, nAxes, initially, ...}, |
200 : | jhr | 1375 | isArray : bool, |
201 : | iterPrefix : stm list, | ||
202 : | iters : (var * exp * exp) list, | ||
203 : | createPrefix : stm list, | ||
204 : | strand : Atom.atom, | ||
205 : | args : exp list | ||
206 : | } = let | ||
207 : | val name = Atom.toString strand | ||
208 : | val nDims = List.length iters | ||
209 : | jhr | 1376 | val worldTy = CL.T_Ptr(CL.T_Named N.worldTy) |
210 : | jhr | 1375 | fun mapi f xs = let |
211 : | fun mapf (_, []) = [] | ||
212 : | | mapf (i, x::xs) = f(i, x) :: mapf(i+1, xs) | ||
213 : | in | ||
214 : | mapf (0, xs) | ||
215 : | end | ||
216 : | val baseInit = mapi (fn (i, (_, e, _)) => (i, CL.I_Exp e)) iters | ||
217 : | val sizeInit = mapi | ||
218 : | jhr | 1640 | (fn (i, (CL.V(ty, _), lo, hi)) => |
219 : | jhr | 1375 | (i, CL.I_Exp(CL.mkBinOp(CL.mkBinOp(hi, CL.#-, lo), CL.#+, CL.E_Int(1, ty)))) |
220 : | ) iters | ||
221 : | (* code to allocate the world and initial strands *) | ||
222 : | val wrld = "wrld" | ||
223 : | val allocCode = [ | ||
224 : | CL.mkComment["allocate initial block of strands"], | ||
225 : | CL.mkDecl(CL.T_Array(CL.int32, SOME nDims), "base", SOME(CL.I_Array baseInit)), | ||
226 : | CL.mkDecl(CL.T_Array(CL.uint32, SOME nDims), "size", SOME(CL.I_Array sizeInit)), | ||
227 : | CL.mkDecl(worldTy, wrld, | ||
228 : | jhr | 1376 | SOME(CL.I_Exp(CL.E_Apply(N.allocInitially, [ |
229 : | jhr | 1375 | CL.mkVar "ProgramName", |
230 : | jhr | 1376 | CL.mkUnOp(CL.%&, CL.E_Var(N.strandDesc name)), |
231 : | jhr | 1375 | CL.E_Bool isArray, |
232 : | CL.E_Int(IntInf.fromInt nDims, CL.int32), | ||
233 : | CL.E_Var "base", | ||
234 : | CL.E_Var "size" | ||
235 : | ])))) | ||
236 : | ] | ||
237 : | (* create the loop nest for the initially iterations *) | ||
238 : | val indexVar = "ix" | ||
239 : | jhr | 1376 | val strandTy = CL.T_Ptr(CL.T_Named(N.strandTy name)) |
240 : | jhr | 1375 | fun mkLoopNest [] = CL.mkBlock(createPrefix @ [ |
241 : | CL.mkDecl(strandTy, "sp", | ||
242 : | SOME(CL.I_Exp( | ||
243 : | CL.E_Cast(strandTy, | ||
244 : | jhr | 1376 | CL.E_Apply(N.inState, [CL.E_Var "wrld", CL.E_Var indexVar]))))), |
245 : | CL.mkCall(N.strandInit name, CL.E_Var "sp" :: args), | ||
246 : | jhr | 1375 | CL.mkAssign(CL.E_Var indexVar, CL.mkBinOp(CL.E_Var indexVar, CL.#+, CL.E_Int(1, CL.uint32))) |
247 : | ]) | ||
248 : | jhr | 1640 | | mkLoopNest ((CL.V(ty, param), lo, hi)::iters) = let |
249 : | jhr | 1375 | val body = mkLoopNest iters |
250 : | in | ||
251 : | CL.mkFor( | ||
252 : | [(ty, param, lo)], | ||
253 : | CL.mkBinOp(CL.E_Var param, CL.#<=, hi), | ||
254 : | [CL.mkPostOp(CL.E_Var param, CL.^++)], | ||
255 : | body) | ||
256 : | end | ||
257 : | val iterCode = [ | ||
258 : | CL.mkComment["initially"], | ||
259 : | CL.mkDecl(CL.uint32, indexVar, SOME(CL.I_Exp(CL.E_Int(0, CL.uint32)))), | ||
260 : | mkLoopNest iters | ||
261 : | ] | ||
262 : | val body = CL.mkBlock( | ||
263 : | jhr | 1301 | iterPrefix @ |
264 : | allocCode @ | ||
265 : | iterCode @ | ||
266 : | [CL.mkReturn(SOME(CL.E_Var "wrld"))]) | ||
267 : | jhr | 1376 | val initFn = CL.D_Func([], worldTy, N.initially, [], body) |
268 : | jhr | 1375 | in |
269 : | jhr | 1713 | nAxes := (if isArray then SOME nDims else NONE); |
270 : | jhr | 1375 | initially := initFn |
271 : | end | ||
272 : | jhr | 1115 | |
273 : | (***** OUTPUT *****) | ||
274 : | jhr | 1716 | |
275 : | fun genStrand (tgt : target_desc, Strand{name, tyName, state, output, code}) = let | ||
276 : | jhr | 1375 | (* the type declaration for the strand's state struct *) |
277 : | val selfTyDef = CL.D_StructDef( | ||
278 : | jhr | 1716 | SOME(concat[#namespace tgt, "struct_", name]), |
279 : | jhr | 1640 | List.rev (List.map (fn CL.V(ty, x) => (ty, x)) state), |
280 : | jhr | 1716 | NONE) |
281 : | jhr | 1640 | (* the type and access expression for the strand's output variable *) |
282 : | val (outTy, outState) = (#1 output, CL.mkIndirect(CL.mkVar "self", #2 output)) | ||
283 : | jhr | 1375 | (* the strand's descriptor object *) |
284 : | val descI = let | ||
285 : | fun fnPtr (ty, f) = CL.I_Exp(CL.mkCast(CL.T_Named ty, CL.mkVar f)) | ||
286 : | jhr | 1640 | val nrrdTy = NrrdTypes.toNrrdType outTy |
287 : | val nrrdSize = NrrdTypes.toNrrdSize outTy | ||
288 : | in | ||
289 : | CL.I_Struct[ | ||
290 : | ("name", CL.I_Exp(CL.mkStr name)), | ||
291 : | ("stateSzb", CL.I_Exp(CL.mkSizeof(CL.T_Named(N.strandTy name)))), | ||
292 : | ("update", fnPtr("update_method_t", name ^ "_Update")), | ||
293 : | jhr | 1716 | ("stabilize", fnPtr("stabilize_method_t", name ^ "_Stabilize")) |
294 : | jhr | 1640 | ] |
295 : | end | ||
296 : | jhr | 1376 | val desc = CL.D_Var([], CL.T_Named N.strandDescTy, N.strandDesc name, SOME descI) |
297 : | jhr | 1375 | in |
298 : | jhr | 1716 | selfTyDef :: List.rev (desc :: !code) |
299 : | jhr | 1375 | end |
300 : | jhr | 1115 | |
301 : | jhr | 1716 | (* FIXME: this function will also be used for other targets, so we should pull it into a |
302 : | * utility module in c-util. | ||
303 : | *) | ||
304 : | (* generate the struct declaration for the world representation *) | ||
305 : | fun genWorldStruct (tgt : target_desc, Strand{tyName, ...}) = CL.D_StructDef( | ||
306 : | SOME(#namespace tgt ^ "struct_world"), | ||
307 : | [ | ||
308 : | (CL.T_Ptr(CL.T_Named "const char"), "name"), | ||
309 : | (CL.charPtr, "err"), | ||
310 : | (CL.boolTy, "isArray"), | ||
311 : | (CL.uint32, "nStrands"), | ||
312 : | (CL.T_Ptr(CL.T_Named "Strand_t"), "strandDesc"), | ||
313 : | (CL.uint32, "nAxes"), | ||
314 : | (CL.T_Ptr CL.uint32, "base"), | ||
315 : | (CL.T_Ptr CL.uint32, "size"), | ||
316 : | (CL.uint32, "numStrands"), | ||
317 : | (CL.T_Ptr CL.uint8, "status"), | ||
318 : | (CL.T_Ptr(CL.T_Ptr(CL.T_Named tyName)), "inState"), | ||
319 : | (CL.T_Ptr(CL.T_Ptr(CL.T_Named tyName)), "outState") | ||
320 : | ], | ||
321 : | NONE) | ||
322 : | |||
323 : | jhr | 1115 | (* generate the table of strand descriptors *) |
324 : | jhr | 1716 | fun ppStrandTable (ppStrm, strands) = let |
325 : | jhr | 1375 | val nStrands = length strands |
326 : | jhr | 1376 | fun genInit (Strand{name, ...}) = CL.I_Exp(CL.mkUnOp(CL.%&, CL.E_Var(N.strandDesc name))) |
327 : | jhr | 1375 | fun genInits (_, []) = [] |
328 : | | genInits (i, s::ss) = (i, genInit s) :: genInits(i+1, ss) | ||
329 : | fun ppDecl dcl = PrintAsC.output(ppStrm, dcl) | ||
330 : | in | ||
331 : | jhr | 1376 | ppDecl (CL.D_Var([], CL.int32, N.numStrands, |
332 : | jhr | 1375 | SOME(CL.I_Exp(CL.E_Int(IntInf.fromInt nStrands, CL.int32))))); |
333 : | ppDecl (CL.D_Var([], | ||
334 : | jhr | 1376 | CL.T_Array(CL.T_Ptr(CL.T_Named N.strandDescTy), SOME nStrands), |
335 : | N.strands, | ||
336 : | jhr | 1375 | SOME(CL.I_Array(genInits (0, strands))))) |
337 : | end | ||
338 : | jhr | 1115 | |
339 : | jhr | 1713 | fun genExecSrc (baseName, prog) = let |
340 : | jhr | 1716 | val Prog{tgt, globals, topDecls, strands, initially, ...} = prog |
341 : | jhr | 1375 | val fileName = OS.Path.joinBaseExt{base=baseName, ext=SOME "c"} |
342 : | val outS = TextIO.openOut fileName | ||
343 : | val ppStrm = PrintAsC.new outS | ||
344 : | fun ppDecl dcl = PrintAsC.output(ppStrm, dcl) | ||
345 : | val strands = AtomTable.listItems strands | ||
346 : | in | ||
347 : | List.app ppDecl (List.rev (!globals)); | ||
348 : | List.app ppDecl (List.rev (!topDecls)); | ||
349 : | jhr | 1716 | List.app (fn strand => List.app ppDecl (genStrand(tgt, strand))) strands; |
350 : | ppStrandTable (ppStrm, strands); | ||
351 : | jhr | 1375 | ppDecl (!initially); |
352 : | PrintAsC.close ppStrm; | ||
353 : | TextIO.closeOut outS | ||
354 : | end | ||
355 : | jhr | 1115 | |
356 : | jhr | 1714 | fun condCons (true, x, xs) = x::xs |
357 : | | condCons (false, _, xs) = xs | ||
358 : | |||
359 : | jhr | 1716 | fun compile (tgt : target_desc, basename) = let |
360 : | jhr | 1375 | (* generate the C compiler flags *) |
361 : | val cflags = ["-I" ^ Paths.diderotInclude, "-I" ^ Paths.teemInclude] | ||
362 : | jhr | 1714 | val cflags = condCons (#parallel tgt, #pthread Paths.cflags, cflags) |
363 : | val cflags = if #debug tgt | ||
364 : | jhr | 1375 | then #debug Paths.cflags :: cflags |
365 : | else #ndebug Paths.cflags :: cflags | ||
366 : | val cflags = #base Paths.cflags :: cflags | ||
367 : | jhr | 1714 | in |
368 : | RunCC.compile (basename, cflags) | ||
369 : | end | ||
370 : | |||
371 : | jhr | 1716 | fun ldFlags (tgt : target_desc) = let |
372 : | jhr | 1714 | val extraLibs = condCons (#parallel tgt, #pthread Paths.extraLibs, []) |
373 : | jhr | 1375 | val extraLibs = Paths.teemLinkFlags @ #base Paths.extraLibs :: extraLibs |
374 : | jhr | 1706 | val rtLib = TargetUtil.runtimeName tgt |
375 : | jhr | 1714 | in |
376 : | rtLib :: extraLibs | ||
377 : | end | ||
378 : | |||
379 : | (* output the code to a file. The string is the basename of the file, the extension | ||
380 : | * is provided by the target. | ||
381 : | *) | ||
382 : | fun generateExec (prog as Prog{tgt, ...}) = let | ||
383 : | val {outDir, outBase, exec, double, parallel, debug, ...} = tgt | ||
384 : | jhr | 1705 | val basename = OS.Path.joinDirFile{dir=outDir, file=outBase} |
385 : | jhr | 1375 | in |
386 : | jhr | 1713 | genExecSrc (basename, prog); |
387 : | jhr | 1714 | compile (tgt, basename); |
388 : | RunCC.linkExec (basename, ldFlags tgt) | ||
389 : | jhr | 1375 | end |
390 : | jhr | 1115 | |
391 : | jhr | 1716 | fun outputLibSrc (baseName, Prog{tgt, globals, strands, nAxes, ...}) = let |
392 : | val [strand as Strand{name, tyName, state, output, ...}] = AtomTable.listItems strands | ||
393 : | jhr | 1713 | val outputs = List.map (GenOutput.gen (tgt, !nAxes)) [output] |
394 : | (* output to C file *) | ||
395 : | val fileName = OS.Path.joinBaseExt{base=baseName, ext=SOME "c"} | ||
396 : | val outS = TextIO.openOut fileName | ||
397 : | val ppStrm = PrintAsC.new outS | ||
398 : | fun ppDecl dcl = PrintAsC.output(ppStrm, dcl) | ||
399 : | in | ||
400 : | jhr | 1716 | (* FIXME: use a fragment for this part of the file *) |
401 : | ppDecl (CL.D_Verbatim [ | ||
402 : | "#include \"", OS.Path.joinBaseExt{base= #outBase tgt, ext= SOME "h"}, "\"\n", | ||
403 : | "#include \"teem/nrrd.h\"\n", | ||
404 : | "#include \"teem/biff.h\"\n", | ||
405 : | "typedef struct ", #namespace tgt, "struct_", name, " ", tyName, ";\n" | ||
406 : | ]); | ||
407 : | ppDecl (genWorldStruct(tgt, strand)); | ||
408 : | jhr | 1715 | List.app ppDecl (List.rev (!globals)); |
409 : | jhr | 1716 | List.app ppDecl (genStrand(tgt, strand)); |
410 : | jhr | 1714 | List.app ppDecl outputs; |
411 : | PrintAsC.close ppStrm; | ||
412 : | TextIO.closeOut outS | ||
413 : | jhr | 1713 | end |
414 : | |||
415 : | jhr | 1706 | fun generateLib (prog as Prog{tgt, strands, ...}) = let |
416 : | val {outDir, outBase, exec, double, parallel, debug, ...} = tgt | ||
417 : | val basename = OS.Path.joinDirFile{dir=outDir, file=outBase} | ||
418 : | val [Strand{state, output, ...}] = AtomTable.listItems strands | ||
419 : | in | ||
420 : | jhr | 1713 | (* generate the library .h file *) |
421 : | jhr | 1706 | GenLibraryInterface.gen { |
422 : | tgt = tgt, | ||
423 : | inputs = [], (* FIXME *) | ||
424 : | outputs = [output] | ||
425 : | jhr | 1713 | }; |
426 : | (* *) | ||
427 : | jhr | 1716 | outputLibSrc (basename, prog); |
428 : | jhr | 1714 | (* compile and link *) |
429 : | compile (tgt, basename); | ||
430 : | RunCC.linkLib (basename, ldFlags tgt) | ||
431 : | jhr | 1706 | end |
432 : | |||
433 : | fun generate (prog as Prog{tgt, ...}) = if #exec tgt | ||
434 : | then generateExec prog | ||
435 : | else generateLib prog | ||
436 : | |||
437 : | jhr | 1115 | end |
438 : | |||
439 : | (* strands *) | ||
440 : | structure Strand = | ||
441 : | struct | ||
442 : | jhr | 1640 | fun define (Prog{strands, ...}, strandId, state) = let |
443 : | jhr | 1375 | val name = Atom.toString strandId |
444 : | jhr | 1640 | (* the output state variable *) |
445 : | val outputVar = (case List.filter IL.StateVar.isOutput state | ||
446 : | of [] => raise Fail("no output specified for strand " ^ name) | ||
447 : | | [x] => (IL.StateVar.ty x, IL.StateVar.name x) | ||
448 : | | _ => raise Fail("multiple outputs in " ^ name) | ||
449 : | (* end case *)) | ||
450 : | (* the state variables *) | ||
451 : | val state = let | ||
452 : | fun cvt x = CL.V(ToC.trType(IL.StateVar.ty x), IL.StateVar.name x) | ||
453 : | in | ||
454 : | List.map cvt state | ||
455 : | end | ||
456 : | jhr | 1375 | val strand = Strand{ |
457 : | name = name, | ||
458 : | jhr | 1376 | tyName = N.strandTy name, |
459 : | jhr | 1640 | state = state, |
460 : | output = outputVar, | ||
461 : | jhr | 1375 | code = ref [] |
462 : | } | ||
463 : | in | ||
464 : | AtomTable.insert strands (strandId, strand); | ||
465 : | strand | ||
466 : | end | ||
467 : | jhr | 1115 | |
468 : | (* return the strand with the given name *) | ||
469 : | jhr | 1375 | fun lookup (Prog{strands, ...}, strandId) = AtomTable.lookup strands strandId |
470 : | jhr | 1115 | |
471 : | (* register the strand-state initialization code. The variables are the strand | ||
472 : | * parameters. | ||
473 : | *) | ||
474 : | jhr | 1375 | fun init (Strand{name, tyName, code, ...}, params, init) = let |
475 : | jhr | 1376 | val fName = N.strandInit name |
476 : | jhr | 1375 | val params = |
477 : | CL.PARAM([], CL.T_Ptr(CL.T_Named tyName), "selfOut") :: | ||
478 : | jhr | 1640 | List.map (fn (CL.V(ty, x)) => CL.PARAM([], ty, x)) params |
479 : | jhr | 1375 | val initFn = CL.D_Func([], CL.voidTy, fName, params, init) |
480 : | in | ||
481 : | code := initFn :: !code | ||
482 : | end | ||
483 : | jhr | 1115 | |
484 : | (* register a strand method *) | ||
485 : | jhr | 1375 | fun method (Strand{name, tyName, code, ...}, methName, body) = let |
486 : | jhr | 1640 | val fName = concat[name, "_", StrandUtil.nameToString methName] |
487 : | jhr | 1375 | val params = [ |
488 : | CL.PARAM([], CL.T_Ptr(CL.T_Named tyName), "selfIn"), | ||
489 : | CL.PARAM([], CL.T_Ptr(CL.T_Named tyName), "selfOut") | ||
490 : | ] | ||
491 : | jhr | 1444 | val resTy = (case methName |
492 : | jhr | 1640 | of StrandUtil.Update => CL.T_Named "StrandStatus_t" |
493 : | | StrandUtil.Stabilize => CL.voidTy | ||
494 : | jhr | 1444 | (* end case *)) |
495 : | val methFn = CL.D_Func(["static"], resTy, fName, params, body) | ||
496 : | jhr | 1375 | in |
497 : | code := methFn :: !code | ||
498 : | end | ||
499 : | jhr | 1115 | |
500 : | end | ||
501 : | |||
502 : | end | ||
503 : | |||
504 : | structure CBackEnd = CodeGenFn(CTarget) |
root@smlnj-gforge.cs.uchicago.edu | ViewVC Help |
Powered by ViewVC 1.0.0 |