Bug Summary

File:src/of_crinlin.c
Warning:line 357, column 2
Value stored to 'env' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name of_crinlin.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/home/kfp/aldor/aldor/aldor/src -fcoverage-compilation-dir=/home/kfp/aldor/aldor/aldor/src -resource-dir /usr/local/lib/clang/18 -D PACKAGE_NAME="aldor" -D PACKAGE_TARNAME="aldor" -D PACKAGE_VERSION="1.4.0" -D PACKAGE_STRING="aldor 1.4.0" -D PACKAGE_BUGREPORT="aldor@xinutec.org" -D PACKAGE_URL="" -D PACKAGE="aldor" -D VERSION="1.4.0" -D YYTEXT_POINTER=1 -D HAVE_STDIO_H=1 -D HAVE_STDLIB_H=1 -D HAVE_STRING_H=1 -D HAVE_INTTYPES_H=1 -D HAVE_STDINT_H=1 -D HAVE_STRINGS_H=1 -D HAVE_SYS_STAT_H=1 -D HAVE_SYS_TYPES_H=1 -D HAVE_UNISTD_H=1 -D STDC_HEADERS=1 -D HAVE_LIBREADLINE=1 -D HAVE_READLINE_READLINE_H=1 -D HAVE_READLINE_HISTORY=1 -D HAVE_READLINE_HISTORY_H=1 -D USE_GLOOP_SHELL=1 -D GENERATOR_COROUTINES=0 -D HAVE_DLFCN_H=1 -D LT_OBJDIR=".libs/" -I . -D VCSVERSION="2c53e759f1e00e345f8b172e7139debda72fda13" -internal-isystem /usr/local/lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O0 -Wno-empty-body -Wno-enum-compare -Wno-missing-field-initializers -Wno-unused -Wno-unused-parameter -Wno-error=format -Wno-error=type-limits -Wno-error=strict-aliasing -Wno-sign-compare -Wno-error=shift-negative-value -Wno-error=clobbered -std=c99 -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2026-01-15-223856-845667-1 -x c of_crinlin.c
1#include "debug.h"
2#include "inlstate.h"
3#include "flog.h"
4#include "fptr.h"
5#include "list.h"
6#include "of_util.h"
7#include "optinfo.h"
8#include "store.h"
9#include "strops.h"
10#include "usedef.h"
11#include "util.h"
12
13/**
14 * Inlining coroutines
15 *
16 * A coroutine looks like (Gener (Env 0) (Const 1))
17 * ..
18 * A call is
19 * (Set v (GenIter g P1 P2))
20 * (GenerStep label v) .. (GenerValue v)
21 * ..
22 * A coroutine is a prog with yields rather than return values.
23 * Inlining:
24 * find GenIter, and related steps
25 * .. Count yields..
26 * 0 => None
27 * 1 => Boolean
28 * 1 => Int
29 *..
30 * (Set
31 * (Loc 2)
32 * (GenIter (Gener 0 (Nil) (Loc 3) (Const 5 xlistIter_coroutine))))
33 * (Label 0)
34 * (GenerStep 1 (Loc 2))
35 * (Set (Loc 1) (Cast SInt (GenerValue (Loc 2))))
36 * (Set (Loc 0 total) (BCall SIntPlus (Loc 0 total) (Loc 1)))
37 * (Goto 0)
38 * ++
39 * (Seq
40 * (Yield (Cast Word (SInt 99)))
41 * (Return (Values)))))
42 *
43 *...
44 * Maybe merge graphs..
45 */
46
47typedef struct genCallInfo {
48 AInt varId;
49 Foam generSource; // GClos for generator
50 FoamPtr genIter; // (Set xyz (GenIter () ...))
51 AInt progId;
52 Foam progCR;
53 Foam envCR;
54 FoamPtrList steps;
55 FoamPtrList values;
56 BBlockList bbs;
57} *GenCallInfo;
58
59typedef struct crinInlinee {
60 AInt yieldCount;
61 AInt labelCount;
62 Foam prog;
63 InlEnvState env;
64 InlSubstState substState;
65} *CrinInlinee;
66
67// "Stuff" needed for transformation - This assumes that there is a single 'GenerStep'
68typedef struct crinTarget {
69 Foam prog;
70 Foam env;
71 FoamPtr step;
72 FoamPtr call;
73 FoamPtrList values;
74 AInt doneLabel;
75 BBlock bb;
76} *CrinTarget;
77
78// How to go from target & inlinee to the final result
79typedef struct crinResult {
80 CrinTarget target;
81 // 'input'
82 AInt labelBase;
83 AInt maxLabel;
84 // newBits
85 AInt tmpVarBase;
86 AInt localBase;
87 AInt resultVar;
88 AInt stepVar;
89 AInt outLabel;
90 // How to xform target
91 AInt nExtraLabels;
92 FoamList newLocals;
93 FoamList setupStmts;
94 FoamList stmts;
95 FoamPtrList doneRefs;
96 Foam envRefs;
97 // extra info
98 Bool newGenerStep;
99} *CrinResult;
100
101typedef struct crinUnit {
102 Foam unit;
103} *CrinUnit;
104
105Bool crinDebug = false((int) 0);
106#define crinDEBUGif (!crinDebug) { } else afprintf DEBUG_IF(crin)if (!crinDebug) { } else afprintf
107
108DECLARE_LIST(GenCallInfo)typedef struct GenCallInfoListCons { GenCallInfo first; struct
GenCallInfoListCons *rest; } *GenCallInfoList; struct GenCallInfo_listOpsStruct
{ GenCallInfoList (*Cons) (GenCallInfo, GenCallInfoList); GenCallInfoList
(*Singleton) (GenCallInfo); GenCallInfoList (*List) (int n, ...
); GenCallInfoList (*Listv) (va_list argp); GenCallInfoList (
*ListNull) (GenCallInfo, ...); Bool (*Equal) (GenCallInfoList
, GenCallInfoList, Bool (*f) (GenCallInfo, GenCallInfo)); GenCallInfo
(*Find) (GenCallInfoList, GenCallInfo, Bool(*eq)(GenCallInfo
,GenCallInfo) , int *); GenCallInfo (*Match) (GenCallInfoList
, void *, Bool(*match)(GenCallInfo, void *), int *); GenCallInfoList
(*MatchAll) (GenCallInfoList, void *, Bool(*match)(GenCallInfo
, void *)); GenCallInfoList (*FreeCons) (GenCallInfoList); void
(*Free) (GenCallInfoList); GenCallInfoList (*FreeTo) (GenCallInfoList
, GenCallInfoList); void (*FreeDeeply) (GenCallInfoList, void
(*f)(GenCallInfo)); GenCallInfoList (*FreeDeeplyTo) (GenCallInfoList
, GenCallInfoList, void (*f) (GenCallInfo) ); GenCallInfoList
(*FreeIfSat) (GenCallInfoList, void (*f)(GenCallInfo), Bool (
*s)(GenCallInfo)); GenCallInfo (*Elt) (GenCallInfoList, Length
); GenCallInfoList (*Drop) (GenCallInfoList, Length); GenCallInfoList
(*LastCons) (GenCallInfoList); Length (*_Length) (GenCallInfoList
); Bool (*IsLength) (GenCallInfoList, Length); Bool (*IsShorter
) (GenCallInfoList, Length); Bool (*IsLonger) (GenCallInfoList
, Length); GenCallInfoList (*Copy) (GenCallInfoList); GenCallInfoList
(*CopyTo) (GenCallInfoList, GenCallInfoList); GenCallInfoList
(*CopyDeeply) (GenCallInfoList, GenCallInfo (*)(GenCallInfo)
); GenCallInfoList (*CopyDeeplyTo) (GenCallInfoList, GenCallInfoList
, GenCallInfo (*)(GenCallInfo)); GenCallInfoList (*Map) (GenCallInfo
(*f)(GenCallInfo), GenCallInfoList); GenCallInfoList (*NMap)
(GenCallInfo (*f)(GenCallInfo), GenCallInfoList); GenCallInfoList
(*Reverse) (GenCallInfoList); GenCallInfoList (*NReverse) (GenCallInfoList
); GenCallInfoList (*Concat) (GenCallInfoList, GenCallInfoList
); GenCallInfoList (*NConcat) (GenCallInfoList, GenCallInfoList
); Bool (*Memq) (GenCallInfoList, GenCallInfo); Bool (*Member
) (GenCallInfoList, GenCallInfo, Bool(*eq)(GenCallInfo,GenCallInfo
) ); Bool (*ContainsAllq) (GenCallInfoList, GenCallInfoList);
Bool (*ContainsAnyq) (GenCallInfoList, GenCallInfoList); Bool
(*ContainsAll) (GenCallInfoList, GenCallInfoList, Bool (*eq)
(GenCallInfo, GenCallInfo)); Bool (*ContainsAny) (GenCallInfoList
, GenCallInfoList, Bool (*eq)(GenCallInfo, GenCallInfo)); int
(*Posq) (GenCallInfoList, GenCallInfo); int (*Position) (GenCallInfoList
, GenCallInfo, Bool(*eq)(GenCallInfo,GenCallInfo) ); GenCallInfoList
(*NRemove) (GenCallInfoList, GenCallInfo, Bool(*eq)(GenCallInfo
,GenCallInfo) ); void (*FillVector) (GenCallInfo *, GenCallInfoList
); int (*Print) (FILE *, GenCallInfoList, int (*pr)(FILE *, GenCallInfo
) ); int (*GPrint) (FILE *, GenCallInfoList, int (*pr)(FILE *
, GenCallInfo), char *l,char *m,char *r); int (*Format) (OStream
, CString, GenCallInfoList); }; extern struct GenCallInfo_listOpsStruct
const *GenCallInfo_listPointer
;
109CREATE_LIST(GenCallInfo)struct GenCallInfo_listOpsStruct const *GenCallInfo_listPointer
= (struct GenCallInfo_listOpsStruct const *) &ptrlistOps
;
110
111localstatic void crinUnitInit(Foam unit);
112localstatic void crinUnitFini(Foam unit);
113localstatic Foam crinUnitFindConst(AInt constId);
114localstatic Foam crinDerefReference(Foam foam);
115localstatic Foam crinDerefGener(Foam foam);
116
117localstatic void crinProg(AInt idx, Foam prog);
118localstatic void crinProgInit(AInt idx, Foam prog);
119localstatic void crinProgFini(Foam prog);
120localstatic Bool crinInlineGenIter(Foam prog, GenCallInfo info);
121localstatic InlEnvState crinInlineEnvState(GenCallInfo info);
122localstatic InlSubstState crinInlineSubstState(GenCallInfo info);
123localstatic Foam crinFindInlinee(Foam genIter);
124localstatic Bool crinInlineCoroutine(CrinTarget target, CrinInlinee inlinee);
125localstatic Bool crinTransformGraph(CrinTarget target, CrinInlinee inlinee);
126localstatic void crinSetCRVars(void);
127localstatic void crinSetEnvRefs(void);
128
129localstatic void crinTransformAddLocals(CrinInlinee inlinee);
130localstatic void crinTransformAddParams(CrinInlinee inlinee);
131localstatic AInt crinTransformLocalId(AInt index);
132localstatic void crinTransformSetEnv(CrinInlinee inlinee);
133localstatic void crinTransformBody(CrinTarget target, CrinInlinee inlinee);
134localstatic Foam crinTransformEElt(Foam foam);
135localstatic Foam crinTransformExpr(Foam expr);
136localstatic Foam crinTransformEnv(Foam lex);
137localstatic Foam crinTransformLex(Foam lex);
138localstatic Foam crinGetDecl(AInt format, AInt index);
139
140localstatic AInt crinAllocateLabels(AInt count);
141localstatic void crinAddStatement(Foam stmt);
142localstatic AInt crinLabelIndex(AInt labelBase, AInt index);
143localstatic AInt crinAllocateLocal(Foam foam);
144localstatic void crinAddSetupStatement(Foam foam);
145localstatic void crinEnvSetUsage(AInt level, AInt format);
146
147localstatic void crinApplyResult(CrinTarget target, CrinResult result);
148localstatic void crinApplyResultEnvRefs(CrinTarget target, CrinResult result);
149
150localstatic GenCallInfoList crinBuildCandidates(GenCallInfoList list);
151localstatic GenCallInfoList crinProgFindCandidates(Foam prog);
152
153localstatic CrinResult crinNewResult(CrinTarget target);
154localstatic void crinResultAddStatement(CrinResult result, Foam stmt);
155localstatic void crinResultAddSetupStatement(CrinResult result, Foam stmt);
156localstatic AInt crinResultAllocateLocal(CrinResult result, Foam stmt);
157localstatic void crinResultEnvSetUsage(CrinResult result, AInt level, AInt format);
158
159localstatic GenCallInfo crgcInfoNew (AInt varId);
160localstatic void crgcInfoFree(GenCallInfo info);
161localstatic void crgcAddStep(FoamPtr ptr, BBlock bb, GenCallInfoList *candidates);
162localstatic void crgcAddValue(FoamPtr ptr, BBlock bb, GenCallInfoList *candidates);
163localstatic void crgcAddIter(FoamPtr ptr, BBlock bb, GenCallInfoList *candidates);
164
165localstatic GenCallInfo crgcFindRef(GenCallInfoList lst, AInt id);
166
167localstatic GenCallInfo crinProgFillVar(GenCallInfo info);
168localstatic Foam crinProgFind(GenCallInfo info);
169
170localstatic CrinUnit crinvUnit;
171localstatic CrinResult crinvResult;
172localstatic CrinInlinee crinvInlinee;
173localstatic PtrSet crinvFindContext;
174localstatic AInt crinvProgId;
175
176void
177crinUnit(Foam unit)
178{
179 Foam defs, def;
180 int i;
181
182 crinDEBUGif (!crinDebug) { } else afprintf(dbOut, "(Starting unit\n");
183 crinUnitInit(unit);
184
185 defs = unit->foamUnit.defs;
186
187 for (i=0; i<foamArgc(defs)((defs)->hdr.argc); i++) {
188 def = defs->foamDDef.argv[i];
189
190 if (foamTag(def->foamDef.rhs)((def->foamDef.rhs)->hdr.tag) != FOAM_Prog)
191 continue;
192
193 crinDEBUGif (!crinDebug) { } else afprintf(dbOut, "(Starting const %d...\n", i);
194 crinDEBUGif (!crinDebug) { } else afprintf(dbOut, " Prog %d\n%pFoamTypes\n", i, def->foamDef.rhs);
195 crinProg(i, def->foamDef.rhs);
196 crinDEBUGif (!crinDebug) { } else afprintf(dbOut, "Finished const %d)\n", i);
197 }
198 crinDEBUGif (!crinDebug) { } else afprintf(dbOut, "After---->\n");
199 crinDEBUGif (!crinDebug) { } else afprintf(dbOut, "%pFoamTypes\n", unit);
200 crinDEBUGif (!crinDebug) { } else afprintf(dbOut, "Unit complete)\n");
201
202 crinUnitFini(unit);
203 assert(foamAudit(unit))do { if (!(foamAudit(unit))) _do_assert(("foamAudit(unit)"),"of_crinlin.c"
,203); } while (0)
;
204}
205
206localstatic void
207crinUnitInit(Foam unit)
208{
209 crinvUnit = (CrinUnit) stoAlloc(OB_Other0, sizeof(*crinvUnit));
210 crinvUnit->unit = unit;
211}
212
213localstatic void
214crinUnitFini(Foam unit)
215{
216 stoFree(crinvUnit);
217 crinvUnit = NULL((void*)0);
218}
219
220localstatic Foam
221crinUnitFindConst(AInt constId)
222{
223 AInt i;
224 Foam defs = crinvUnit->unit->foamUnit.defs;
225 for (i=0; i<foamArgc(defs)((defs)->hdr.argc); i++) {
226 Foam lhs = defs->foamDDef.argv[i]->foamDef.lhs;
227 Foam rhs = defs->foamDDef.argv[i]->foamDef.rhs;
228 if (foamTag(lhs)((lhs)->hdr.tag) == FOAM_Const && lhs->foamConst.index == constId) {
229 return rhs;
230 }
231 }
232 return NULL((void*)0);
233}
234
235
236localstatic void
237crinProg(AInt constId, Foam prog)
238{
239 GenCallInfoList candidates;
240 FlowGraph flog;
241 Bool more, chk;
242 int count = 0, inl = 0;
243
244 crinProgInit(constId, prog);
245
246
247 more = true1;
248 while (more) {
249 flog = flogFrProg(prog, FLOG_UniqueExit);
250 chk = usedefChainsFrFlog(flog, UD_OUTPUT_SinglePointer);
251 flogToProg(flog);
252
253 more = false((int) 0);
254 candidates = crinProgFindCandidates(prog); // Maybe add priority queue here
255
256 crinDEBUGif (!crinDebug) { } else afprintf(dbOut, "Found %d candidates (round %d) - Usedef: %d\n", listLength(GenCallInfo)(GenCallInfo_listPointer->_Length)(candidates), count, chk);
257
258 candidates = crinBuildCandidates(candidates);
259 crinDEBUGif (!crinDebug) { } else afprintf(dbOut, ".. filtered to %d candidates\n", listLength(GenCallInfo)(GenCallInfo_listPointer->_Length)(candidates));
260 while (candidates != listNil(GenCallInfo)((GenCallInfoList) 0)) {
261 more = more || crinInlineGenIter(prog, car(candidates)((candidates)->first));
262 crgcInfoFree(car(candidates)((candidates)->first));
263 candidates = cdr(candidates)((candidates)->rest);
264 inl++;
265 }
266 prog->foamProg.body = utilMakeFlatSeq(prog->foamProg.body);
267 count++;
268
269 // Hard cut-off on prog size
270 if (foamArgc(prog->foamProg.body)((prog->foamProg.body)->hdr.argc) > 25)
271 more = false((int) 0);
272 }
273 if (inl > 0) {
274 foamOptInfo(prog)((prog)->hdr.info.opt)->inlState = INL_NotInlined;
275 }
276
277 crinDEBUGif (!crinDebug) { } else afprintf(dbOut, "Finished on %d rounds\n", count);
278 crinProgFini(prog);
279}
280
281localstatic void
282crinProgInit(AInt progId, Foam prog)
283{
284 crinvFindContext = psetNew();
285 crinvProgId = progId;
286}
287
288localstatic void
289crinProgFini(Foam prog)
290{
291 // Check for leaks..
292 assert(psetIsEmpty(crinvFindContext))do { if (!(psetIsEmpty(crinvFindContext))) _do_assert(("psetIsEmpty(crinvFindContext)"
),"of_crinlin.c",292); } while (0)
;
293 crinvFindContext = NULL((void*)0);
294}
295
296localstatic GenCallInfoList
297crinBuildCandidates(GenCallInfoList list)
298{
299 GenCallInfoList newList = listNil(GenCallInfo)((GenCallInfoList) 0);
300 // Filtered priority queue
301 while (list != listNil(GenCallInfo)((GenCallInfoList) 0)) {
302 GenCallInfo candidate = car(list)((list)->first);
303 list = listFreeCons(GenCallInfo)(GenCallInfo_listPointer->FreeCons)(list);
304 if (candidate == NULL((void*)0)) {
305 continue;
306 }
307 else if (candidate->genIter == NULL((void*)0)) {
308 crgcInfoFree(candidate);
309 continue;
310 }
311 else if (candidate->progId == crinvProgId) {
312 crgcInfoFree(candidate);
313 continue;
314 }
315 else if (listLength(FoamPtr)(FoamPtr_listPointer->_Length)(candidate->steps) > 1) {
316 // TODO: Deal with #steps > 1
317 crgcInfoFree(candidate);
318 continue;
319 }
320 newList = listCons(GenCallInfo)(GenCallInfo_listPointer->Cons)(candidate, newList);
321 }
322 return listNReverse(GenCallInfo)(GenCallInfo_listPointer->NReverse)(newList);
323}
324
325localstatic CrinTarget
326crinNewTarget(Foam prog)
327{
328 CrinTarget target = (CrinTarget) stoAlloc(OB_Other0, sizeof(*target));
329 target->prog = prog;
330 target->env = NULL((void*)0);
331 target->step = NULL((void*)0);
332 target->call = NULL((void*)0);
333 target->values = listNil(FoamPtr)((FoamPtrList) 0);
334 target->bb = NULL((void*)0);
335 return target;
336}
337
338localstatic CrinInlinee
339crinNewInlinee(GenCallInfo info, InlEnvState env, InlSubstState substState)
340{
341 CrinInlinee inlinee = (CrinInlinee) stoAlloc(OB_Other0, sizeof(*inlinee));
342 inlinee->yieldCount = foamCountSubtreesOfKind(info->progCR->foamProg.body, FOAM_Yield);
343 inlinee->labelCount = info->progCR->foamProg.nLabels;
344 inlinee->prog = info->progCR;
345 inlinee->env = env;
346 inlinee->substState = substState;
347 return inlinee;
348}
349
350localstatic Bool
351crinInlineGenIter(Foam prog, GenCallInfo info)
352{
353 Foam genClos, env;
354
355 genClos = info->generSource;
356
357 env = genClos->foamGener.env;
Value stored to 'env' is never read
358
359 CrinTarget target = crinNewTarget(prog);
360 target->step = car(info->steps)((info->steps)->first);
361 target->call = info->genIter;
362 target->doneLabel = fptrVal(target->step)->foamGenerStep.label;
363 target->values = info->values;
364 target->bb = car(info->bbs)((info->bbs)->first);
365 InlEnvState envState = crinInlineEnvState(info);
366 InlSubstState substState = crinInlineSubstState(info);
367 CrinInlinee inlinee = crinNewInlinee(info, envState, substState);
368 return crinInlineCoroutine(target, inlinee);
369}
370
371localstatic InlEnvState
372crinInlineEnvState(GenCallInfo info)
373{
374 Foam prog = info->progCR;
375 Foam levels = prog->foamProg.levels;
376 Foam env1;
377 Bool hasEnv0;
378
379 hasEnv0 = true1;
380 env1 = info->envCR;
381 if (levels->foamDEnv.argv[0] == emptyFormatSlot4
382 || levels->foamDEnv.argv[0] == envUsedSlot0) {
383 hasEnv0 = false((int) 0);
384 }
385
386 return inlEnvNew(levels, hasEnv0, env1);
387}
388
389localstatic InlSubstState
390crinInlineSubstState(GenCallInfo info)
391{
392 Foam gener = info->generSource;
393
394 return inlSubstStateNew(foamSyme(gener->foamGener.env)((gener->foamGener.env)->hdr.syme));
395}
396
397localstatic Bool
398crinInlineCoroutine(CrinTarget target, CrinInlinee inlinee)
399{
400 // Set up parameters
401 // Move prog into "this" environment
402 return crinTransformGraph(target, inlinee);
403 // clean up loose ends
404}
405
406localstatic Bool
407crinTransformGraph(CrinTarget target, CrinInlinee inlinee)
408{
409 Bool moreToDo;
410 Foam stmt;
411 int i;
412
413 // 1. Replace GenIter with vars
414 // - Step number
415 // - Done flag
416 // - Return value
417
418 // Replace inlinee code,
419 // -- adding initial select/step thing
420 // -- Yield => Assignment to return var
421 // -- Return => branch to out of here
422
423 crinDEBUGif (!crinDebug) { } else afprintf(dbOut, "Inline prog\n %pFoamTypes\n", inlinee->prog);
424 CrinResult result = crinNewResult(target);
425 crinvResult = result;
426 crinvInlinee = inlinee;
427
428 crinSetCRVars();
429 crinSetEnvRefs();
430 crinTransformAddParams(inlinee);
431 crinTransformAddLocals(inlinee);
432 crinTransformSetEnv(inlinee);
433 crinTransformBody(target, inlinee);
434
435 crinDEBUGif (!crinDebug) { } else afprintf(dbOut, "Transformed\n");
436 crinDEBUGif (!crinDebug) { } else afprintf(dbOut, " (Seq\n");
437 listIter(Foam, stmt, listReverse(Foam)(result->setupStmts), {{ { FoamList _l0; Foam stmt; for (_l0 = ((Foam_listPointer->
Reverse)(result->setupStmts)); _l0; _l0 = ((_l0)->rest)
) { stmt = ((_l0)->first); { { if (!crinDebug) { } else afprintf
(dbOut, " %pFoamTypes\n", stmt); }; }; } }; }
438 crinDEBUG(dbOut, " %pFoamTypes\n", stmt);{ { FoamList _l0; Foam stmt; for (_l0 = ((Foam_listPointer->
Reverse)(result->setupStmts)); _l0; _l0 = ((_l0)->rest)
) { stmt = ((_l0)->first); { { if (!crinDebug) { } else afprintf
(dbOut, " %pFoamTypes\n", stmt); }; }; } }; }
439 }){ { FoamList _l0; Foam stmt; for (_l0 = ((Foam_listPointer->
Reverse)(result->setupStmts)); _l0; _l0 = ((_l0)->rest)
) { stmt = ((_l0)->first); { { if (!crinDebug) { } else afprintf
(dbOut, " %pFoamTypes\n", stmt); }; }; } }; }
;
440 crinDEBUGif (!crinDebug) { } else afprintf(dbOut, ")\n");
441 crinDEBUGif (!crinDebug) { } else afprintf(dbOut, "Code\n (Seq\n");
442 listIter(Foam, stmt, listReverse(Foam)(result->stmts), {{ { FoamList _l0; Foam stmt; for (_l0 = ((Foam_listPointer->
Reverse)(result->stmts)); _l0; _l0 = ((_l0)->rest)) { stmt
= ((_l0)->first); { { if (!crinDebug) { } else afprintf(dbOut
, " %pFoamTypes\n", stmt); }; }; } }; }
443 crinDEBUG(dbOut, " %pFoamTypes\n", stmt);{ { FoamList _l0; Foam stmt; for (_l0 = ((Foam_listPointer->
Reverse)(result->stmts)); _l0; _l0 = ((_l0)->rest)) { stmt
= ((_l0)->first); { { if (!crinDebug) { } else afprintf(dbOut
, " %pFoamTypes\n", stmt); }; }; } }; }
444 }){ { FoamList _l0; Foam stmt; for (_l0 = ((Foam_listPointer->
Reverse)(result->stmts)); _l0; _l0 = ((_l0)->rest)) { stmt
= ((_l0)->first); { { if (!crinDebug) { } else afprintf(dbOut
, " %pFoamTypes\n", stmt); }; }; } }; }
;
445 crinDEBUGif (!crinDebug) { } else afprintf(dbOut, ")\n");
446
447 crinApplyResult(target, result);
448
449 moreToDo = result->newGenerStep;
450
451 crinvResult = NULL((void*)0);
452 crinvInlinee = NULL((void*)0);
453
454 return moreToDo;
455}
456
457localstatic void
458crinApplyResult(CrinTarget target, CrinResult result)
459{
460 Foam prog = target->prog;
461 // Add Locals
462 Foam oldLocals = prog->foamProg.locals;
463 AInt sz = foamDDeclArgc(oldLocals)(((oldLocals)->hdr.argc) - (1)) + listLength(Foam)(Foam_listPointer->_Length)(result->newLocals);
464 Foam decls = foamNewDDeclEmpty(sz, oldLocals->foamDDecl.usage);
465 int idx = 0;
466
467 for (;idx < foamDDeclArgc(oldLocals)(((oldLocals)->hdr.argc) - (1)); idx++) {
468 decls->foamDDecl.argv[idx] = oldLocals->foamDDecl.argv[idx];
469 }
470 listIter(Foam, var, listNReverse(Foam)(result->newLocals), {{ { FoamList _l0; Foam var; for (_l0 = ((Foam_listPointer->
NReverse)(result->newLocals)); _l0; _l0 = ((_l0)->rest)
) { var = ((_l0)->first); { { decls->foamDDecl.argv[idx
++] = var; }; }; } }; }
471 decls->foamDDecl.argv[idx++] = var;{ { FoamList _l0; Foam var; for (_l0 = ((Foam_listPointer->
NReverse)(result->newLocals)); _l0; _l0 = ((_l0)->rest)
) { var = ((_l0)->first); { { decls->foamDDecl.argv[idx
++] = var; }; }; } }; }
472 }){ { FoamList _l0; Foam var; for (_l0 = ((Foam_listPointer->
NReverse)(result->newLocals)); _l0; _l0 = ((_l0)->rest)
) { var = ((_l0)->first); { { decls->foamDDecl.argv[idx
++] = var; }; }; } }; }
;
473 prog->foamProg.locals = decls;
474
475 // Sort environment
476 crinApplyResultEnvRefs(target, result);
477
478 // Replace call with setup (nb: We will flatten the whole later)
479 Foam seq = foamNewOfList(FOAM_Seq, listNReverse(Foam)(Foam_listPointer->NReverse)(result->setupStmts));
480 fptrSet(target->call, seq);
481
482 // Stomp in variable references
483 listIter(FoamPtr, valueRef, target->values, {{ { FoamPtrList _l0; FoamPtr valueRef; for (_l0 = (target->
values); _l0; _l0 = ((_l0)->rest)) { valueRef = ((_l0)->
first); { { fptrSet(valueRef, foamNew(FOAM_Loc, 1, (AInt)(result
->resultVar))); }; }; } }; }
484 fptrSet(valueRef, foamNewLoc(result->resultVar));{ { FoamPtrList _l0; FoamPtr valueRef; for (_l0 = (target->
values); _l0; _l0 = ((_l0)->rest)) { valueRef = ((_l0)->
first); { { fptrSet(valueRef, foamNew(FOAM_Loc, 1, (AInt)(result
->resultVar))); }; }; } }; }
485 }){ { FoamPtrList _l0; FoamPtr valueRef; for (_l0 = (target->
values); _l0; _l0 = ((_l0)->rest)) { valueRef = ((_l0)->
first); { { fptrSet(valueRef, foamNew(FOAM_Loc, 1, (AInt)(result
->resultVar))); }; }; } }; }
;
486 // Replace GenerStep with goto
487 if (target->bb != NULL((void*)0)) {
488 BBlock bb = target->bb;
489 bb->kind = FOAM_Goto;
490 bbSetExitC(bb, 1)((bb)->exits->pos = (1));
491 Foam outLabel = foamNewLabel(result->outLabel)foamNew(FOAM_Label, 1, (AInt)(result->outLabel));
492 Foam nextGoto = foamNewGoto(bbExit(bb, 0))foamNew(FOAM_Goto, 1, (AInt)(((bb)->exits->argv[0])));
493 result->stmts = listCons(Foam)(Foam_listPointer->Cons)(outLabel, result->stmts);
494 result->stmts = listCons(Foam)(Foam_listPointer->Cons)(nextGoto, result->stmts);
495 }
496 else {
497 Foam outLabel = foamNewLabel(result->outLabel)foamNew(FOAM_Label, 1, (AInt)(result->outLabel));
498 result->stmts = listCons(Foam)(Foam_listPointer->Cons)(outLabel, result->stmts);
499 }
500
501 FoamList whole = listNReverse(Foam)(Foam_listPointer->NReverse)(result->stmts);
502 fptrSet(target->step, foamNewSeqOfList(whole));
503 // Clean up nested seq
504 //prog->foamProg.body = utilMakeFlatSeq(prog->foamProg.body);
505 prog->foamProg.nLabels = result->maxLabel + 1;
506
507
508 if (target->bb != NULL((void*)0)) {
509 flogPrintDb(target->bb->graph);
510 }
511 else {
512 crinDEBUGif (!crinDebug) { } else afprintf(dbOut, "Applied:\n%pFoamTypes\n", prog);
513 }
514}
515
516localstatic void
517crinSetCRVars()
518{
519 // Return var - FIXME: Type
520 Foam retDecl = foamNewDecl(FOAM_Word, strCopy("crRet"), emptyFormatSlot)foamNew(FOAM_Decl,4,(AInt)(FOAM_Word),strCopy("crRet"), (AInt
) (0x7FFF), 4)
;
521 crinvResult->tmpVarBase = foamDDeclArgc(crinvResult->target->prog->foamProg.locals)(((crinvResult->target->prog->foamProg.locals)->hdr
.argc) - (1))
;
522 crinvResult->resultVar = crinAllocateLocal(retDecl);
523 // Step Var
524 Foam stepDecl = foamNewDecl(FOAM_SInt, strCopy("step"), emptyFormatSlot)foamNew(FOAM_Decl,4,(AInt)(FOAM_SInt),strCopy("step"), (AInt)
(0x7FFF), 4)
;
525 crinvResult->stepVar = crinAllocateLocal(stepDecl);
526 // outLabel
527 crinvResult->outLabel = crinAllocateLabels(1);
528
529 crinAddSetupStatement(foamNewSet(foamNewLoc(crinvResult->stepVar), foamNewSInt(0))foamNew(FOAM_Set, 2, foamNew(FOAM_Loc, 1, (AInt)(crinvResult->
stepVar)), foamNew(FOAM_SInt, 1, (AInt)(0)))
);
530}
531
532localstatic void
533crinSetEnvRefs()
534{
535 crinvResult->envRefs = foamNewDEnvUnused(foamDEnvArgc(crinvResult->target->prog->foamProg.levels)((crinvResult->target->prog->foamProg.levels)->hdr
.argc)
);
536}
537
538localstatic void
539crinTransformAddParams(CrinInlinee inlinee)
540{
541}
542
543localstatic void
544crinTransformAddLocals(CrinInlinee inlinee)
545{
546 // Fixme: crinvAddLocalsDDecl
547 Foam locals = inlinee->prog->foamProg.locals;
548 crinvResult->localBase = crinvResult->tmpVarBase;
549 for (int i=0; i<foamDDeclArgc(locals)(((locals)->hdr.argc) - (1)); i++) {
550 crinAllocateLocal(foamCopy(locals->foamDDecl.argv[i]));
551 }
552}
553
554localstatic void
555crinTransformSetEnv(CrinInlinee inlinee)
556{
557 AInt fmt, var;
558
559 if (!inlEnvHasEnv0(inlinee->env)) {
560 return;
561 }
562
563 fmt = inlinee->prog->foamProg.levels->foamDEnv.argv[0];
564 var = crinAllocateLocal(foamNewDecl(FOAM_Env, strCopy("e"), emptyFormatSlot)foamNew(FOAM_Decl,4,(AInt)(FOAM_Env),strCopy("e"), (AInt) (0x7FFF
), 4)
);
565 inlEnvSetEnv0(inlinee->env, foamNewLoc(var)foamNew(FOAM_Loc, 1, (AInt)(var)));
566 crinAddSetupStatement(foamNewSet(foamNewLoc(var), foamNewPushEnv(fmt, foamCopy(inlinee->env->env1)))foamNew(FOAM_Set, 2, foamNew(FOAM_Loc, 1, (AInt)(var)), foamNew
(FOAM_PushEnv,2,fmt,foamCopy(inlinee->env->env1)))
);
567}
568
569localstatic void
570crinApplyResultEnvRefs(CrinTarget target, CrinResult result)
571{
572 Foam prog = target->prog;
573 Foam levels = prog->foamProg.levels;
574 AInt i;
575 for (i=0; i<foamArgc(levels)((levels)->hdr.argc); i++) {
576 AInt newUsage = result->envRefs->foamDEnv.argv[i];
577 AInt oldUsage = levels->foamDEnv.argv[i];
578 if (newUsage != emptyFormatSlot4 && oldUsage != newUsage) {
579 if (oldUsage == emptyFormatSlot4 || oldUsage == envUsedSlot0) {
580 levels->foamDEnv.argv[i] = newUsage;
581 }
582 else {
583 bug("usage update error");
584 }
585 }
586 }
587}
588
589
590localstatic void
591crinTransformBody(CrinTarget target, CrinInlinee inlinee)
592{
593 Foam seq, control;
594 AInt labelBase;
595 AInt yieldBase;
596 AInt stepIdx;
597
598 yieldBase = crinAllocateLabels(1+inlinee->yieldCount);
599 labelBase = crinAllocateLabels(inlinee->labelCount);
600 stepIdx = 0;
601 crinAddStatement(foamNewSelectRange(foamNewLoc(crinvResult->stepVar)foamNew(FOAM_Loc, 1, (AInt)(crinvResult->stepVar)),
602 yieldBase,
603 1 + inlinee->yieldCount));
604 crinAddStatement(foamNewLabel(yieldBase + stepIdx)foamNew(FOAM_Label, 1, (AInt)(yieldBase + stepIdx)));
605 stepIdx++;
606
607 seq = inlinee->prog->foamProg.body;
608 assert(foamTag(seq) == FOAM_Seq)do { if (!(((seq)->hdr.tag) == FOAM_Seq)) _do_assert(("foamTag(seq) == FOAM_Seq"
),"of_crinlin.c",608); } while (0)
;
609
610 for (int i=0; i<foamArgc(seq)((seq)->hdr.argc); i++) {
611 Foam foam = seq->foamSeq.argv[i];
612 switch (foamTag(foam)((foam)->hdr.tag)) {
613 case FOAM_Label:
614 crinAddStatement(foamNewLabel(crinLabelIndex(labelBase, foam->foamLabel.label))foamNew(FOAM_Label, 1, (AInt)(crinLabelIndex(labelBase, foam->
foamLabel.label)))
);
615 break;
616 case FOAM_Goto:
617 crinAddStatement(foamNewGoto(crinLabelIndex(labelBase, foam->foamLabel.label))foamNew(FOAM_Goto, 1, (AInt)(crinLabelIndex(labelBase, foam->
foamLabel.label)))
);
618 break;
619 case FOAM_GenerStep:
620 crinAddStatement(foamNewGenerStep(crinLabelIndex(labelBase, foam->foamGenerStep.label),foamNew(FOAM_GenerStep, 2, crinLabelIndex(labelBase, foam->
foamGenerStep.label), crinTransformExpr(foamCopy(foam->foamGenerStep
.gener)))
621 crinTransformExpr(foamCopy(foam->foamGenerStep.gener)))foamNew(FOAM_GenerStep, 2, crinLabelIndex(labelBase, foam->
foamGenerStep.label), crinTransformExpr(foamCopy(foam->foamGenerStep
.gener)))
);
622 break;
623 case FOAM_If:
624 crinAddStatement(foamNewIf(crinTransformExpr(foamCopy(foam->foamIf.test)),foamNew(FOAM_If, 2, crinTransformExpr(foamCopy(foam->foamIf
.test)), crinLabelIndex(labelBase, foam->foamIf.label))
625 crinLabelIndex(labelBase, foam->foamIf.label))foamNew(FOAM_If, 2, crinTransformExpr(foamCopy(foam->foamIf
.test)), crinLabelIndex(labelBase, foam->foamIf.label))
);
626 break;
627 case FOAM_Select: {
628 Foam select = foamNewSelect(crinTransformExpr(foamCopy(foam->foamSelect.op)), foamSelectArgc(foam)(((foam)->hdr.argc) - 1));
629 int i;
630 for (i=0; i<foamSelectArgc(select)(((select)->hdr.argc) - 1); i++)
631 select->foamSelect.argv[i] = crinLabelIndex(labelBase, foam->foamSelect.argv[i]);
632 crinAddStatement(select);
633 break;
634 }
635 case FOAM_Yield: {
636 crinAddStatement(foamNewSet(foamNewLoc(crinvResult->resultVar),foamNew(FOAM_Set, 2, foamNew(FOAM_Loc, 1, (AInt)(crinvResult->
resultVar)), crinTransformExpr(foamCopy(foam->foamYield.value
)))
637 crinTransformExpr(foamCopy(foam->foamYield.value)))foamNew(FOAM_Set, 2, foamNew(FOAM_Loc, 1, (AInt)(crinvResult->
resultVar)), crinTransformExpr(foamCopy(foam->foamYield.value
)))
);
638 crinAddStatement(foamNewSet(foamNewLoc(crinvResult->stepVar),foamNew(FOAM_Set, 2, foamNew(FOAM_Loc, 1, (AInt)(crinvResult->
stepVar)), foamNew(FOAM_SInt, 1, (AInt)(stepIdx)))
639 foamNewSInt(stepIdx))foamNew(FOAM_Set, 2, foamNew(FOAM_Loc, 1, (AInt)(crinvResult->
stepVar)), foamNew(FOAM_SInt, 1, (AInt)(stepIdx)))
);
640 crinAddStatement(foamNewGoto(crinvResult->outLabel)foamNew(FOAM_Goto, 1, (AInt)(crinvResult->outLabel)));
641 crinAddStatement(foamNewLabel(yieldBase + stepIdx)foamNew(FOAM_Label, 1, (AInt)(yieldBase + stepIdx)));
642 stepIdx++;
643 break;
644 }
645 case FOAM_Return:
646 crinAddStatement(foamNewGoto(target->doneLabel)foamNew(FOAM_Goto, 1, (AInt)(target->doneLabel)));
647 break;
648 default:
649 crinAddStatement(crinTransformExpr(foamCopy(foam)));
650 }
651 }
652 crinvResult = NULL((void*)0);
653}
654
655localstatic AInt
656crinAllocateLocal(Foam foam)
657{
658 return crinResultAllocateLocal(crinvResult, foam);
659}
660
661localstatic void
662crinAddSetupStatement(Foam foam)
663{
664 crinResultAddSetupStatement(crinvResult, foam);
665}
666
667localstatic void
668crinAddStatement(Foam foam)
669{
670 crinResultAddStatement(crinvResult, foam);
671}
672
673localstatic AInt
674crinLabelIndex(AInt labelBase, AInt index)
675{
676 // FIXME: Are labels contiguous?
677 return labelBase + index;
678}
679
680localstatic AInt
681crinAllocateLabels(AInt count)
682{
683 // FIXME: Need 'result' specific version
684 AInt label0 = crinvResult->maxLabel;
685 crinvResult->maxLabel += count;
686 return label0;
687}
688
689
690localstatic Foam
691crinTransformExpr(Foam expr)
692{
693 foamIter(expr, arg, *arg = crinTransformExpr(*arg)){ { String argf = (foamInfoTable [(int)(((expr)->hdr.tag))
-(int)FOAM_START]).argf; Length _i; for (_i = 0; _i < ((expr
)->hdr.argc); _i++, argf++) { if (*argf == '*') argf--; if
(*argf == 'C') { Foam *arg = (Foam *) ((expr)->foamGen.argv
)+_i; { *arg = crinTransformExpr(*arg); }; } } }; }
;
694
695 switch (foamTag(expr)((expr)->hdr.tag)) {
696 case FOAM_Loc:
697 return foamNewLoc(crinTransformLocalId(expr->foamLoc.index))foamNew(FOAM_Loc, 1, (AInt)(crinTransformLocalId(expr->foamLoc
.index)))
;
698 case FOAM_Lex:
699 return crinTransformLex(expr);
700 case FOAM_Env:
701 return crinTransformEnv(expr);
702 case FOAM_EElt:
703 return crinTransformEElt(expr);
704 default:
705 return expr;
706 }
707}
708
709localstatic Foam
710crinTransformLex(Foam lex)
711{
712 Foam foam = inlEnvTransformLex(crinvInlinee->env, lex);
713 if (foamSyme(lex)((lex)->hdr.syme) != NULL((void*)0)) {
714 Syme syme = inlSubstStateSyme(crinvInlinee->substState, foamSyme(lex)((lex)->hdr.syme));
715 if (syme != NULL((void*)0))
716 foamSyme(foam)((foam)->hdr.syme) = syme;
717 }
718 else {
719 AInt format = foamProgFormatForLevel(crinvInlinee->prog, lex->foamLex.level);
720 AInt index = lex->foamLex.index;
721 Foam decl = crinGetDecl(format, index);
722 Syme syme = foamSyme(decl)((decl)->hdr.syme);
723 if (syme != NULL((void*)0))
724 syme = inlSubstStateSyme(crinvInlinee->substState, syme);
725 foamSyme(foam)((foam)->hdr.syme) = syme;
726 }
727 if (foamTag(foam)((foam)->hdr.tag) == FOAM_Lex) {
728 crinEnvSetUsage(foam->foamLex.level, foamProgFormatForLevel(crinvInlinee->prog, lex->foamLex.level));
729 }
730 return foam;
731}
732
733localstatic Foam
734crinTransformEElt(Foam foam)
735{
736 if (foamSyme(foam)((foam)->hdr.syme) != NULL((void*)0)) {
737 Syme syme = inlSubstStateSyme(crinvInlinee->substState, foamSyme(foam)((foam)->hdr.syme));
738 if (syme != NULL((void*)0))
739 foamSyme(foam)((foam)->hdr.syme) = syme;
740 }
741 else {
742 AInt index = foam->foamEElt.lex;
743 Foam decl = crinGetDecl(foam->foamEElt.env, index);
744 Syme syme = foamSyme(decl)((decl)->hdr.syme);
745 foamSyme(foam)((foam)->hdr.syme) = syme;
746 }
747 return foam;
748}
749
750localstatic Foam
751crinGetDecl(AInt format, AInt index)
752{
753 Foam ddecl = crinvUnit->unit->foamUnit.formats->foamDFmt.argv[format];
754 assert(index < foamDDeclArgc(ddecl))do { if (!(index < (((ddecl)->hdr.argc) - (1)))) _do_assert
(("index < foamDDeclArgc(ddecl)"),"of_crinlin.c",754); } while
(0)
;
755 return ddecl->foamDDecl.argv[index];
756}
757
758
759localstatic void
760crinEnvSetUsage(AInt level, AInt format)
761{
762 crinResultEnvSetUsage(crinvResult, level, format);
763}
764
765localstatic Foam
766crinTransformEnv(Foam env)
767{
768 env = inlEnvTransformEnv(crinvInlinee->env, env);
769 return env;
770}
771
772
773localstatic AInt
774crinTransformLocalId(AInt id)
775{
776 return crinvResult->localBase + id;
777}
778
779localstatic CrinResult
780crinNewResult(CrinTarget target)
781{
782 CrinResult res = (CrinResult) stoAlloc(OB_Other0, sizeof(*res));
783 res->target = target;
784 res->tmpVarBase = -1;
785 res->localBase = -1;
786 res->labelBase = -1;
787 res->maxLabel = target->prog->foamProg.nLabels;
788 res->stepVar = 0;
789 res->resultVar = 0;
790 res->nExtraLabels = 0;
791 res->newLocals = listNil(Foam)((FoamList) 0);
792 res->setupStmts = listNil(Foam)((FoamList) 0);
793 res->stmts = listNil(Foam)((FoamList) 0);
794 res->newGenerStep = false((int) 0);
795 res->envRefs = NULL((void*)0);
796 return res;
797}
798
799
800localstatic AInt
801crinResultAllocateLocal(CrinResult result, Foam decl)
802{
803 AInt idx = result->tmpVarBase;
804 result->newLocals = listCons(Foam)(Foam_listPointer->Cons)(decl, result->newLocals);
805 result->tmpVarBase++;
806 return idx;
807}
808
809localstatic void
810crinResultAddSetupStatement(CrinResult result, Foam stmt)
811{
812 result->setupStmts = listCons(Foam)(Foam_listPointer->Cons)(stmt, result->setupStmts);
813}
814
815localstatic void
816crinResultAddStatement(CrinResult result, Foam stmt)
817{
818 if (foamTag(stmt)((stmt)->hdr.tag) == FOAM_GenerStep) {
819 result->newGenerStep = true1;
820 }
821 result->stmts = listCons(Foam)(Foam_listPointer->Cons)(stmt, result->stmts);
822}
823
824localstatic void
825crinResultEnvSetUsage(CrinResult result, AInt level, AInt format)
826{
827 AInt oldUsage = result->envRefs->foamDEnv.argv[level];
828 if (oldUsage == format)
829 return;
830 assert(oldUsage == emptyFormatSlot || oldUsage == envUsedSlot)do { if (!(oldUsage == 4 || oldUsage == 0)) _do_assert(("oldUsage == emptyFormatSlot || oldUsage == envUsedSlot"
),"of_crinlin.c",830); } while (0)
;
831 result->envRefs->foamDEnv.argv[level] = format;
832}
833
834/*
835 * :: Identifying GenIter calls
836 *
837 * Iterates over the current flow graph and finds calls to
838 * GenIter (or similar).
839 * Also adds Step calls..
840 */
841
842localstatic void crinProgFindCandidatesExpr(FoamPtr ptr, BBlock bb, GenCallInfoList *candidates);
843
844GenCallInfoList
845crinProgFindCandidates(Foam foam)
846{
847 GenCallInfoList ll = listNil(GenCallInfo)((GenCallInfoList) 0);
848 FlowGraph flog;
849 flog = foamOptInfo(foam)((foam)->hdr.info.opt) == NULL((void*)0) ? NULL((void*)0) : foamOptInfo(foam)((foam)->hdr.info.opt)->flog;
850
851 if (flog != NULL((void*)0)) {
852 flogIter(flog, bb, {{ { int _i; BBlock bb; for (_i = 0; _i < ((flog)->blocks
->pos); _i++) { bb = bbufBlockFn((flog)->blocks,_i); if
(!bb) continue; { { { { String argf = (foamInfoTable [(int)(
((bb->code)->hdr.tag))-(int)FOAM_START]).argf; Length _i
; for (_i = 0; _i < ((bb->code)->hdr.argc); _i++, argf
++) { if (*argf == '*') argf--; if (*argf == 'C') { Foam *expr
= (Foam *) ((bb->code)->foamGen.argv)+_i; { crinProgFindCandidatesExpr
(fptrNew(crinvFindContext, bb->code, _i), bb, &ll); };
} } }; }; }; }; } }; }
853 foamIter(bb->code, expr,{ { int _i; BBlock bb; for (_i = 0; _i < ((flog)->blocks
->pos); _i++) { bb = bbufBlockFn((flog)->blocks,_i); if
(!bb) continue; { { { { String argf = (foamInfoTable [(int)(
((bb->code)->hdr.tag))-(int)FOAM_START]).argf; Length _i
; for (_i = 0; _i < ((bb->code)->hdr.argc); _i++, argf
++) { if (*argf == '*') argf--; if (*argf == 'C') { Foam *expr
= (Foam *) ((bb->code)->foamGen.argv)+_i; { crinProgFindCandidatesExpr
(fptrNew(crinvFindContext, bb->code, _i), bb, &ll); };
} } }; }; }; }; } }; }
854 crinProgFindCandidatesExpr(fptrNew(crinvFindContext,{ { int _i; BBlock bb; for (_i = 0; _i < ((flog)->blocks
->pos); _i++) { bb = bbufBlockFn((flog)->blocks,_i); if
(!bb) continue; { { { { String argf = (foamInfoTable [(int)(
((bb->code)->hdr.tag))-(int)FOAM_START]).argf; Length _i
; for (_i = 0; _i < ((bb->code)->hdr.argc); _i++, argf
++) { if (*argf == '*') argf--; if (*argf == 'C') { Foam *expr
= (Foam *) ((bb->code)->foamGen.argv)+_i; { crinProgFindCandidatesExpr
(fptrNew(crinvFindContext, bb->code, _i), bb, &ll); };
} } }; }; }; }; } }; }
855 bb->code, _i),{ { int _i; BBlock bb; for (_i = 0; _i < ((flog)->blocks
->pos); _i++) { bb = bbufBlockFn((flog)->blocks,_i); if
(!bb) continue; { { { { String argf = (foamInfoTable [(int)(
((bb->code)->hdr.tag))-(int)FOAM_START]).argf; Length _i
; for (_i = 0; _i < ((bb->code)->hdr.argc); _i++, argf
++) { if (*argf == '*') argf--; if (*argf == 'C') { Foam *expr
= (Foam *) ((bb->code)->foamGen.argv)+_i; { crinProgFindCandidatesExpr
(fptrNew(crinvFindContext, bb->code, _i), bb, &ll); };
} } }; }; }; }; } }; }
856 bb,{ { int _i; BBlock bb; for (_i = 0; _i < ((flog)->blocks
->pos); _i++) { bb = bbufBlockFn((flog)->blocks,_i); if
(!bb) continue; { { { { String argf = (foamInfoTable [(int)(
((bb->code)->hdr.tag))-(int)FOAM_START]).argf; Length _i
; for (_i = 0; _i < ((bb->code)->hdr.argc); _i++, argf
++) { if (*argf == '*') argf--; if (*argf == 'C') { Foam *expr
= (Foam *) ((bb->code)->foamGen.argv)+_i; { crinProgFindCandidatesExpr
(fptrNew(crinvFindContext, bb->code, _i), bb, &ll); };
} } }; }; }; }; } }; }
857 &ll));{ { int _i; BBlock bb; for (_i = 0; _i < ((flog)->blocks
->pos); _i++) { bb = bbufBlockFn((flog)->blocks,_i); if
(!bb) continue; { { { { String argf = (foamInfoTable [(int)(
((bb->code)->hdr.tag))-(int)FOAM_START]).argf; Length _i
; for (_i = 0; _i < ((bb->code)->hdr.argc); _i++, argf
++) { if (*argf == '*') argf--; if (*argf == 'C') { Foam *expr
= (Foam *) ((bb->code)->foamGen.argv)+_i; { crinProgFindCandidatesExpr
(fptrNew(crinvFindContext, bb->code, _i), bb, &ll); };
} } }; }; }; }; } }; }
858 }){ { int _i; BBlock bb; for (_i = 0; _i < ((flog)->blocks
->pos); _i++) { bb = bbufBlockFn((flog)->blocks,_i); if
(!bb) continue; { { { { String argf = (foamInfoTable [(int)(
((bb->code)->hdr.tag))-(int)FOAM_START]).argf; Length _i
; for (_i = 0; _i < ((bb->code)->hdr.argc); _i++, argf
++) { if (*argf == '*') argf--; if (*argf == 'C') { Foam *expr
= (Foam *) ((bb->code)->foamGen.argv)+_i; { crinProgFindCandidatesExpr
(fptrNew(crinvFindContext, bb->code, _i), bb, &ll); };
} } }; }; }; }; } }; }
;
859 }
860 else {
861 foamIter(foam->foamProg.body, expr,{ { String argf = (foamInfoTable [(int)(((foam->foamProg.body
)->hdr.tag))-(int)FOAM_START]).argf; Length _i; for (_i = 0
; _i < ((foam->foamProg.body)->hdr.argc); _i++, argf
++) { if (*argf == '*') argf--; if (*argf == 'C') { Foam *expr
= (Foam *) ((foam->foamProg.body)->foamGen.argv)+_i; {
crinProgFindCandidatesExpr(fptrNew(crinvFindContext, foam->
foamProg.body, _i), ((void*)0), &ll); }; } } }; }
862 crinProgFindCandidatesExpr(fptrNew(crinvFindContext, foam->foamProg.body, _i), NULL, &ll)){ { String argf = (foamInfoTable [(int)(((foam->foamProg.body
)->hdr.tag))-(int)FOAM_START]).argf; Length _i; for (_i = 0
; _i < ((foam->foamProg.body)->hdr.argc); _i++, argf
++) { if (*argf == '*') argf--; if (*argf == 'C') { Foam *expr
= (Foam *) ((foam->foamProg.body)->foamGen.argv)+_i; {
crinProgFindCandidatesExpr(fptrNew(crinvFindContext, foam->
foamProg.body, _i), ((void*)0), &ll); }; } } }; }
;
863 }
864 listNMap(GenCallInfo)(GenCallInfo_listPointer->NMap)(crinProgFillVar, ll);
865 return ll;
866}
867
868
869localstatic GenCallInfo
870crinProgFillVar(GenCallInfo info)
871{
872 Foam var = crinProgFind(info);
873 if (var == NULL((void*)0)) {
874 crgcInfoFree(info);
875 return NULL((void*)0);
876 }
877
878 foamDereferenceCast(var)while (((var)->hdr.tag) == FOAM_Cast) (var) = (var)->foamCast
.expr;
;
879
880 if (foamTag(var)((var)->hdr.tag) != FOAM_Gener) {
881 crgcInfoFree(info);
882 return NULL((void*)0);
883 }
884 if (foamTag(var->foamGener.prog)((var->foamGener.prog)->hdr.tag) != FOAM_Const) {
885 crgcInfoFree(info);
886 return NULL((void*)0);
887 }
888 info->generSource = var;
889 info->progId = var->foamGener.prog->foamConst.index;
890 info->progCR = crinUnitFindConst(var->foamGener.prog->foamConst.index);
891 if (info->progCR->foamProg.body == NULL((void*)0)) {
892 info->progCR = flogToProg(foamOptInfo(info->progCR)((info->progCR)->hdr.info.opt)->flog);
893 }
894 info->envCR = var->foamGener.env;
895 if (info->progCR == NULL((void*)0)) {
896 crgcInfoFree(info);
897 return NULL((void*)0);
898 }
899 return info;
900}
901
902localstatic Foam
903crinProgFind(GenCallInfo info)
904{
905 FoamPtr genIter = info->genIter;
906 Foam rhs, g;
907 if (genIter == NULL((void*)0)) {
908 return NULL((void*)0);
909 }
910 rhs = fptrVal(genIter)->foamSet.rhs;
911 assert(foamTag(rhs) == FOAM_GenIter)do { if (!(((rhs)->hdr.tag) == FOAM_GenIter)) _do_assert((
"foamTag(rhs) == FOAM_GenIter"),"of_crinlin.c",911); } while (
0)
;
912
913 g = rhs->foamGenIter.gener;
914 foamDereferenceCast(g)while (((g)->hdr.tag) == FOAM_Cast) (g) = (g)->foamCast
.expr;
;
915
916 if (foamTag(g)((g)->hdr.tag) == FOAM_Loc || foamTag(g)((g)->hdr.tag) == FOAM_Lex) {
917 }
918 if (foamTag(g)((g)->hdr.tag) == FOAM_Gener) {
919 return g;
920 }
921
922 // Next: Look at flow graph...
923 Foam ref = crinDerefGener(g);
924 if (ref == NULL((void*)0)) {
925 crinDEBUGif (!crinDebug) { } else afprintf(dbOut, "Failed to find ref for %pFoam\n", fptrVal(genIter));
926 return NULL((void*)0);
927 }
928
929 crinDEBUGif (!crinDebug) { } else afprintf(dbOut, "Switched %pFoam --> %pFoam\n", g, ref);
930 foamDereferenceCast(ref)while (((ref)->hdr.tag) == FOAM_Cast) (ref) = (ref)->foamCast
.expr;
; // NB: Cancel casts nicely
931 return ref;
932}
933
934localstatic Foam
935crinDerefGener(Foam foam)
936{
937 switch (foamTag(foam)((foam)->hdr.tag)) {
938 case FOAM_Gener:
939 return foam;
940 case FOAM_Cast: {
941 Foam inner = crinDerefGener(foam->foamCast.expr);
942 if (inner == NULL((void*)0))
943 return NULL((void*)0);
944 else
945 return foamNewCast(foam->foamCast.type, inner)foamNew(FOAM_Cast, 2, foam->foamCast.type, inner);
946 }
947 case FOAM_Loc:
948 case FOAM_Lex:
949 return crinDerefReference(foam);
950 default:
951 return NULL((void*)0);
952 }
953}
954
955localstatic Foam
956crinDerefReference(Foam foam)
957{
958 Foam ref;
959 if (foamOptInfo(foam)((foam)->hdr.info.opt) == NULL((void*)0))
960 return NULL((void*)0);
961 ref = (Foam) foam->foamGen.hdr.info.defList;
962 if (ref == NULL((void*)0))
963 return NULL((void*)0);
964 switch (foamTag(ref)((ref)->hdr.tag)) {
965 case FOAM_Def:
966 case FOAM_Set:
967 return crinDerefGener(ref->foamDef.rhs);
968 default:
969 return NULL((void*)0);
970 }
971}
972
973localstatic void
974crinProgFindCandidatesExpr(FoamPtr ptr, BBlock bb, GenCallInfoList *candidates)
975{
976 Foam expr = fptrVal(ptr);
977
978 foamIter(expr, subexpr, crinProgFindCandidatesExpr(fptrNew(crinvFindContext, expr, _i), bb, candidates)){ { String argf = (foamInfoTable [(int)(((expr)->hdr.tag))
-(int)FOAM_START]).argf; Length _i; for (_i = 0; _i < ((expr
)->hdr.argc); _i++, argf++) { if (*argf == '*') argf--; if
(*argf == 'C') { Foam *subexpr = (Foam *) ((expr)->foamGen
.argv)+_i; { crinProgFindCandidatesExpr(fptrNew(crinvFindContext
, expr, _i), bb, candidates); }; } } }; }
;
979
980 switch (foamTag(expr)((expr)->hdr.tag)) {
981 case FOAM_Def:
982 case FOAM_Set:
983 if (foamTag(expr->foamSet.rhs)((expr->foamSet.rhs)->hdr.tag) == FOAM_GenIter) {
984 crgcAddIter(ptr, bb, candidates);
985 }
986 else {
987 fptrFree(ptr);
988 }
989 break;
990 case FOAM_GenerValue:
991 crgcAddValue(ptr, bb, candidates);
992 break;
993 case FOAM_GenerStep:
994 crgcAddStep(ptr, bb, candidates);
995 break;
996 default:
997 fptrFree(ptr);
998 }
999}
1000
1001localstatic void
1002crgcAddIter(FoamPtr ptr, BBlock bb, GenCallInfoList *candidates)
1003{
1004 GenCallInfo info;
1005 GenCallInfoList ll;
1006 Foam expr;
1007 Foam var;
1008 AInt varId;
1009
1010 expr = fptrVal(ptr);
1011 assert(foamTag(expr) == FOAM_Set || foamTag(expr) == FOAM_Def)do { if (!(((expr)->hdr.tag) == FOAM_Set || ((expr)->hdr
.tag) == FOAM_Def)) _do_assert(("foamTag(expr) == FOAM_Set || foamTag(expr) == FOAM_Def"
),"of_crinlin.c",1011); } while (0)
;
1012 if (foamTag(expr->foamSet.lhs)((expr->foamSet.lhs)->hdr.tag) != FOAM_Loc) {
1013 fptrFree(ptr);
1014 return;
1015 }
1016 var = expr->foamSet.lhs;
1017 varId = var->foamLoc.index;
1018 info = crgcFindRef(*candidates, varId);
1019
1020 if (info == NULL((void*)0)) {
1021 info = crgcInfoNew(varId);
1022 *candidates = listCons(GenCallInfo)(GenCallInfo_listPointer->Cons)(info, *candidates);
1023 }
1024
1025 assert(info->genIter == NULL)do { if (!(info->genIter == ((void*)0))) _do_assert(("info->genIter == NULL"
),"of_crinlin.c",1025); } while (0)
;
1026 info->genIter = ptr;
1027}
1028
1029localstatic void
1030crgcAddValue(FoamPtr ptr, BBlock bb, GenCallInfoList *candidates)
1031{
1032 Foam expr;
1033 AInt varId;
1034
1035 expr = fptrVal(ptr);
1036 assert(foamTag(expr) == FOAM_GenerValue)do { if (!(((expr)->hdr.tag) == FOAM_GenerValue)) _do_assert
(("foamTag(expr) == FOAM_GenerValue"),"of_crinlin.c",1036); }
while (0)
;
1037 varId = expr->foamGenerValue.gener->foamLoc.index;
1038
1039 GenCallInfo info = crgcFindRef(*candidates, varId);
1040 if (info == NULL((void*)0)) {
1041 info = crgcInfoNew(varId);
1042 *candidates = listCons(GenCallInfo)(GenCallInfo_listPointer->Cons)(info, *candidates);
1043 }
1044 info->values = listCons(FoamPtr)(FoamPtr_listPointer->Cons)(ptr, info->values);
1045}
1046
1047localstatic void
1048crgcAddStep(FoamPtr ptr, BBlock bb, GenCallInfoList *candidates)
1049{
1050 Foam expr;
1051 AInt varId;
1052 expr = fptrVal(ptr);
1053
1054 assert(foamTag(expr) == FOAM_GenerStep)do { if (!(((expr)->hdr.tag) == FOAM_GenerStep)) _do_assert
(("foamTag(expr) == FOAM_GenerStep"),"of_crinlin.c",1054); } while
(0)
;
1055 varId = expr->foamGenerStep.gener->foamLoc.index;
1056
1057 GenCallInfo info = crgcFindRef(*candidates, varId);
1058 if (info == NULL((void*)0)) {
1059 info = crgcInfoNew(varId);
1060 *candidates = listCons(GenCallInfo)(GenCallInfo_listPointer->Cons)(info, *candidates);
1061 }
1062 info->bbs = listCons(BBlock)(BBlock_listPointer->Cons)(bb, info->bbs);
1063 info->steps = listCons(FoamPtr)(FoamPtr_listPointer->Cons)(ptr, info->steps);
1064}
1065
1066localstatic GenCallInfo
1067crgcInfoNew(AInt varId)
1068{
1069 GenCallInfo info = (GenCallInfo) stoAlloc(OB_Other0, sizeof(*info));
1070 info->varId = varId;
1071 info->generSource = NULL((void*)0);
1072 info->genIter = NULL((void*)0);
1073 info->progCR = NULL((void*)0);
1074 info->envCR = NULL((void*)0);
1075 info->bbs = listNil(BBlock)((BBlockList) 0);
1076 info->steps = listNil(FoamPtr)((FoamPtrList) 0);
1077 info->values = listNil(FoamPtr)((FoamPtrList) 0);
1078
1079 return info;
1080}
1081
1082localstatic void
1083crgcInfoFree(GenCallInfo info)
1084{
1085 listIter(FoamPtr, step, info->steps, fptrFree(step)){ { FoamPtrList _l0; FoamPtr step; for (_l0 = (info->steps
); _l0; _l0 = ((_l0)->rest)) { step = ((_l0)->first); {
fptrFree(step); }; } }; }
;
1086 listIter(FoamPtr, val, info->values, fptrFree(val)){ { FoamPtrList _l0; FoamPtr val; for (_l0 = (info->values
); _l0; _l0 = ((_l0)->rest)) { val = ((_l0)->first); { fptrFree
(val); }; } }; }
;
1087 if (info->genIter != NULL((void*)0))
1088 fptrFree(info->genIter);
1089 stoFree(info);
1090}
1091
1092
1093localstatic GenCallInfo
1094crgcFindRef(GenCallInfoList lst, AInt id)
1095{
1096 while (lst != listNil(GenCallInfo)((GenCallInfoList) 0)) {
1097 GenCallInfo inf = car(lst)((lst)->first);
1098 lst = cdr(lst)((lst)->rest);
1099 if (inf->varId == id) {
1100 return inf;
1101 }
1102 }
1103 return NULL((void*)0);
1104}
1105