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