Bug Summary

File:src/of_rrfmt.c
Warning:line 244, column 2
Value stored to 'nlocs' 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_rrfmt.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_rrfmt.c
1
2/*****************************************************************************
3 *
4 * of_rrfmt.c: Dynamic format (RRFmt) optimizations.
5 *
6 * Copyright (c) 1990-2007 Aldor Software Organization Ltd (Aldor.org).
7 *
8 ****************************************************************************/
9
10/*****************************************************************************
11 * Dynamic formats are constants whose value can only be computed when the
12 * target program is executed, not at compile time. Although they are cheap
13 * to compute, dynamic formats need heap storage and tend to populate loop
14 * bodies rather than dominent blocks. As a result they are rarely available
15 * for optimisations such as common sub-expression elimination and their
16 * runtime computation prevents them being cfolded away. Repeatedly computing
17 * their value seriously degrades performance and churns heap memory.
18 *
19 * The semantics of raw records are as follows:
20 * - an RRNew returns a pointer to an area of memory that will be used
21 * to hold N elements of non-uniform data.
22 * - an RRElt returns a pointer into a block of memory representing the
23 * specified field of a raw record. Usually this pointer lies within
24 * a block of memory created by RRNew.
25 *
26 ****************************************************************************
27 * FIXME:
28 * - free bitv and bivClass objects
29 * - free any other objects we leave lying around
30 ****************************************************************************/
31
32#include "debug.h"
33#include "flog.h"
34#include "of_rrfmt.h"
35#include "optinfo.h"
36#include "util.h"
37#include "syme.h"
38#include "strops.h"
39#include "fbox.h"
40
41/*****************************************************************************
42 *
43 * :: Debugging
44 *
45 ****************************************************************************/
46
47Bool rrfmtDebug = false((int) 0);
48#define rrfmtDEBUGif (!rrfmtDebug) { } else afprintf DEBUG_IF(rrfmt)if (!rrfmtDebug) { } else afprintf
49
50/*****************************************************************************
51 *
52 * :: Local macros
53 *
54 ****************************************************************************/
55
56#define rrDF_CUTOFF(200) (200)
57
58/*****************************************************************************
59 *
60 * :: Local state
61 *
62 ****************************************************************************/
63
64static rrEmergeInfo rrInfo;
65
66/*****************************************************************************
67 *
68 * :: Local function declarations
69 *
70 ****************************************************************************/
71
72localstatic Foam rrProgEmerge (Foam /* prog */);
73localstatic Bool rrFlogEmerge (FlowGraph, Foam /* prog */);
74localstatic AInt rrCountDefs (BBlock);
75localstatic void rrFindEscapes (BBlock);
76localstatic void rrFindDefEscapes (Foam);
77localstatic void rr0FindDefEscapes (Foam, Foam, Foam);
78localstatic void rrDefEscapes (Foam);
79localstatic void rrDefNotEscapes (Foam);
80localstatic void rrFindDeepEscapes (Foam);
81localstatic void rrReconcileLocal (Foam);
82localstatic void rrReturnEscapes (Foam);
83localstatic void rrBCallEscapes (Foam);
84localstatic void rrCCallEscapes (Foam);
85localstatic void rrOCallEscapes (Foam);
86localstatic void rrPCallEscapes (Foam);
87localstatic void rrCallArgsEscape (Foam *, AInt);
88localstatic void rrLocalEscapes (Foam);
89localstatic void rr0LocalEscapes (Foam, Bitv, Bitv, Bitv);
90localstatic Bool rrNonEscapingLocal (Foam);
91localstatic Bool rr0NonEscapingLocal (Foam, Bitv, Bitv, Bitv);
92localstatic void rrReplace (BBlock);
93localstatic Foam rrReplaceDef (Foam, FoamList *);
94localstatic Foam rrReplaceDeeply (Foam);
95localstatic FoamTag rrSizeToType (Foam);
96localstatic FoamTag rrTypeToType (Foam);
97localstatic AInt rrNewRecordFmt (FoamTag, AInt);
98localstatic void rrInitFormats (Foam /* unit */);
99localstatic AInt rrAddFormat (Foam /* ddecl */);
100localstatic void rrMakeNewFormats (Foam /* unit */);
101localstatic AInt rrLookupRRFmt (Foam /* rrfmt */);
102localstatic void rrCacheRRFmt (Foam /* rrfmt */, AInt);
103localstatic AInt rrTranslateRRFmt (Foam /* rrfmt */);
104localstatic Bool rrFoamHasRRFmt (Foam);
105localstatic Bool rrIndepExpr (Foam);
106
107/*****************************************************************************
108 *
109 * :: Top-level entry points.
110 *
111 ****************************************************************************/
112
113
114/*
115 * This optimisation attempts to replace raw records with plain records
116 * in such a way that raw record semantics are preserved. The solution
117 * adopted here is to replace non-escaping raw records with plain records
118 * whose fields are pointers to individual records of the correct size.
119 * Then all RRElt instructions operating over non-escaping raw records
120 * can be replaced with RElt instructions.
121 *
122 * To do: allow raw records to be placed in globals, lexicals and parameters
123 * if we can show that these definitions do not escape. Raw records that are
124 * written to records and arrays can be ignored: if they don't escape then
125 * the emerger ought to replace them with locals that we can examine.
126 *
127 * To do: replace ALL non-escaping raw records with plain records. At the
128 * moment we only consider raw records whose format can be computed at
129 * compile time. However, with BCall StoAlloc we can allocate store based
130 * on the RawRepSize of the RRFmt type field. Hmm, what happens in LISP
131 * though - perhaps we only allow this optimisation for really special
132 * occasions?
133 */
134void
135rrUnitEmerge(Foam unit)
136{
137 AInt i;
138 Foam defs;
139
140 /* Sanity check */
141 assert(foamTag(unit) == FOAM_Unit)do { if (!(((unit)->hdr.tag) == FOAM_Unit)) _do_assert(("foamTag(unit) == FOAM_Unit"
),"of_rrfmt.c",141); } while (0)
;
142
143
144 /* Extract the top-level definitions */
145 defs = unit->foamUnit.defs;
146 assert(foamTag(defs) == FOAM_DDef)do { if (!(((defs)->hdr.tag) == FOAM_DDef)) _do_assert(("foamTag(defs) == FOAM_DDef"
),"of_rrfmt.c",146); } while (0)
;
147
148
149 /* Formats may change during optimisation */
150 rrInitFormats(unit);
151
152
153 /* Search for suitable progs */
154 for (i = 0;i < foamArgc(defs)((defs)->hdr.argc); i++)
155 {
156 Foam prog;
157 Foam def = defs->foamDDef.argv[i];
158
159
160 /* Sanity check */
161 assert(foamTag(def) == FOAM_Def)do { if (!(((def)->hdr.tag) == FOAM_Def)) _do_assert(("foamTag(def) == FOAM_Def"
),"of_rrfmt.c",161); } while (0)
;
162
163
164 /* We only care about progs */
165 prog = def->foamDef.rhs;
166 if (foamTag(prog)((prog)->hdr.tag) != FOAM_Prog) continue;
167
168
169 /* Replace the prog with an optimised version */
170 def->foamDef.rhs = rrProgEmerge(prog);
171 }
172
173
174 /* Rebuild the format declarations */
175 rrMakeNewFormats(unit);
176}
177
178
179/*****************************************************************************
180 *
181 * :: Prog-level optimisers
182 *
183 ****************************************************************************/
184
185/*
186 * Replace raw records in a prog with arrays or plain records
187 */
188localstatic Foam
189rrProgEmerge(Foam prog)
190{
191 FlowGraph flog;
192
193
194 /* Are there any RRFmt instructions in this prog? */
195 if (!rrFoamHasRRFmt(prog)) return prog;
196
197
198 /* We may need to create more locals */
199 rrInfo.locals = vpNew(fboxNew(prog->foamProg.locals));
200
201
202 /* Create a flow-graph for optimisation */
203 flog = flogFrProg(prog, FLOG_UniqueExit);
204
205
206 /* cprop the prog to make RRFmts available */
207 cpFlog(flog);
208
209
210 /* Compute all the reaching definitions and merge */
211 if (usedefChainsFrFlog(flog, UD_OUTPUT_UdList))
212 {
213 if (rrFlogEmerge(flog, prog))
214 optSetDeadvPending(prog)(((prog)->hdr.info.opt)->optMask |= (1 << 3));
215 }
216
217
218 /* Rebuild the locals vector */
219 prog->foamProg.locals = fboxMake(rrInfo.locals->fbox);
220
221
222 /* Rebuild the prog and return */
223 prog = flogToProg(flog);
224 return prog;
225}
226
227
228localstatic Bool
229rrFlogEmerge(FlowGraph flog, Foam prog)
230{
231 /*
232 * Determine which raw record locals don't escape. Those
233 * which don't are replaced with records: we hope that
234 * emerge will continue and replace these with locals.
235 */
236 AInt i, nlocs, npars, ndefs;
237
238
239 /* Safety check */
240 assert(foamTag(prog) == FOAM_Prog)do { if (!(((prog)->hdr.tag) == FOAM_Prog)) _do_assert(("foamTag(prog) == FOAM_Prog"
),"of_rrfmt.c",240); } while (0)
;
241
242
243 /* How many locals and parameters are we tracking? */
244 nlocs = foamDDeclArgc(prog->foamProg.locals)(((prog->foamProg.locals)->hdr.argc) - (1));
Value stored to 'nlocs' is never read
245 npars = foamDDeclArgc(prog->foamProg.params)(((prog->foamProg.params)->hdr.argc) - (1));
246
247
248 /*
249 * How many definitions are there in this prog? See
250 * udVarDefsVectBuild() to see why we begin with the
251 * number of parameters to this prog.
252 */
253 ndefs = npars;
254 flogIter(flog, bb, { ndefs += rrCountDefs(bb); }){ { int _i; BBlock bb; for (_i = 0; _i < ((flog)->blocks
->pos); _i++) { bb = bbufBlockFn((flog)->blocks,_i); if
(!bb) continue; { { ndefs += rrCountDefs(bb); }; }; } }; }
;
255
256
257 /* Data structures for caching reaching results */
258 rrInfo.changed = false((int) 0);
259 rrInfo.ndefs = ndefs;
260 rrInfo.npars = npars;
261 rrInfo.class = bitvClassCreate(rrInfo.ndefs);
262 rrInfo.seen = bitvNew(rrInfo.class);
263 rrInfo.cached = bitvNew(rrInfo.class);
264 rrInfo.escapes = bitvNew(rrInfo.class);
265
266
267 /* Initialise cached results */
268 bitvClearAll(rrInfo.class, rrInfo.cached);
269 bitvClearAll(rrInfo.class, rrInfo.escapes);
270
271
272 /*
273 * The parameters passed to this function all escape. From the
274 * source in usedef.c we see that values passed to a function
275 * are given false definitions with a definition number equal
276 * to the parameter number.
277 */
278 for (i = 0;i < npars; i++) rrMarkEscapingDef(i){ bitvSet(rrInfo.class, rrInfo.cached, i); bitvSet(rrInfo.class
, rrInfo.escapes, i); }
;
279
280
281 /* Identify escaping and non-escaping raw records */
282 flogIter(flog, bb, { rrFindEscapes(bb); }){ { int _i; BBlock bb; for (_i = 0; _i < ((flog)->blocks
->pos); _i++) { bb = bbufBlockFn((flog)->blocks,_i); if
(!bb) continue; { { rrFindEscapes(bb); }; }; } }; }
;
283
284
285 /* Display the numbers of non-escaping raw records */
286 if (DEBUG(rrfmt)rrfmtDebug) {
287 (void)fprintf(dbOut, "Non-escapes: [ ");
288 for (i = 0; i < ndefs; i++)
289 {
290 /* Skip past unknown definitions */
291 if (!rrDefIsKnown(i)bitvTest(rrInfo.class, rrInfo.cached, i))
292 continue;
293
294
295 /* Skip definitions that escape */
296 if (rrDefHasEscaped(i)bitvTest(rrInfo.class, rrInfo.escapes, i))
297 continue;
298
299
300 /* Print this one */
301 (void)fprintf(dbOut, "<%d> ", (int)i);
302 }
303 (void)fprintf(dbOut, "]\n");
304 }
305
306
307 /* Walk the prog replacing raw records */
308 flogIter(flog, bb, { rrReplace(bb); }){ { int _i; BBlock bb; for (_i = 0; _i < ((flog)->blocks
->pos); _i++) { bb = bbufBlockFn((flog)->blocks,_i); if
(!bb) continue; { { rrReplace(bb); }; }; } }; }
;
309
310
311 /* Did we change anything? */
312 return rrInfo.changed;
313}
314
315
316localstatic AInt
317rrCountDefs(BBlock bb)
318{
319 AInt ndefs = 0;
320 Foam code = bb->code;
321
322
323 /* Count the number of definitions in this bblock */
324 foamIter(code, stmtp, { if (rrIsDef(*stmtp)) ndefs++; }){ { String argf = (foamInfoTable [(int)(((code)->hdr.tag))
-(int)FOAM_START]).argf; Length _i; for (_i = 0; _i < ((code
)->hdr.argc); _i++, argf++) { if (*argf == '*') argf--; if
(*argf == 'C') { Foam *stmtp = (Foam *) ((code)->foamGen.
argv)+_i; { { if (( (((*stmtp)->hdr.tag) == FOAM_Set) || (
((*stmtp)->hdr.tag) == FOAM_Def) )) ndefs++; }; }; } } }; }
;
325
326
327 /* Return the number of definitions found */
328 return ndefs;
329}
330
331
332localstatic void
333rrFindEscapes(BBlock bb)
334{
335 /* Walk the bb to find escapes */
336 foamIter(bb->code, stmtp,{ { 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 *stmtp = (Foam *) ((bb->
code)->foamGen.argv)+_i; { { Foam stmt = *stmtp; if (( (((
stmt)->hdr.tag) == FOAM_Set) || (((stmt)->hdr.tag) == FOAM_Def
) )) rrFindDefEscapes(stmt); else rrFindDeepEscapes(stmt); };
}; } } }; }
337 {{ { 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 *stmtp = (Foam *) ((bb->
code)->foamGen.argv)+_i; { { Foam stmt = *stmtp; if (( (((
stmt)->hdr.tag) == FOAM_Set) || (((stmt)->hdr.tag) == FOAM_Def
) )) rrFindDefEscapes(stmt); else rrFindDeepEscapes(stmt); };
}; } } }; }
338 Foam stmt = *stmtp;{ { 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 *stmtp = (Foam *) ((bb->
code)->foamGen.argv)+_i; { { Foam stmt = *stmtp; if (( (((
stmt)->hdr.tag) == FOAM_Set) || (((stmt)->hdr.tag) == FOAM_Def
) )) rrFindDefEscapes(stmt); else rrFindDeepEscapes(stmt); };
}; } } }; }
339
340 /* Definitions need special care */{ { 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 *stmtp = (Foam *) ((bb->
code)->foamGen.argv)+_i; { { Foam stmt = *stmtp; if (( (((
stmt)->hdr.tag) == FOAM_Set) || (((stmt)->hdr.tag) == FOAM_Def
) )) rrFindDefEscapes(stmt); else rrFindDeepEscapes(stmt); };
}; } } }; }
341 if (rrIsDef(stmt)){ { 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 *stmtp = (Foam *) ((bb->
code)->foamGen.argv)+_i; { { Foam stmt = *stmtp; if (( (((
stmt)->hdr.tag) == FOAM_Set) || (((stmt)->hdr.tag) == FOAM_Def
) )) rrFindDefEscapes(stmt); else rrFindDeepEscapes(stmt); };
}; } } }; }
342 rrFindDefEscapes(stmt);{ { 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 *stmtp = (Foam *) ((bb->
code)->foamGen.argv)+_i; { { Foam stmt = *stmtp; if (( (((
stmt)->hdr.tag) == FOAM_Set) || (((stmt)->hdr.tag) == FOAM_Def
) )) rrFindDefEscapes(stmt); else rrFindDeepEscapes(stmt); };
}; } } }; }
343 else{ { 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 *stmtp = (Foam *) ((bb->
code)->foamGen.argv)+_i; { { Foam stmt = *stmtp; if (( (((
stmt)->hdr.tag) == FOAM_Set) || (((stmt)->hdr.tag) == FOAM_Def
) )) rrFindDefEscapes(stmt); else rrFindDeepEscapes(stmt); };
}; } } }; }
344 rrFindDeepEscapes(stmt);{ { 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 *stmtp = (Foam *) ((bb->
code)->foamGen.argv)+_i; { { Foam stmt = *stmtp; if (( (((
stmt)->hdr.tag) == FOAM_Set) || (((stmt)->hdr.tag) == FOAM_Def
) )) rrFindDefEscapes(stmt); else rrFindDeepEscapes(stmt); };
}; } } }; }
345 }){ { 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 *stmtp = (Foam *) ((bb->
code)->foamGen.argv)+_i; { { Foam stmt = *stmtp; if (( (((
stmt)->hdr.tag) == FOAM_Set) || (((stmt)->hdr.tag) == FOAM_Def
) )) rrFindDefEscapes(stmt); else rrFindDeepEscapes(stmt); };
}; } } }; }
;
346}
347
348
349localstatic void
350rrFindDefEscapes(Foam foam)
351{
352 /* Examine a Set/Def for escapes */
353 Bool isDef = (foamTag(foam)((foam)->hdr.tag) == FOAM_Def);
354 Foam lhs = (isDef ? foam->foamDef.lhs : foam->foamSet.lhs);
355 Foam rhs = (isDef ? foam->foamDef.rhs : foam->foamSet.rhs);
356
357
358 /* Safety check (a tad late) */
359 assert((foamTag(foam) == FOAM_Set) || (foamTag(foam) == FOAM_Def))do { if (!((((foam)->hdr.tag) == FOAM_Set) || (((foam)->
hdr.tag) == FOAM_Def))) _do_assert(("(foamTag(foam) == FOAM_Set) || (foamTag(foam) == FOAM_Def)"
),"of_rrfmt.c",359); } while (0)
;
360
361
362 /*
363 * If the lhs is a multi then we consider it to be an escaping
364 * definition. Future work: check each element of the multi to
365 * see which ones escape and which do no.
366 */
367 if (foamTag(lhs)((lhs)->hdr.tag) == FOAM_Values)
368 {
369 /* This definition escapes */
370 rrDefEscapes(foam);
371
372
373 /* Check for other escapes */
374 rrFindDeepEscapes(lhs);
375 rrFindDeepEscapes(rhs);
376 }
377
378
379 /* If the lhs is a local then check to see if the rhs escapes. */
380 else if (rrIsLocal(lhs)( (((lhs)->hdr.tag) == FOAM_Loc) || (((lhs)->hdr.tag) ==
FOAM_Par) )
)
381 rr0FindDefEscapes(foam, lhs, rhs);
382
383
384 /* If the lhs is non-local but the rhs is, then the rhs escapes */
385 else if (rrIsLocal(rhs)( (((rhs)->hdr.tag) == FOAM_Loc) || (((rhs)->hdr.tag) ==
FOAM_Par) )
)
386 {
387 rrFindDeepEscapes(lhs);
388 rrLocalEscapes(rhs);
389 }
390
391
392 /* Otherwise both sides may contain escapes */
393 else
394 {
395 rrFindDeepEscapes(rhs);
396 rrFindDeepEscapes(lhs);
397 }
398}
399
400
401localstatic void
402rr0FindDefEscapes(Foam def, Foam loc, Foam val)
403{
404 /*
405 * Given the foam (Set (Loc a) (Loc b)), or the equivalent Def,
406 * mark the definition as non-escaping if all definitions of
407 * (Loc b) reaching this point can be traced to RRNew expressions.
408 * Definitions which trace back to other expressions are deemed
409 * to escape and this definition escapes as a result. However, if
410 * (Loc a) is already known to escape then (Loc b) is marked as
411 * escaping.
412 *
413 * Given the foam (Set (Loc a) (RRNew ...)), or the equivalent
414 * Def, then this definition does not escape.
415 *
416 * Given the foam (Set (Loc a) <expr>), or the equivalent Def,
417 * consider this definition to escape and check <expr> to see if
418 * any other locals escape.
419 */
420 Foam uncast;
421
422
423 /* Safety check */
424 assert(rrIsLocal(loc))do { if (!(( (((loc)->hdr.tag) == FOAM_Loc) || (((loc)->
hdr.tag) == FOAM_Par) ))) _do_assert(("rrIsLocal(loc)"),"of_rrfmt.c"
,424); } while (0)
;
425
426
427 /* What does the rhs look like without a cast? */
428 uncast = val;
429 while (foamTag(uncast)((uncast)->hdr.tag) == FOAM_Cast)
430 uncast = uncast->foamCast.expr;
431
432
433 /* Deal with each case in turn */
434 if (foamTag(uncast)((uncast)->hdr.tag) == FOAM_RRNew)
435 {
436 Foam fmt = uncast->foamRRNew.fmt;
437
438 /*
439 * If we can determine the raw record format statically
440 * then it is non-escaping.
441 */
442 if (!rrRRFmtIsIndependent(fmt))
443 {
444 /* Check for escapes in format */
445 rrDefEscapes(def);
446 rrFindDeepEscapes(fmt);
447 }
448 else
449 rrDefNotEscapes(def);
450 }
451 else if (rrIsLocal(uncast)( (((uncast)->hdr.tag) == FOAM_Loc) || (((uncast)->hdr.
tag) == FOAM_Par) )
)
452 {
453 /* If either escapes then mark them */
454 if (!rrNonEscapingLocal(uncast) || !rrNonEscapingLocal(loc))
455 {
456 rrDefEscapes(def);
457 rrLocalEscapes(uncast);
458 }
459 else
460 rrDefNotEscapes(def);
461 }
462 else
463 {
464 /* Assume def escapes and check rhs for escapes */
465 rrDefEscapes(def);
466 rrFindDeepEscapes(val);
467 }
468}
469
470
471localstatic void
472rrDefEscapes(Foam def)
473{
474 /* This definition escapes */
475 AInt defno = rrDefNo(def)((def)->foamGen.hdr.info.defNo);
476
477
478 /* We always record escaping definitions */
479 rrMarkEscapingDef(defno){ bitvSet(rrInfo.class, rrInfo.cached, defno); bitvSet(rrInfo
.class, rrInfo.escapes, defno); }
;
480}
481
482
483localstatic void
484rrDefNotEscapes(Foam def)
485{
486 /* This definition does not escape */
487 AInt defno = rrDefNo(def)((def)->foamGen.hdr.info.defNo);
488
489
490 /* Only mark non-escaping if no result known */
491 if (!rrDefIsKnown(defno)bitvTest(rrInfo.class, rrInfo.cached, defno))
492 rrMarkNonEscapingDef(defno){ bitvSet(rrInfo.class, rrInfo.cached, defno); bitvClear(rrInfo
.class, rrInfo.escapes, defno); }
;
493}
494
495
496/*
497 * Identify escaping raw records: those which are passed to
498 * functions and those whose set of reaching definitions
499 * includes an escaping definition. Note that Defs/Sets are
500 * examined elsewhere and may call us recursively.
501 */
502localstatic void
503rrFindDeepEscapes(Foam foam)
504{
505 /* Safety checks */
506 assert(foam)do { if (!(foam)) _do_assert(("foam"),"of_rrfmt.c",506); } while
(0)
;
507 assert(foamTag(foam) != FOAM_Set)do { if (!(((foam)->hdr.tag) != FOAM_Set)) _do_assert(("foamTag(foam) != FOAM_Set"
),"of_rrfmt.c",507); } while (0)
;
508 assert(foamTag(foam) != FOAM_Def)do { if (!(((foam)->hdr.tag) != FOAM_Def)) _do_assert(("foamTag(foam) != FOAM_Def"
),"of_rrfmt.c",508); } while (0)
;
509
510
511 /* Special check on locals */
512 if (rrIsLocal(foam)( (((foam)->hdr.tag) == FOAM_Loc) || (((foam)->hdr.tag)
== FOAM_Par) )
)
513 {
514 rrReconcileLocal(foam);
515 return;
516 }
517
518
519 /* Ignore other variables */
520 if (rrIsVar(foam)( (((foam)->hdr.tag) == FOAM_Lex) || (((foam)->hdr.tag)
== FOAM_Glo) || ( (((foam)->hdr.tag) == FOAM_Loc) || (((foam
)->hdr.tag) == FOAM_Par) ) )
) return;
521
522
523 /* Raw records can escape if they are arguments to a call. */
524 switch (foamTag(foam)((foam)->hdr.tag))
525 {
526 case FOAM_Return: rrReturnEscapes(foam); break;
527 case FOAM_BCall: rrBCallEscapes(foam); break;
528 case FOAM_CCall: rrCCallEscapes(foam); break;
529 case FOAM_OCall: rrOCallEscapes(foam); break;
530 case FOAM_PCall: rrPCallEscapes(foam); break;
531 default: foamIter(foam, arg, rrFindDeepEscapes(*arg)){ { String argf = (foamInfoTable [(int)(((foam)->hdr.tag))
-(int)FOAM_START]).argf; Length _i; for (_i = 0; _i < ((foam
)->hdr.argc); _i++, argf++) { if (*argf == '*') argf--; if
(*argf == 'C') { Foam *arg = (Foam *) ((foam)->foamGen.argv
)+_i; { rrFindDeepEscapes(*arg); }; } } }; }
;
532 }
533}
534
535
536/*
537 * The set of all definitions that reach the use of this local must be
538 * all escaping or all non-escaping. If any of the reaching definitions
539 * escape then all the others are marked as escaping.
540 */
541localstatic void
542rrReconcileLocal(Foam loc)
543{
544 /* If no definitions escape then we can stop now */
545 if (rrNonEscapingLocal(loc)) return;
546
547
548 /* Mark all the definitions as escaping */
549 rrLocalEscapes(loc);
550}
551
552
553localstatic void
554rrReturnEscapes(Foam ret)
555{
556 Foam value;
557
558 /* Safety check */
559 assert(foamTag(ret) == FOAM_Return)do { if (!(((ret)->hdr.tag) == FOAM_Return)) _do_assert(("foamTag(ret) == FOAM_Return"
),"of_rrfmt.c",559); } while (0)
;
560
561
562 /* Get the value being returned */
563 value = ret->foamReturn.value;
564
565
566 /* Single or multi? */
567 if (foamTag(value)((value)->hdr.tag) == FOAM_Values)
568 rrCallArgsEscape(value->foamValues.argv, foamArgc(value)((value)->hdr.argc));
569
570
571 /* Mark all definitions of this local as escaping */
572 else if (rrIsLocal(value)( (((value)->hdr.tag) == FOAM_Loc) || (((value)->hdr.tag
) == FOAM_Par) )
)
573 rrLocalEscapes(value);
574
575
576 /* Check for other escapes */
577 else
578 rrFindDeepEscapes(value);
579}
580
581
582localstatic void
583rrBCallEscapes(Foam call)
584{
585 assert(foamTag(call) == FOAM_BCall)do { if (!(((call)->hdr.tag) == FOAM_BCall)) _do_assert(("foamTag(call) == FOAM_BCall"
),"of_rrfmt.c",585); } while (0)
;
586 rrCallArgsEscape(call->foamBCall.argv, foamArgc(call)((call)->hdr.argc) - 1);
587}
588
589
590localstatic void
591rrCCallEscapes(Foam call)
592{
593 assert(foamTag(call) == FOAM_CCall)do { if (!(((call)->hdr.tag) == FOAM_CCall)) _do_assert(("foamTag(call) == FOAM_CCall"
),"of_rrfmt.c",593); } while (0)
;
594 rrCallArgsEscape(call->foamCCall.argv, foamArgc(call)((call)->hdr.argc) - 2);
595}
596
597
598localstatic void
599rrOCallEscapes(Foam call)
600{
601 assert(foamTag(call) == FOAM_OCall)do { if (!(((call)->hdr.tag) == FOAM_OCall)) _do_assert(("foamTag(call) == FOAM_OCall"
),"of_rrfmt.c",601); } while (0)
;
602 rrCallArgsEscape(call->foamOCall.argv, foamArgc(call)((call)->hdr.argc) - 3);
603}
604
605
606localstatic void
607rrPCallEscapes(Foam call)
608{
609 assert(foamTag(call) == FOAM_PCall)do { if (!(((call)->hdr.tag) == FOAM_PCall)) _do_assert(("foamTag(call) == FOAM_PCall"
),"of_rrfmt.c",609); } while (0)
;
610 rrCallArgsEscape(call->foamPCall.argv, foamArgc(call)((call)->hdr.argc) - 3);
611}
612
613
614localstatic void
615rrCallArgsEscape(Foam *argv, AInt argc)
616{
617 AInt i;
618
619 for (i = 0;i < argc; i++)
620 {
621 Foam arg = argv[i];
622
623 /* Mark all definitions of this local as escaping */
624 if (rrIsLocal(arg)( (((arg)->hdr.tag) == FOAM_Loc) || (((arg)->hdr.tag) ==
FOAM_Par) )
)
625 rrLocalEscapes(arg);
626 else
627 rrFindDeepEscapes(arg);
628 }
629}
630
631
632/*
633 * Find all definitions that reach this use of a local and
634 * mark them as escaping.
635 */
636localstatic void
637rrLocalEscapes(Foam loc)
638{
639 Bitv seen = rrInfo.seen;
640 Bitv cached = rrInfo.cached;
641 Bitv escapes = rrInfo.escapes;
642
643
644 /* Clear the loop detection marks */
645 bitvClearAll(rrInfo.class, seen);
646
647
648 /* Inner marker */
649 rr0LocalEscapes(loc, seen, cached, escapes);
650}
651
652
653localstatic void
654rr0LocalEscapes(Foam loc, Bitv seen, Bitv cached, Bitv escapes)
655{
656 /*
657 * Walk the chain of definitions that reach this local
658 * marking them all as escaping.
659 *
660 * Since the reaching definitions may contain loops
661 * we have to be careful where we tread.
662 *
663 * !!! See if we can optimise this to prevent us from
664 * !!! having to walk all definitions repeatedly for
665 * !!! the same local.
666 */
667 AInt defno;
668 Bool isDef;
669 UdInfoList udList;
670 Foam def, val;
671
672
673 /* Safety check */
674 assert(rrIsLocal(loc))do { if (!(( (((loc)->hdr.tag) == FOAM_Loc) || (((loc)->
hdr.tag) == FOAM_Par) ))) _do_assert(("rrIsLocal(loc)"),"of_rrfmt.c"
,674); } while (0)
;
675
676
677 /* Get the chain of definitions that reach this usage */
678 udList = (UdInfoList)rrReachingDefs(loc)((Foam)((loc)->foamGen.hdr.info.defList));
679
680
681 /* Mark each definition and its ancestors as escaping. */
682 listIter(UdInfo, udInfo, udList,{ { UdInfoList _l0; UdInfo udInfo; for (_l0 = (udList); _l0; _l0
= ((_l0)->rest)) { udInfo = ((_l0)->first); { { def = udInfo
-> foam; isDef = (((def)->hdr.tag) == FOAM_Def); defno
= ((def)->foamGen.hdr.info.defNo); if (bitvTest(rrInfo.class
, rrInfo.seen, defno)) continue; bitvSet(rrInfo.class, rrInfo
.seen, defno); rrDefEscapes(def); val = (isDef ? def->foamDef
.rhs : def->foamSet.rhs); while (((val)->hdr.tag) == FOAM_Cast
) val = val->foamCast.expr; if (!( (((val)->hdr.tag) ==
FOAM_Loc) || (((val)->hdr.tag) == FOAM_Par) )) continue; rr0LocalEscapes
(val, seen, cached, escapes); }; }; } }; }
683 {{ { UdInfoList _l0; UdInfo udInfo; for (_l0 = (udList); _l0; _l0
= ((_l0)->rest)) { udInfo = ((_l0)->first); { { def = udInfo
-> foam; isDef = (((def)->hdr.tag) == FOAM_Def); defno
= ((def)->foamGen.hdr.info.defNo); if (bitvTest(rrInfo.class
, rrInfo.seen, defno)) continue; bitvSet(rrInfo.class, rrInfo
.seen, defno); rrDefEscapes(def); val = (isDef ? def->foamDef
.rhs : def->foamSet.rhs); while (((val)->hdr.tag) == FOAM_Cast
) val = val->foamCast.expr; if (!( (((val)->hdr.tag) ==
FOAM_Loc) || (((val)->hdr.tag) == FOAM_Par) )) continue; rr0LocalEscapes
(val, seen, cached, escapes); }; }; } }; }
684 /* Extract the definition reaching here */{ { UdInfoList _l0; UdInfo udInfo; for (_l0 = (udList); _l0; _l0
= ((_l0)->rest)) { udInfo = ((_l0)->first); { { def = udInfo
-> foam; isDef = (((def)->hdr.tag) == FOAM_Def); defno
= ((def)->foamGen.hdr.info.defNo); if (bitvTest(rrInfo.class
, rrInfo.seen, defno)) continue; bitvSet(rrInfo.class, rrInfo
.seen, defno); rrDefEscapes(def); val = (isDef ? def->foamDef
.rhs : def->foamSet.rhs); while (((val)->hdr.tag) == FOAM_Cast
) val = val->foamCast.expr; if (!( (((val)->hdr.tag) ==
FOAM_Loc) || (((val)->hdr.tag) == FOAM_Par) )) continue; rr0LocalEscapes
(val, seen, cached, escapes); }; }; } }; }
685 def = udInfo -> foam;{ { UdInfoList _l0; UdInfo udInfo; for (_l0 = (udList); _l0; _l0
= ((_l0)->rest)) { udInfo = ((_l0)->first); { { def = udInfo
-> foam; isDef = (((def)->hdr.tag) == FOAM_Def); defno
= ((def)->foamGen.hdr.info.defNo); if (bitvTest(rrInfo.class
, rrInfo.seen, defno)) continue; bitvSet(rrInfo.class, rrInfo
.seen, defno); rrDefEscapes(def); val = (isDef ? def->foamDef
.rhs : def->foamSet.rhs); while (((val)->hdr.tag) == FOAM_Cast
) val = val->foamCast.expr; if (!( (((val)->hdr.tag) ==
FOAM_Loc) || (((val)->hdr.tag) == FOAM_Par) )) continue; rr0LocalEscapes
(val, seen, cached, escapes); }; }; } }; }
686 isDef = (foamTag(def) == FOAM_Def);{ { UdInfoList _l0; UdInfo udInfo; for (_l0 = (udList); _l0; _l0
= ((_l0)->rest)) { udInfo = ((_l0)->first); { { def = udInfo
-> foam; isDef = (((def)->hdr.tag) == FOAM_Def); defno
= ((def)->foamGen.hdr.info.defNo); if (bitvTest(rrInfo.class
, rrInfo.seen, defno)) continue; bitvSet(rrInfo.class, rrInfo
.seen, defno); rrDefEscapes(def); val = (isDef ? def->foamDef
.rhs : def->foamSet.rhs); while (((val)->hdr.tag) == FOAM_Cast
) val = val->foamCast.expr; if (!( (((val)->hdr.tag) ==
FOAM_Loc) || (((val)->hdr.tag) == FOAM_Par) )) continue; rr0LocalEscapes
(val, seen, cached, escapes); }; }; } }; }
687 defno = rrDefNo(def);{ { UdInfoList _l0; UdInfo udInfo; for (_l0 = (udList); _l0; _l0
= ((_l0)->rest)) { udInfo = ((_l0)->first); { { def = udInfo
-> foam; isDef = (((def)->hdr.tag) == FOAM_Def); defno
= ((def)->foamGen.hdr.info.defNo); if (bitvTest(rrInfo.class
, rrInfo.seen, defno)) continue; bitvSet(rrInfo.class, rrInfo
.seen, defno); rrDefEscapes(def); val = (isDef ? def->foamDef
.rhs : def->foamSet.rhs); while (((val)->hdr.tag) == FOAM_Cast
) val = val->foamCast.expr; if (!( (((val)->hdr.tag) ==
FOAM_Loc) || (((val)->hdr.tag) == FOAM_Par) )) continue; rr0LocalEscapes
(val, seen, cached, escapes); }; }; } }; }
688
689
690 /* Have we checked this node already? */{ { UdInfoList _l0; UdInfo udInfo; for (_l0 = (udList); _l0; _l0
= ((_l0)->rest)) { udInfo = ((_l0)->first); { { def = udInfo
-> foam; isDef = (((def)->hdr.tag) == FOAM_Def); defno
= ((def)->foamGen.hdr.info.defNo); if (bitvTest(rrInfo.class
, rrInfo.seen, defno)) continue; bitvSet(rrInfo.class, rrInfo
.seen, defno); rrDefEscapes(def); val = (isDef ? def->foamDef
.rhs : def->foamSet.rhs); while (((val)->hdr.tag) == FOAM_Cast
) val = val->foamCast.expr; if (!( (((val)->hdr.tag) ==
FOAM_Loc) || (((val)->hdr.tag) == FOAM_Par) )) continue; rr0LocalEscapes
(val, seen, cached, escapes); }; }; } }; }
691 if (rrDefAlreadySeen(defno)) continue;{ { UdInfoList _l0; UdInfo udInfo; for (_l0 = (udList); _l0; _l0
= ((_l0)->rest)) { udInfo = ((_l0)->first); { { def = udInfo
-> foam; isDef = (((def)->hdr.tag) == FOAM_Def); defno
= ((def)->foamGen.hdr.info.defNo); if (bitvTest(rrInfo.class
, rrInfo.seen, defno)) continue; bitvSet(rrInfo.class, rrInfo
.seen, defno); rrDefEscapes(def); val = (isDef ? def->foamDef
.rhs : def->foamSet.rhs); while (((val)->hdr.tag) == FOAM_Cast
) val = val->foamCast.expr; if (!( (((val)->hdr.tag) ==
FOAM_Loc) || (((val)->hdr.tag) == FOAM_Par) )) continue; rr0LocalEscapes
(val, seen, cached, escapes); }; }; } }; }
692
693
694 /* Note that we have checked this node */{ { UdInfoList _l0; UdInfo udInfo; for (_l0 = (udList); _l0; _l0
= ((_l0)->rest)) { udInfo = ((_l0)->first); { { def = udInfo
-> foam; isDef = (((def)->hdr.tag) == FOAM_Def); defno
= ((def)->foamGen.hdr.info.defNo); if (bitvTest(rrInfo.class
, rrInfo.seen, defno)) continue; bitvSet(rrInfo.class, rrInfo
.seen, defno); rrDefEscapes(def); val = (isDef ? def->foamDef
.rhs : def->foamSet.rhs); while (((val)->hdr.tag) == FOAM_Cast
) val = val->foamCast.expr; if (!( (((val)->hdr.tag) ==
FOAM_Loc) || (((val)->hdr.tag) == FOAM_Par) )) continue; rr0LocalEscapes
(val, seen, cached, escapes); }; }; } }; }
695 rrMarkDefSeen(defno);{ { UdInfoList _l0; UdInfo udInfo; for (_l0 = (udList); _l0; _l0
= ((_l0)->rest)) { udInfo = ((_l0)->first); { { def = udInfo
-> foam; isDef = (((def)->hdr.tag) == FOAM_Def); defno
= ((def)->foamGen.hdr.info.defNo); if (bitvTest(rrInfo.class
, rrInfo.seen, defno)) continue; bitvSet(rrInfo.class, rrInfo
.seen, defno); rrDefEscapes(def); val = (isDef ? def->foamDef
.rhs : def->foamSet.rhs); while (((val)->hdr.tag) == FOAM_Cast
) val = val->foamCast.expr; if (!( (((val)->hdr.tag) ==
FOAM_Loc) || (((val)->hdr.tag) == FOAM_Par) )) continue; rr0LocalEscapes
(val, seen, cached, escapes); }; }; } }; }
696
697
698 /* Mark this definition as escaping */{ { UdInfoList _l0; UdInfo udInfo; for (_l0 = (udList); _l0; _l0
= ((_l0)->rest)) { udInfo = ((_l0)->first); { { def = udInfo
-> foam; isDef = (((def)->hdr.tag) == FOAM_Def); defno
= ((def)->foamGen.hdr.info.defNo); if (bitvTest(rrInfo.class
, rrInfo.seen, defno)) continue; bitvSet(rrInfo.class, rrInfo
.seen, defno); rrDefEscapes(def); val = (isDef ? def->foamDef
.rhs : def->foamSet.rhs); while (((val)->hdr.tag) == FOAM_Cast
) val = val->foamCast.expr; if (!( (((val)->hdr.tag) ==
FOAM_Loc) || (((val)->hdr.tag) == FOAM_Par) )) continue; rr0LocalEscapes
(val, seen, cached, escapes); }; }; } }; }
699 rrDefEscapes(def);{ { UdInfoList _l0; UdInfo udInfo; for (_l0 = (udList); _l0; _l0
= ((_l0)->rest)) { udInfo = ((_l0)->first); { { def = udInfo
-> foam; isDef = (((def)->hdr.tag) == FOAM_Def); defno
= ((def)->foamGen.hdr.info.defNo); if (bitvTest(rrInfo.class
, rrInfo.seen, defno)) continue; bitvSet(rrInfo.class, rrInfo
.seen, defno); rrDefEscapes(def); val = (isDef ? def->foamDef
.rhs : def->foamSet.rhs); while (((val)->hdr.tag) == FOAM_Cast
) val = val->foamCast.expr; if (!( (((val)->hdr.tag) ==
FOAM_Loc) || (((val)->hdr.tag) == FOAM_Par) )) continue; rr0LocalEscapes
(val, seen, cached, escapes); }; }; } }; }
700
701
702 /* Get the value that reaches this point */{ { UdInfoList _l0; UdInfo udInfo; for (_l0 = (udList); _l0; _l0
= ((_l0)->rest)) { udInfo = ((_l0)->first); { { def = udInfo
-> foam; isDef = (((def)->hdr.tag) == FOAM_Def); defno
= ((def)->foamGen.hdr.info.defNo); if (bitvTest(rrInfo.class
, rrInfo.seen, defno)) continue; bitvSet(rrInfo.class, rrInfo
.seen, defno); rrDefEscapes(def); val = (isDef ? def->foamDef
.rhs : def->foamSet.rhs); while (((val)->hdr.tag) == FOAM_Cast
) val = val->foamCast.expr; if (!( (((val)->hdr.tag) ==
FOAM_Loc) || (((val)->hdr.tag) == FOAM_Par) )) continue; rr0LocalEscapes
(val, seen, cached, escapes); }; }; } }; }
703 val = (isDef ? def->foamDef.rhs : def->foamSet.rhs);{ { UdInfoList _l0; UdInfo udInfo; for (_l0 = (udList); _l0; _l0
= ((_l0)->rest)) { udInfo = ((_l0)->first); { { def = udInfo
-> foam; isDef = (((def)->hdr.tag) == FOAM_Def); defno
= ((def)->foamGen.hdr.info.defNo); if (bitvTest(rrInfo.class
, rrInfo.seen, defno)) continue; bitvSet(rrInfo.class, rrInfo
.seen, defno); rrDefEscapes(def); val = (isDef ? def->foamDef
.rhs : def->foamSet.rhs); while (((val)->hdr.tag) == FOAM_Cast
) val = val->foamCast.expr; if (!( (((val)->hdr.tag) ==
FOAM_Loc) || (((val)->hdr.tag) == FOAM_Par) )) continue; rr0LocalEscapes
(val, seen, cached, escapes); }; }; } }; }
704
705
706 /* Remove any casts from the value */{ { UdInfoList _l0; UdInfo udInfo; for (_l0 = (udList); _l0; _l0
= ((_l0)->rest)) { udInfo = ((_l0)->first); { { def = udInfo
-> foam; isDef = (((def)->hdr.tag) == FOAM_Def); defno
= ((def)->foamGen.hdr.info.defNo); if (bitvTest(rrInfo.class
, rrInfo.seen, defno)) continue; bitvSet(rrInfo.class, rrInfo
.seen, defno); rrDefEscapes(def); val = (isDef ? def->foamDef
.rhs : def->foamSet.rhs); while (((val)->hdr.tag) == FOAM_Cast
) val = val->foamCast.expr; if (!( (((val)->hdr.tag) ==
FOAM_Loc) || (((val)->hdr.tag) == FOAM_Par) )) continue; rr0LocalEscapes
(val, seen, cached, escapes); }; }; } }; }
707 while (foamTag(val) == FOAM_Cast){ { UdInfoList _l0; UdInfo udInfo; for (_l0 = (udList); _l0; _l0
= ((_l0)->rest)) { udInfo = ((_l0)->first); { { def = udInfo
-> foam; isDef = (((def)->hdr.tag) == FOAM_Def); defno
= ((def)->foamGen.hdr.info.defNo); if (bitvTest(rrInfo.class
, rrInfo.seen, defno)) continue; bitvSet(rrInfo.class, rrInfo
.seen, defno); rrDefEscapes(def); val = (isDef ? def->foamDef
.rhs : def->foamSet.rhs); while (((val)->hdr.tag) == FOAM_Cast
) val = val->foamCast.expr; if (!( (((val)->hdr.tag) ==
FOAM_Loc) || (((val)->hdr.tag) == FOAM_Par) )) continue; rr0LocalEscapes
(val, seen, cached, escapes); }; }; } }; }
708 val = val->foamCast.expr;{ { UdInfoList _l0; UdInfo udInfo; for (_l0 = (udList); _l0; _l0
= ((_l0)->rest)) { udInfo = ((_l0)->first); { { def = udInfo
-> foam; isDef = (((def)->hdr.tag) == FOAM_Def); defno
= ((def)->foamGen.hdr.info.defNo); if (bitvTest(rrInfo.class
, rrInfo.seen, defno)) continue; bitvSet(rrInfo.class, rrInfo
.seen, defno); rrDefEscapes(def); val = (isDef ? def->foamDef
.rhs : def->foamSet.rhs); while (((val)->hdr.tag) == FOAM_Cast
) val = val->foamCast.expr; if (!( (((val)->hdr.tag) ==
FOAM_Loc) || (((val)->hdr.tag) == FOAM_Par) )) continue; rr0LocalEscapes
(val, seen, cached, escapes); }; }; } }; }
709
710
711 /* If it isn't a local then it is a leaf node */{ { UdInfoList _l0; UdInfo udInfo; for (_l0 = (udList); _l0; _l0
= ((_l0)->rest)) { udInfo = ((_l0)->first); { { def = udInfo
-> foam; isDef = (((def)->hdr.tag) == FOAM_Def); defno
= ((def)->foamGen.hdr.info.defNo); if (bitvTest(rrInfo.class
, rrInfo.seen, defno)) continue; bitvSet(rrInfo.class, rrInfo
.seen, defno); rrDefEscapes(def); val = (isDef ? def->foamDef
.rhs : def->foamSet.rhs); while (((val)->hdr.tag) == FOAM_Cast
) val = val->foamCast.expr; if (!( (((val)->hdr.tag) ==
FOAM_Loc) || (((val)->hdr.tag) == FOAM_Par) )) continue; rr0LocalEscapes
(val, seen, cached, escapes); }; }; } }; }
712 if (!rrIsLocal(val)) continue;{ { UdInfoList _l0; UdInfo udInfo; for (_l0 = (udList); _l0; _l0
= ((_l0)->rest)) { udInfo = ((_l0)->first); { { def = udInfo
-> foam; isDef = (((def)->hdr.tag) == FOAM_Def); defno
= ((def)->foamGen.hdr.info.defNo); if (bitvTest(rrInfo.class
, rrInfo.seen, defno)) continue; bitvSet(rrInfo.class, rrInfo
.seen, defno); rrDefEscapes(def); val = (isDef ? def->foamDef
.rhs : def->foamSet.rhs); while (((val)->hdr.tag) == FOAM_Cast
) val = val->foamCast.expr; if (!( (((val)->hdr.tag) ==
FOAM_Loc) || (((val)->hdr.tag) == FOAM_Par) )) continue; rr0LocalEscapes
(val, seen, cached, escapes); }; }; } }; }
713
714
715 /* Mark the reaching definitions of this local */{ { UdInfoList _l0; UdInfo udInfo; for (_l0 = (udList); _l0; _l0
= ((_l0)->rest)) { udInfo = ((_l0)->first); { { def = udInfo
-> foam; isDef = (((def)->hdr.tag) == FOAM_Def); defno
= ((def)->foamGen.hdr.info.defNo); if (bitvTest(rrInfo.class
, rrInfo.seen, defno)) continue; bitvSet(rrInfo.class, rrInfo
.seen, defno); rrDefEscapes(def); val = (isDef ? def->foamDef
.rhs : def->foamSet.rhs); while (((val)->hdr.tag) == FOAM_Cast
) val = val->foamCast.expr; if (!( (((val)->hdr.tag) ==
FOAM_Loc) || (((val)->hdr.tag) == FOAM_Par) )) continue; rr0LocalEscapes
(val, seen, cached, escapes); }; }; } }; }
716 rr0LocalEscapes(val, seen, cached, escapes);{ { UdInfoList _l0; UdInfo udInfo; for (_l0 = (udList); _l0; _l0
= ((_l0)->rest)) { udInfo = ((_l0)->first); { { def = udInfo
-> foam; isDef = (((def)->hdr.tag) == FOAM_Def); defno
= ((def)->foamGen.hdr.info.defNo); if (bitvTest(rrInfo.class
, rrInfo.seen, defno)) continue; bitvSet(rrInfo.class, rrInfo
.seen, defno); rrDefEscapes(def); val = (isDef ? def->foamDef
.rhs : def->foamSet.rhs); while (((val)->hdr.tag) == FOAM_Cast
) val = val->foamCast.expr; if (!( (((val)->hdr.tag) ==
FOAM_Loc) || (((val)->hdr.tag) == FOAM_Par) )) continue; rr0LocalEscapes
(val, seen, cached, escapes); }; }; } }; }
717 }){ { UdInfoList _l0; UdInfo udInfo; for (_l0 = (udList); _l0; _l0
= ((_l0)->rest)) { udInfo = ((_l0)->first); { { def = udInfo
-> foam; isDef = (((def)->hdr.tag) == FOAM_Def); defno
= ((def)->foamGen.hdr.info.defNo); if (bitvTest(rrInfo.class
, rrInfo.seen, defno)) continue; bitvSet(rrInfo.class, rrInfo
.seen, defno); rrDefEscapes(def); val = (isDef ? def->foamDef
.rhs : def->foamSet.rhs); while (((val)->hdr.tag) == FOAM_Cast
) val = val->foamCast.expr; if (!( (((val)->hdr.tag) ==
FOAM_Loc) || (((val)->hdr.tag) == FOAM_Par) )) continue; rr0LocalEscapes
(val, seen, cached, escapes); }; }; } }; }
;
718}
719
720
721localstatic Bool
722rrNonEscapingLocal(Foam loc)
723{
724 Bitv seen = rrInfo.seen;
725 Bitv cached = rrInfo.cached;
726 Bitv escapes = rrInfo.escapes;
727
728
729 /* Clear the loop detection marks */
730 bitvClearAll(rrInfo.class, seen);
731
732
733 /* Inner checker */
734 return rr0NonEscapingLocal(loc, seen, cached, escapes);
735}
736
737
738localstatic Bool
739rr0NonEscapingLocal(Foam loc, Bitv seen, Bitv cached, Bitv escapes)
740{
741 /*
742 * Walk the chain of definitions that reach this local.
743 * If any of the leaves is not an RRNew then return
744 * false indicating that this local escapes somehow.
745 *
746 * Since the reaching definitions may contain loops
747 * we have to be careful where we tread.
748 */
749 AInt defno;
750 Bool isDef;
751 UdInfoList udList;
752 Foam def, val;
753
754
755 /* Safety check */
756 assert(rrIsLocal(loc))do { if (!(( (((loc)->hdr.tag) == FOAM_Loc) || (((loc)->
hdr.tag) == FOAM_Par) ))) _do_assert(("rrIsLocal(loc)"),"of_rrfmt.c"
,756); } while (0)
;
757
758
759 /* Get the chain of definitions that reach this usage */
760 udList = (UdInfoList)rrReachingDefs(loc)((Foam)((loc)->foamGen.hdr.info.defList));
761
762
763 /*
764 * If we can't find any definitions it must have been
765 * used before definition (or we have a bug). Consider
766 * it to escape for safety.
767 */
768 if (!udList) return false((int) 0);
769
770
771 /*
772 * Check each definition - if any of the definitions
773 * that reach this use escape then this use escapes.
774 * If none escape then this use doesn't escape.
775 */
776 listIter(UdInfo, udInfo, udList,{ { UdInfoList _l0; UdInfo udInfo; for (_l0 = (udList); _l0; _l0
= ((_l0)->rest)) { udInfo = ((_l0)->first); { { def = udInfo
-> foam; isDef = (((def)->hdr.tag) == FOAM_Def); defno
= ((def)->foamGen.hdr.info.defNo); if (bitvTest(rrInfo.class
, rrInfo.seen, defno)) continue; bitvSet(rrInfo.class, rrInfo
.seen, defno); if (bitvTest(rrInfo.class, rrInfo.cached, defno
)) { if (bitvTest(rrInfo.class, rrInfo.escapes, defno)) return
((int) 0); continue; } val = (isDef ? def->foamDef.rhs : def
->foamSet.rhs); while (((val)->hdr.tag) == FOAM_Cast) val
= val->foamCast.expr; if (((val)->hdr.tag) == FOAM_RRNew
) { rrDefNotEscapes(def); continue; } if (!( (((val)->hdr.
tag) == FOAM_Loc) || (((val)->hdr.tag) == FOAM_Par) )) { rrDefEscapes
(def); return ((int) 0); } if (!rr0NonEscapingLocal(val, seen
, cached, escapes)) { rrDefEscapes(def); return ((int) 0); } rrDefNotEscapes
(def); }; }; } }; }
777 {{ { UdInfoList _l0; UdInfo udInfo; for (_l0 = (udList); _l0; _l0
= ((_l0)->rest)) { udInfo = ((_l0)->first); { { def = udInfo
-> foam; isDef = (((def)->hdr.tag) == FOAM_Def); defno
= ((def)->foamGen.hdr.info.defNo); if (bitvTest(rrInfo.class
, rrInfo.seen, defno)) continue; bitvSet(rrInfo.class, rrInfo
.seen, defno); if (bitvTest(rrInfo.class, rrInfo.cached, defno
)) { if (bitvTest(rrInfo.class, rrInfo.escapes, defno)) return
((int) 0); continue; } val = (isDef ? def->foamDef.rhs : def
->foamSet.rhs); while (((val)->hdr.tag) == FOAM_Cast) val
= val->foamCast.expr; if (((val)->hdr.tag) == FOAM_RRNew
) { rrDefNotEscapes(def); continue; } if (!( (((val)->hdr.
tag) == FOAM_Loc) || (((val)->hdr.tag) == FOAM_Par) )) { rrDefEscapes
(def); return ((int) 0); } if (!rr0NonEscapingLocal(val, seen
, cached, escapes)) { rrDefEscapes(def); return ((int) 0); } rrDefNotEscapes
(def); }; }; } }; }
778 /* Extract the definition reaching here */{ { UdInfoList _l0; UdInfo udInfo; for (_l0 = (udList); _l0; _l0
= ((_l0)->rest)) { udInfo = ((_l0)->first); { { def = udInfo
-> foam; isDef = (((def)->hdr.tag) == FOAM_Def); defno
= ((def)->foamGen.hdr.info.defNo); if (bitvTest(rrInfo.class
, rrInfo.seen, defno)) continue; bitvSet(rrInfo.class, rrInfo
.seen, defno); if (bitvTest(rrInfo.class, rrInfo.cached, defno
)) { if (bitvTest(rrInfo.class, rrInfo.escapes, defno)) return
((int) 0); continue; } val = (isDef ? def->foamDef.rhs : def
->foamSet.rhs); while (((val)->hdr.tag) == FOAM_Cast) val
= val->foamCast.expr; if (((val)->hdr.tag) == FOAM_RRNew
) { rrDefNotEscapes(def); continue; } if (!( (((val)->hdr.
tag) == FOAM_Loc) || (((val)->hdr.tag) == FOAM_Par) )) { rrDefEscapes
(def); return ((int) 0); } if (!rr0NonEscapingLocal(val, seen
, cached, escapes)) { rrDefEscapes(def); return ((int) 0); } rrDefNotEscapes
(def); }; }; } }; }
779 def = udInfo -> foam;{ { UdInfoList _l0; UdInfo udInfo; for (_l0 = (udList); _l0; _l0
= ((_l0)->rest)) { udInfo = ((_l0)->first); { { def = udInfo
-> foam; isDef = (((def)->hdr.tag) == FOAM_Def); defno
= ((def)->foamGen.hdr.info.defNo); if (bitvTest(rrInfo.class
, rrInfo.seen, defno)) continue; bitvSet(rrInfo.class, rrInfo
.seen, defno); if (bitvTest(rrInfo.class, rrInfo.cached, defno
)) { if (bitvTest(rrInfo.class, rrInfo.escapes, defno)) return
((int) 0); continue; } val = (isDef ? def->foamDef.rhs : def
->foamSet.rhs); while (((val)->hdr.tag) == FOAM_Cast) val
= val->foamCast.expr; if (((val)->hdr.tag) == FOAM_RRNew
) { rrDefNotEscapes(def); continue; } if (!( (((val)->hdr.
tag) == FOAM_Loc) || (((val)->hdr.tag) == FOAM_Par) )) { rrDefEscapes
(def); return ((int) 0); } if (!rr0NonEscapingLocal(val, seen
, cached, escapes)) { rrDefEscapes(def); return ((int) 0); } rrDefNotEscapes
(def); }; }; } }; }
780 isDef = (foamTag(def) == FOAM_Def);{ { UdInfoList _l0; UdInfo udInfo; for (_l0 = (udList); _l0; _l0
= ((_l0)->rest)) { udInfo = ((_l0)->first); { { def = udInfo
-> foam; isDef = (((def)->hdr.tag) == FOAM_Def); defno
= ((def)->foamGen.hdr.info.defNo); if (bitvTest(rrInfo.class
, rrInfo.seen, defno)) continue; bitvSet(rrInfo.class, rrInfo
.seen, defno); if (bitvTest(rrInfo.class, rrInfo.cached, defno
)) { if (bitvTest(rrInfo.class, rrInfo.escapes, defno)) return
((int) 0); continue; } val = (isDef ? def->foamDef.rhs : def
->foamSet.rhs); while (((val)->hdr.tag) == FOAM_Cast) val
= val->foamCast.expr; if (((val)->hdr.tag) == FOAM_RRNew
) { rrDefNotEscapes(def); continue; } if (!( (((val)->hdr.
tag) == FOAM_Loc) || (((val)->hdr.tag) == FOAM_Par) )) { rrDefEscapes
(def); return ((int) 0); } if (!rr0NonEscapingLocal(val, seen
, cached, escapes)) { rrDefEscapes(def); return ((int) 0); } rrDefNotEscapes
(def); }; }; } }; }
781 defno = rrDefNo(def);{ { UdInfoList _l0; UdInfo udInfo; for (_l0 = (udList); _l0; _l0
= ((_l0)->rest)) { udInfo = ((_l0)->first); { { def = udInfo
-> foam; isDef = (((def)->hdr.tag) == FOAM_Def); defno
= ((def)->foamGen.hdr.info.defNo); if (bitvTest(rrInfo.class
, rrInfo.seen, defno)) continue; bitvSet(rrInfo.class, rrInfo
.seen, defno); if (bitvTest(rrInfo.class, rrInfo.cached, defno
)) { if (bitvTest(rrInfo.class, rrInfo.escapes, defno)) return
((int) 0); continue; } val = (isDef ? def->foamDef.rhs : def
->foamSet.rhs); while (((val)->hdr.tag) == FOAM_Cast) val
= val->foamCast.expr; if (((val)->hdr.tag) == FOAM_RRNew
) { rrDefNotEscapes(def); continue; } if (!( (((val)->hdr.
tag) == FOAM_Loc) || (((val)->hdr.tag) == FOAM_Par) )) { rrDefEscapes
(def); return ((int) 0); } if (!rr0NonEscapingLocal(val, seen
, cached, escapes)) { rrDefEscapes(def); return ((int) 0); } rrDefNotEscapes
(def); }; }; } }; }
782
783
784 /* Have we checked this node already? */{ { UdInfoList _l0; UdInfo udInfo; for (_l0 = (udList); _l0; _l0
= ((_l0)->rest)) { udInfo = ((_l0)->first); { { def = udInfo
-> foam; isDef = (((def)->hdr.tag) == FOAM_Def); defno
= ((def)->foamGen.hdr.info.defNo); if (bitvTest(rrInfo.class
, rrInfo.seen, defno)) continue; bitvSet(rrInfo.class, rrInfo
.seen, defno); if (bitvTest(rrInfo.class, rrInfo.cached, defno
)) { if (bitvTest(rrInfo.class, rrInfo.escapes, defno)) return
((int) 0); continue; } val = (isDef ? def->foamDef.rhs : def
->foamSet.rhs); while (((val)->hdr.tag) == FOAM_Cast) val
= val->foamCast.expr; if (((val)->hdr.tag) == FOAM_RRNew
) { rrDefNotEscapes(def); continue; } if (!( (((val)->hdr.
tag) == FOAM_Loc) || (((val)->hdr.tag) == FOAM_Par) )) { rrDefEscapes
(def); return ((int) 0); } if (!rr0NonEscapingLocal(val, seen
, cached, escapes)) { rrDefEscapes(def); return ((int) 0); } rrDefNotEscapes
(def); }; }; } }; }
785 if (rrDefAlreadySeen(defno)) continue;{ { UdInfoList _l0; UdInfo udInfo; for (_l0 = (udList); _l0; _l0
= ((_l0)->rest)) { udInfo = ((_l0)->first); { { def = udInfo
-> foam; isDef = (((def)->hdr.tag) == FOAM_Def); defno
= ((def)->foamGen.hdr.info.defNo); if (bitvTest(rrInfo.class
, rrInfo.seen, defno)) continue; bitvSet(rrInfo.class, rrInfo
.seen, defno); if (bitvTest(rrInfo.class, rrInfo.cached, defno
)) { if (bitvTest(rrInfo.class, rrInfo.escapes, defno)) return
((int) 0); continue; } val = (isDef ? def->foamDef.rhs : def
->foamSet.rhs); while (((val)->hdr.tag) == FOAM_Cast) val
= val->foamCast.expr; if (((val)->hdr.tag) == FOAM_RRNew
) { rrDefNotEscapes(def); continue; } if (!( (((val)->hdr.
tag) == FOAM_Loc) || (((val)->hdr.tag) == FOAM_Par) )) { rrDefEscapes
(def); return ((int) 0); } if (!rr0NonEscapingLocal(val, seen
, cached, escapes)) { rrDefEscapes(def); return ((int) 0); } rrDefNotEscapes
(def); }; }; } }; }
786
787
788 /* Note that we have checked this node */{ { UdInfoList _l0; UdInfo udInfo; for (_l0 = (udList); _l0; _l0
= ((_l0)->rest)) { udInfo = ((_l0)->first); { { def = udInfo
-> foam; isDef = (((def)->hdr.tag) == FOAM_Def); defno
= ((def)->foamGen.hdr.info.defNo); if (bitvTest(rrInfo.class
, rrInfo.seen, defno)) continue; bitvSet(rrInfo.class, rrInfo
.seen, defno); if (bitvTest(rrInfo.class, rrInfo.cached, defno
)) { if (bitvTest(rrInfo.class, rrInfo.escapes, defno)) return
((int) 0); continue; } val = (isDef ? def->foamDef.rhs : def
->foamSet.rhs); while (((val)->hdr.tag) == FOAM_Cast) val
= val->foamCast.expr; if (((val)->hdr.tag) == FOAM_RRNew
) { rrDefNotEscapes(def); continue; } if (!( (((val)->hdr.
tag) == FOAM_Loc) || (((val)->hdr.tag) == FOAM_Par) )) { rrDefEscapes
(def); return ((int) 0); } if (!rr0NonEscapingLocal(val, seen
, cached, escapes)) { rrDefEscapes(def); return ((int) 0); } rrDefNotEscapes
(def); }; }; } }; }
789 rrMarkDefSeen(defno);{ { UdInfoList _l0; UdInfo udInfo; for (_l0 = (udList); _l0; _l0
= ((_l0)->rest)) { udInfo = ((_l0)->first); { { def = udInfo
-> foam; isDef = (((def)->hdr.tag) == FOAM_Def); defno
= ((def)->foamGen.hdr.info.defNo); if (bitvTest(rrInfo.class
, rrInfo.seen, defno)) continue; bitvSet(rrInfo.class, rrInfo
.seen, defno); if (bitvTest(rrInfo.class, rrInfo.cached, defno
)) { if (bitvTest(rrInfo.class, rrInfo.escapes, defno)) return
((int) 0); continue; } val = (isDef ? def->foamDef.rhs : def
->foamSet.rhs); while (((val)->hdr.tag) == FOAM_Cast) val
= val->foamCast.expr; if (((val)->hdr.tag) == FOAM_RRNew
) { rrDefNotEscapes(def); continue; } if (!( (((val)->hdr.
tag) == FOAM_Loc) || (((val)->hdr.tag) == FOAM_Par) )) { rrDefEscapes
(def); return ((int) 0); } if (!rr0NonEscapingLocal(val, seen
, cached, escapes)) { rrDefEscapes(def); return ((int) 0); } rrDefNotEscapes
(def); }; }; } }; }
790
791
792 /* Do we have a cached result? */{ { UdInfoList _l0; UdInfo udInfo; for (_l0 = (udList); _l0; _l0
= ((_l0)->rest)) { udInfo = ((_l0)->first); { { def = udInfo
-> foam; isDef = (((def)->hdr.tag) == FOAM_Def); defno
= ((def)->foamGen.hdr.info.defNo); if (bitvTest(rrInfo.class
, rrInfo.seen, defno)) continue; bitvSet(rrInfo.class, rrInfo
.seen, defno); if (bitvTest(rrInfo.class, rrInfo.cached, defno
)) { if (bitvTest(rrInfo.class, rrInfo.escapes, defno)) return
((int) 0); continue; } val = (isDef ? def->foamDef.rhs : def
->foamSet.rhs); while (((val)->hdr.tag) == FOAM_Cast) val
= val->foamCast.expr; if (((val)->hdr.tag) == FOAM_RRNew
) { rrDefNotEscapes(def); continue; } if (!( (((val)->hdr.
tag) == FOAM_Loc) || (((val)->hdr.tag) == FOAM_Par) )) { rrDefEscapes
(def); return ((int) 0); } if (!rr0NonEscapingLocal(val, seen
, cached, escapes)) { rrDefEscapes(def); return ((int) 0); } rrDefNotEscapes
(def); }; }; } }; }
793 if (rrDefIsKnown(defno)){ { UdInfoList _l0; UdInfo udInfo; for (_l0 = (udList); _l0; _l0
= ((_l0)->rest)) { udInfo = ((_l0)->first); { { def = udInfo
-> foam; isDef = (((def)->hdr.tag) == FOAM_Def); defno
= ((def)->foamGen.hdr.info.defNo); if (bitvTest(rrInfo.class
, rrInfo.seen, defno)) continue; bitvSet(rrInfo.class, rrInfo
.seen, defno); if (bitvTest(rrInfo.class, rrInfo.cached, defno
)) { if (bitvTest(rrInfo.class, rrInfo.escapes, defno)) return
((int) 0); continue; } val = (isDef ? def->foamDef.rhs : def
->foamSet.rhs); while (((val)->hdr.tag) == FOAM_Cast) val
= val->foamCast.expr; if (((val)->hdr.tag) == FOAM_RRNew
) { rrDefNotEscapes(def); continue; } if (!( (((val)->hdr.
tag) == FOAM_Loc) || (((val)->hdr.tag) == FOAM_Par) )) { rrDefEscapes
(def); return ((int) 0); } if (!rr0NonEscapingLocal(val, seen
, cached, escapes)) { rrDefEscapes(def); return ((int) 0); } rrDefNotEscapes
(def); }; }; } }; }
794 {{ { UdInfoList _l0; UdInfo udInfo; for (_l0 = (udList); _l0; _l0
= ((_l0)->rest)) { udInfo = ((_l0)->first); { { def = udInfo
-> foam; isDef = (((def)->hdr.tag) == FOAM_Def); defno
= ((def)->foamGen.hdr.info.defNo); if (bitvTest(rrInfo.class
, rrInfo.seen, defno)) continue; bitvSet(rrInfo.class, rrInfo
.seen, defno); if (bitvTest(rrInfo.class, rrInfo.cached, defno
)) { if (bitvTest(rrInfo.class, rrInfo.escapes, defno)) return
((int) 0); continue; } val = (isDef ? def->foamDef.rhs : def
->foamSet.rhs); while (((val)->hdr.tag) == FOAM_Cast) val
= val->foamCast.expr; if (((val)->hdr.tag) == FOAM_RRNew
) { rrDefNotEscapes(def); continue; } if (!( (((val)->hdr.
tag) == FOAM_Loc) || (((val)->hdr.tag) == FOAM_Par) )) { rrDefEscapes
(def); return ((int) 0); } if (!rr0NonEscapingLocal(val, seen
, cached, escapes)) { rrDefEscapes(def); return ((int) 0); } rrDefNotEscapes
(def); }; }; } }; }
795 /* Stop if this escapes */{ { UdInfoList _l0; UdInfo udInfo; for (_l0 = (udList); _l0; _l0
= ((_l0)->rest)) { udInfo = ((_l0)->first); { { def = udInfo
-> foam; isDef = (((def)->hdr.tag) == FOAM_Def); defno
= ((def)->foamGen.hdr.info.defNo); if (bitvTest(rrInfo.class
, rrInfo.seen, defno)) continue; bitvSet(rrInfo.class, rrInfo
.seen, defno); if (bitvTest(rrInfo.class, rrInfo.cached, defno
)) { if (bitvTest(rrInfo.class, rrInfo.escapes, defno)) return
((int) 0); continue; } val = (isDef ? def->foamDef.rhs : def
->foamSet.rhs); while (((val)->hdr.tag) == FOAM_Cast) val
= val->foamCast.expr; if (((val)->hdr.tag) == FOAM_RRNew
) { rrDefNotEscapes(def); continue; } if (!( (((val)->hdr.
tag) == FOAM_Loc) || (((val)->hdr.tag) == FOAM_Par) )) { rrDefEscapes
(def); return ((int) 0); } if (!rr0NonEscapingLocal(val, seen
, cached, escapes)) { rrDefEscapes(def); return ((int) 0); } rrDefNotEscapes
(def); }; }; } }; }
796 if (rrDefHasEscaped(defno)){ { UdInfoList _l0; UdInfo udInfo; for (_l0 = (udList); _l0; _l0
= ((_l0)->rest)) { udInfo = ((_l0)->first); { { def = udInfo
-> foam; isDef = (((def)->hdr.tag) == FOAM_Def); defno
= ((def)->foamGen.hdr.info.defNo); if (bitvTest(rrInfo.class
, rrInfo.seen, defno)) continue; bitvSet(rrInfo.class, rrInfo
.seen, defno); if (bitvTest(rrInfo.class, rrInfo.cached, defno
)) { if (bitvTest(rrInfo.class, rrInfo.escapes, defno)) return
((int) 0); continue; } val = (isDef ? def->foamDef.rhs : def
->foamSet.rhs); while (((val)->hdr.tag) == FOAM_Cast) val
= val->foamCast.expr; if (((val)->hdr.tag) == FOAM_RRNew
) { rrDefNotEscapes(def); continue; } if (!( (((val)->hdr.
tag) == FOAM_Loc) || (((val)->hdr.tag) == FOAM_Par) )) { rrDefEscapes
(def); return ((int) 0); } if (!rr0NonEscapingLocal(val, seen
, cached, escapes)) { rrDefEscapes(def); return ((int) 0); } rrDefNotEscapes
(def); }; }; } }; }
797 return false;{ { UdInfoList _l0; UdInfo udInfo; for (_l0 = (udList); _l0; _l0
= ((_l0)->rest)) { udInfo = ((_l0)->first); { { def = udInfo
-> foam; isDef = (((def)->hdr.tag) == FOAM_Def); defno
= ((def)->foamGen.hdr.info.defNo); if (bitvTest(rrInfo.class
, rrInfo.seen, defno)) continue; bitvSet(rrInfo.class, rrInfo
.seen, defno); if (bitvTest(rrInfo.class, rrInfo.cached, defno
)) { if (bitvTest(rrInfo.class, rrInfo.escapes, defno)) return
((int) 0); continue; } val = (isDef ? def->foamDef.rhs : def
->foamSet.rhs); while (((val)->hdr.tag) == FOAM_Cast) val
= val->foamCast.expr; if (((val)->hdr.tag) == FOAM_RRNew
) { rrDefNotEscapes(def); continue; } if (!( (((val)->hdr.
tag) == FOAM_Loc) || (((val)->hdr.tag) == FOAM_Par) )) { rrDefEscapes
(def); return ((int) 0); } if (!rr0NonEscapingLocal(val, seen
, cached, escapes)) { rrDefEscapes(def); return ((int) 0); } rrDefNotEscapes
(def); }; }; } }; }
798
799
800 /* Try next definition reaching here */{ { UdInfoList _l0; UdInfo udInfo; for (_l0 = (udList); _l0; _l0
= ((_l0)->rest)) { udInfo = ((_l0)->first); { { def = udInfo
-> foam; isDef = (((def)->hdr.tag) == FOAM_Def); defno
= ((def)->foamGen.hdr.info.defNo); if (bitvTest(rrInfo.class
, rrInfo.seen, defno)) continue; bitvSet(rrInfo.class, rrInfo
.seen, defno); if (bitvTest(rrInfo.class, rrInfo.cached, defno
)) { if (bitvTest(rrInfo.class, rrInfo.escapes, defno)) return
((int) 0); continue; } val = (isDef ? def->foamDef.rhs : def
->foamSet.rhs); while (((val)->hdr.tag) == FOAM_Cast) val
= val->foamCast.expr; if (((val)->hdr.tag) == FOAM_RRNew
) { rrDefNotEscapes(def); continue; } if (!( (((val)->hdr.
tag) == FOAM_Loc) || (((val)->hdr.tag) == FOAM_Par) )) { rrDefEscapes
(def); return ((int) 0); } if (!rr0NonEscapingLocal(val, seen
, cached, escapes)) { rrDefEscapes(def); return ((int) 0); } rrDefNotEscapes
(def); }; }; } }; }
801 continue;{ { UdInfoList _l0; UdInfo udInfo; for (_l0 = (udList); _l0; _l0
= ((_l0)->rest)) { udInfo = ((_l0)->first); { { def = udInfo
-> foam; isDef = (((def)->hdr.tag) == FOAM_Def); defno
= ((def)->foamGen.hdr.info.defNo); if (bitvTest(rrInfo.class
, rrInfo.seen, defno)) continue; bitvSet(rrInfo.class, rrInfo
.seen, defno); if (bitvTest(rrInfo.class, rrInfo.cached, defno
)) { if (bitvTest(rrInfo.class, rrInfo.escapes, defno)) return
((int) 0); continue; } val = (isDef ? def->foamDef.rhs : def
->foamSet.rhs); while (((val)->hdr.tag) == FOAM_Cast) val
= val->foamCast.expr; if (((val)->hdr.tag) == FOAM_RRNew
) { rrDefNotEscapes(def); continue; } if (!( (((val)->hdr.
tag) == FOAM_Loc) || (((val)->hdr.tag) == FOAM_Par) )) { rrDefEscapes
(def); return ((int) 0); } if (!rr0NonEscapingLocal(val, seen
, cached, escapes)) { rrDefEscapes(def); return ((int) 0); } rrDefNotEscapes
(def); }; }; } }; }
802 }{ { UdInfoList _l0; UdInfo udInfo; for (_l0 = (udList); _l0; _l0
= ((_l0)->rest)) { udInfo = ((_l0)->first); { { def = udInfo
-> foam; isDef = (((def)->hdr.tag) == FOAM_Def); defno
= ((def)->foamGen.hdr.info.defNo); if (bitvTest(rrInfo.class
, rrInfo.seen, defno)) continue; bitvSet(rrInfo.class, rrInfo
.seen, defno); if (bitvTest(rrInfo.class, rrInfo.cached, defno
)) { if (bitvTest(rrInfo.class, rrInfo.escapes, defno)) return
((int) 0); continue; } val = (isDef ? def->foamDef.rhs : def
->foamSet.rhs); while (((val)->hdr.tag) == FOAM_Cast) val
= val->foamCast.expr; if (((val)->hdr.tag) == FOAM_RRNew
) { rrDefNotEscapes(def); continue; } if (!( (((val)->hdr.
tag) == FOAM_Loc) || (((val)->hdr.tag) == FOAM_Par) )) { rrDefEscapes
(def); return ((int) 0); } if (!rr0NonEscapingLocal(val, seen
, cached, escapes)) { rrDefEscapes(def); return ((int) 0); } rrDefNotEscapes
(def); }; }; } }; }
803
804
805 /* Get the value that reaches this point */{ { UdInfoList _l0; UdInfo udInfo; for (_l0 = (udList); _l0; _l0
= ((_l0)->rest)) { udInfo = ((_l0)->first); { { def = udInfo
-> foam; isDef = (((def)->hdr.tag) == FOAM_Def); defno
= ((def)->foamGen.hdr.info.defNo); if (bitvTest(rrInfo.class
, rrInfo.seen, defno)) continue; bitvSet(rrInfo.class, rrInfo
.seen, defno); if (bitvTest(rrInfo.class, rrInfo.cached, defno
)) { if (bitvTest(rrInfo.class, rrInfo.escapes, defno)) return
((int) 0); continue; } val = (isDef ? def->foamDef.rhs : def
->foamSet.rhs); while (((val)->hdr.tag) == FOAM_Cast) val
= val->foamCast.expr; if (((val)->hdr.tag) == FOAM_RRNew
) { rrDefNotEscapes(def); continue; } if (!( (((val)->hdr.
tag) == FOAM_Loc) || (((val)->hdr.tag) == FOAM_Par) )) { rrDefEscapes
(def); return ((int) 0); } if (!rr0NonEscapingLocal(val, seen
, cached, escapes)) { rrDefEscapes(def); return ((int) 0); } rrDefNotEscapes
(def); }; }; } }; }
806 val = (isDef ? def->foamDef.rhs : def->foamSet.rhs);{ { UdInfoList _l0; UdInfo udInfo; for (_l0 = (udList); _l0; _l0
= ((_l0)->rest)) { udInfo = ((_l0)->first); { { def = udInfo
-> foam; isDef = (((def)->hdr.tag) == FOAM_Def); defno
= ((def)->foamGen.hdr.info.defNo); if (bitvTest(rrInfo.class
, rrInfo.seen, defno)) continue; bitvSet(rrInfo.class, rrInfo
.seen, defno); if (bitvTest(rrInfo.class, rrInfo.cached, defno
)) { if (bitvTest(rrInfo.class, rrInfo.escapes, defno)) return
((int) 0); continue; } val = (isDef ? def->foamDef.rhs : def
->foamSet.rhs); while (((val)->hdr.tag) == FOAM_Cast) val
= val->foamCast.expr; if (((val)->hdr.tag) == FOAM_RRNew
) { rrDefNotEscapes(def); continue; } if (!( (((val)->hdr.
tag) == FOAM_Loc) || (((val)->hdr.tag) == FOAM_Par) )) { rrDefEscapes
(def); return ((int) 0); } if (!rr0NonEscapingLocal(val, seen
, cached, escapes)) { rrDefEscapes(def); return ((int) 0); } rrDefNotEscapes
(def); }; }; } }; }
807
808
809 /* Remove any casts from the value */{ { UdInfoList _l0; UdInfo udInfo; for (_l0 = (udList); _l0; _l0
= ((_l0)->rest)) { udInfo = ((_l0)->first); { { def = udInfo
-> foam; isDef = (((def)->hdr.tag) == FOAM_Def); defno
= ((def)->foamGen.hdr.info.defNo); if (bitvTest(rrInfo.class
, rrInfo.seen, defno)) continue; bitvSet(rrInfo.class, rrInfo
.seen, defno); if (bitvTest(rrInfo.class, rrInfo.cached, defno
)) { if (bitvTest(rrInfo.class, rrInfo.escapes, defno)) return
((int) 0); continue; } val = (isDef ? def->foamDef.rhs : def
->foamSet.rhs); while (((val)->hdr.tag) == FOAM_Cast) val
= val->foamCast.expr; if (((val)->hdr.tag) == FOAM_RRNew
) { rrDefNotEscapes(def); continue; } if (!( (((val)->hdr.
tag) == FOAM_Loc) || (((val)->hdr.tag) == FOAM_Par) )) { rrDefEscapes
(def); return ((int) 0); } if (!rr0NonEscapingLocal(val, seen
, cached, escapes)) { rrDefEscapes(def); return ((int) 0); } rrDefNotEscapes
(def); }; }; } }; }
810 while (foamTag(val) == FOAM_Cast){ { UdInfoList _l0; UdInfo udInfo; for (_l0 = (udList); _l0; _l0
= ((_l0)->rest)) { udInfo = ((_l0)->first); { { def = udInfo
-> foam; isDef = (((def)->hdr.tag) == FOAM_Def); defno
= ((def)->foamGen.hdr.info.defNo); if (bitvTest(rrInfo.class
, rrInfo.seen, defno)) continue; bitvSet(rrInfo.class, rrInfo
.seen, defno); if (bitvTest(rrInfo.class, rrInfo.cached, defno
)) { if (bitvTest(rrInfo.class, rrInfo.escapes, defno)) return
((int) 0); continue; } val = (isDef ? def->foamDef.rhs : def
->foamSet.rhs); while (((val)->hdr.tag) == FOAM_Cast) val
= val->foamCast.expr; if (((val)->hdr.tag) == FOAM_RRNew
) { rrDefNotEscapes(def); continue; } if (!( (((val)->hdr.
tag) == FOAM_Loc) || (((val)->hdr.tag) == FOAM_Par) )) { rrDefEscapes
(def); return ((int) 0); } if (!rr0NonEscapingLocal(val, seen
, cached, escapes)) { rrDefEscapes(def); return ((int) 0); } rrDefNotEscapes
(def); }; }; } }; }
811 val = val->foamCast.expr;{ { UdInfoList _l0; UdInfo udInfo; for (_l0 = (udList); _l0; _l0
= ((_l0)->rest)) { udInfo = ((_l0)->first); { { def = udInfo
-> foam; isDef = (((def)->hdr.tag) == FOAM_Def); defno
= ((def)->foamGen.hdr.info.defNo); if (bitvTest(rrInfo.class
, rrInfo.seen, defno)) continue; bitvSet(rrInfo.class, rrInfo
.seen, defno); if (bitvTest(rrInfo.class, rrInfo.cached, defno
)) { if (bitvTest(rrInfo.class, rrInfo.escapes, defno)) return
((int) 0); continue; } val = (isDef ? def->foamDef.rhs : def
->foamSet.rhs); while (((val)->hdr.tag) == FOAM_Cast) val
= val->foamCast.expr; if (((val)->hdr.tag) == FOAM_RRNew
) { rrDefNotEscapes(def); continue; } if (!( (((val)->hdr.
tag) == FOAM_Loc) || (((val)->hdr.tag) == FOAM_Par) )) { rrDefEscapes
(def); return ((int) 0); } if (!rr0NonEscapingLocal(val, seen
, cached, escapes)) { rrDefEscapes(def); return ((int) 0); } rrDefNotEscapes
(def); }; }; } }; }
812
813
814 /* Try to mark RRNew definitions as non-escaping */{ { UdInfoList _l0; UdInfo udInfo; for (_l0 = (udList); _l0; _l0
= ((_l0)->rest)) { udInfo = ((_l0)->first); { { def = udInfo
-> foam; isDef = (((def)->hdr.tag) == FOAM_Def); defno
= ((def)->foamGen.hdr.info.defNo); if (bitvTest(rrInfo.class
, rrInfo.seen, defno)) continue; bitvSet(rrInfo.class, rrInfo
.seen, defno); if (bitvTest(rrInfo.class, rrInfo.cached, defno
)) { if (bitvTest(rrInfo.class, rrInfo.escapes, defno)) return
((int) 0); continue; } val = (isDef ? def->foamDef.rhs : def
->foamSet.rhs); while (((val)->hdr.tag) == FOAM_Cast) val
= val->foamCast.expr; if (((val)->hdr.tag) == FOAM_RRNew
) { rrDefNotEscapes(def); continue; } if (!( (((val)->hdr.
tag) == FOAM_Loc) || (((val)->hdr.tag) == FOAM_Par) )) { rrDefEscapes
(def); return ((int) 0); } if (!rr0NonEscapingLocal(val, seen
, cached, escapes)) { rrDefEscapes(def); return ((int) 0); } rrDefNotEscapes
(def); }; }; } }; }
815 if (foamTag(val) == FOAM_RRNew){ { UdInfoList _l0; UdInfo udInfo; for (_l0 = (udList); _l0; _l0
= ((_l0)->rest)) { udInfo = ((_l0)->first); { { def = udInfo
-> foam; isDef = (((def)->hdr.tag) == FOAM_Def); defno
= ((def)->foamGen.hdr.info.defNo); if (bitvTest(rrInfo.class
, rrInfo.seen, defno)) continue; bitvSet(rrInfo.class, rrInfo
.seen, defno); if (bitvTest(rrInfo.class, rrInfo.cached, defno
)) { if (bitvTest(rrInfo.class, rrInfo.escapes, defno)) return
((int) 0); continue; } val = (isDef ? def->foamDef.rhs : def
->foamSet.rhs); while (((val)->hdr.tag) == FOAM_Cast) val
= val->foamCast.expr; if (((val)->hdr.tag) == FOAM_RRNew
) { rrDefNotEscapes(def); continue; } if (!( (((val)->hdr.
tag) == FOAM_Loc) || (((val)->hdr.tag) == FOAM_Par) )) { rrDefEscapes
(def); return ((int) 0); } if (!rr0NonEscapingLocal(val, seen
, cached, escapes)) { rrDefEscapes(def); return ((int) 0); } rrDefNotEscapes
(def); }; }; } }; }
816 {{ { UdInfoList _l0; UdInfo udInfo; for (_l0 = (udList); _l0; _l0
= ((_l0)->rest)) { udInfo = ((_l0)->first); { { def = udInfo
-> foam; isDef = (((def)->hdr.tag) == FOAM_Def); defno
= ((def)->foamGen.hdr.info.defNo); if (bitvTest(rrInfo.class
, rrInfo.seen, defno)) continue; bitvSet(rrInfo.class, rrInfo
.seen, defno); if (bitvTest(rrInfo.class, rrInfo.cached, defno
)) { if (bitvTest(rrInfo.class, rrInfo.escapes, defno)) return
((int) 0); continue; } val = (isDef ? def->foamDef.rhs : def
->foamSet.rhs); while (((val)->hdr.tag) == FOAM_Cast) val
= val->foamCast.expr; if (((val)->hdr.tag) == FOAM_RRNew
) { rrDefNotEscapes(def); continue; } if (!( (((val)->hdr.
tag) == FOAM_Loc) || (((val)->hdr.tag) == FOAM_Par) )) { rrDefEscapes
(def); return ((int) 0); } if (!rr0NonEscapingLocal(val, seen
, cached, escapes)) { rrDefEscapes(def); return ((int) 0); } rrDefNotEscapes
(def); }; }; } }; }
817 /* Continue with the next reaching definition */{ { UdInfoList _l0; UdInfo udInfo; for (_l0 = (udList); _l0; _l0
= ((_l0)->rest)) { udInfo = ((_l0)->first); { { def = udInfo
-> foam; isDef = (((def)->hdr.tag) == FOAM_Def); defno
= ((def)->foamGen.hdr.info.defNo); if (bitvTest(rrInfo.class
, rrInfo.seen, defno)) continue; bitvSet(rrInfo.class, rrInfo
.seen, defno); if (bitvTest(rrInfo.class, rrInfo.cached, defno
)) { if (bitvTest(rrInfo.class, rrInfo.escapes, defno)) return
((int) 0); continue; } val = (isDef ? def->foamDef.rhs : def
->foamSet.rhs); while (((val)->hdr.tag) == FOAM_Cast) val
= val->foamCast.expr; if (((val)->hdr.tag) == FOAM_RRNew
) { rrDefNotEscapes(def); continue; } if (!( (((val)->hdr.
tag) == FOAM_Loc) || (((val)->hdr.tag) == FOAM_Par) )) { rrDefEscapes
(def); return ((int) 0); } if (!rr0NonEscapingLocal(val, seen
, cached, escapes)) { rrDefEscapes(def); return ((int) 0); } rrDefNotEscapes
(def); }; }; } }; }
818 rrDefNotEscapes(def);{ { UdInfoList _l0; UdInfo udInfo; for (_l0 = (udList); _l0; _l0
= ((_l0)->rest)) { udInfo = ((_l0)->first); { { def = udInfo
-> foam; isDef = (((def)->hdr.tag) == FOAM_Def); defno
= ((def)->foamGen.hdr.info.defNo); if (bitvTest(rrInfo.class
, rrInfo.seen, defno)) continue; bitvSet(rrInfo.class, rrInfo
.seen, defno); if (bitvTest(rrInfo.class, rrInfo.cached, defno
)) { if (bitvTest(rrInfo.class, rrInfo.escapes, defno)) return
((int) 0); continue; } val = (isDef ? def->foamDef.rhs : def
->foamSet.rhs); while (((val)->hdr.tag) == FOAM_Cast) val
= val->foamCast.expr; if (((val)->hdr.tag) == FOAM_RRNew
) { rrDefNotEscapes(def); continue; } if (!( (((val)->hdr.
tag) == FOAM_Loc) || (((val)->hdr.tag) == FOAM_Par) )) { rrDefEscapes
(def); return ((int) 0); } if (!rr0NonEscapingLocal(val, seen
, cached, escapes)) { rrDefEscapes(def); return ((int) 0); } rrDefNotEscapes
(def); }; }; } }; }
819 continue;{ { UdInfoList _l0; UdInfo udInfo; for (_l0 = (udList); _l0; _l0
= ((_l0)->rest)) { udInfo = ((_l0)->first); { { def = udInfo
-> foam; isDef = (((def)->hdr.tag) == FOAM_Def); defno
= ((def)->foamGen.hdr.info.defNo); if (bitvTest(rrInfo.class
, rrInfo.seen, defno)) continue; bitvSet(rrInfo.class, rrInfo
.seen, defno); if (bitvTest(rrInfo.class, rrInfo.cached, defno
)) { if (bitvTest(rrInfo.class, rrInfo.escapes, defno)) return
((int) 0); continue; } val = (isDef ? def->foamDef.rhs : def
->foamSet.rhs); while (((val)->hdr.tag) == FOAM_Cast) val
= val->foamCast.expr; if (((val)->hdr.tag) == FOAM_RRNew
) { rrDefNotEscapes(def); continue; } if (!( (((val)->hdr.
tag) == FOAM_Loc) || (((val)->hdr.tag) == FOAM_Par) )) { rrDefEscapes
(def); return ((int) 0); } if (!rr0NonEscapingLocal(val, seen
, cached, escapes)) { rrDefEscapes(def); return ((int) 0); } rrDefNotEscapes
(def); }; }; } }; }
820 }{ { UdInfoList _l0; UdInfo udInfo; for (_l0 = (udList); _l0; _l0
= ((_l0)->rest)) { udInfo = ((_l0)->first); { { def = udInfo
-> foam; isDef = (((def)->hdr.tag) == FOAM_Def); defno
= ((def)->foamGen.hdr.info.defNo); if (bitvTest(rrInfo.class
, rrInfo.seen, defno)) continue; bitvSet(rrInfo.class, rrInfo
.seen, defno); if (bitvTest(rrInfo.class, rrInfo.cached, defno
)) { if (bitvTest(rrInfo.class, rrInfo.escapes, defno)) return
((int) 0); continue; } val = (isDef ? def->foamDef.rhs : def
->foamSet.rhs); while (((val)->hdr.tag) == FOAM_Cast) val
= val->foamCast.expr; if (((val)->hdr.tag) == FOAM_RRNew
) { rrDefNotEscapes(def); continue; } if (!( (((val)->hdr.
tag) == FOAM_Loc) || (((val)->hdr.tag) == FOAM_Par) )) { rrDefEscapes
(def); return ((int) 0); } if (!rr0NonEscapingLocal(val, seen
, cached, escapes)) { rrDefEscapes(def); return ((int) 0); } rrDefNotEscapes
(def); }; }; } }; }
821
822
823 /* If it isn't a local then it must escape. */{ { UdInfoList _l0; UdInfo udInfo; for (_l0 = (udList); _l0; _l0
= ((_l0)->rest)) { udInfo = ((_l0)->first); { { def = udInfo
-> foam; isDef = (((def)->hdr.tag) == FOAM_Def); defno
= ((def)->foamGen.hdr.info.defNo); if (bitvTest(rrInfo.class
, rrInfo.seen, defno)) continue; bitvSet(rrInfo.class, rrInfo
.seen, defno); if (bitvTest(rrInfo.class, rrInfo.cached, defno
)) { if (bitvTest(rrInfo.class, rrInfo.escapes, defno)) return
((int) 0); continue; } val = (isDef ? def->foamDef.rhs : def
->foamSet.rhs); while (((val)->hdr.tag) == FOAM_Cast) val
= val->foamCast.expr; if (((val)->hdr.tag) == FOAM_RRNew
) { rrDefNotEscapes(def); continue; } if (!( (((val)->hdr.
tag) == FOAM_Loc) || (((val)->hdr.tag) == FOAM_Par) )) { rrDefEscapes
(def); return ((int) 0); } if (!rr0NonEscapingLocal(val, seen
, cached, escapes)) { rrDefEscapes(def); return ((int) 0); } rrDefNotEscapes
(def); }; }; } }; }
824 if (!rrIsLocal(val)){ { UdInfoList _l0; UdInfo udInfo; for (_l0 = (udList); _l0; _l0
= ((_l0)->rest)) { udInfo = ((_l0)->first); { { def = udInfo
-> foam; isDef = (((def)->hdr.tag) == FOAM_Def); defno
= ((def)->foamGen.hdr.info.defNo); if (bitvTest(rrInfo.class
, rrInfo.seen, defno)) continue; bitvSet(rrInfo.class, rrInfo
.seen, defno); if (bitvTest(rrInfo.class, rrInfo.cached, defno
)) { if (bitvTest(rrInfo.class, rrInfo.escapes, defno)) return
((int) 0); continue; } val = (isDef ? def->foamDef.rhs : def
->foamSet.rhs); while (((val)->hdr.tag) == FOAM_Cast) val
= val->foamCast.expr; if (((val)->hdr.tag) == FOAM_RRNew
) { rrDefNotEscapes(def); continue; } if (!( (((val)->hdr.
tag) == FOAM_Loc) || (((val)->hdr.tag) == FOAM_Par) )) { rrDefEscapes
(def); return ((int) 0); } if (!rr0NonEscapingLocal(val, seen
, cached, escapes)) { rrDefEscapes(def); return ((int) 0); } rrDefNotEscapes
(def); }; }; } }; }
825 {{ { UdInfoList _l0; UdInfo udInfo; for (_l0 = (udList); _l0; _l0
= ((_l0)->rest)) { udInfo = ((_l0)->first); { { def = udInfo
-> foam; isDef = (((def)->hdr.tag) == FOAM_Def); defno
= ((def)->foamGen.hdr.info.defNo); if (bitvTest(rrInfo.class
, rrInfo.seen, defno)) continue; bitvSet(rrInfo.class, rrInfo
.seen, defno); if (bitvTest(rrInfo.class, rrInfo.cached, defno
)) { if (bitvTest(rrInfo.class, rrInfo.escapes, defno)) return
((int) 0); continue; } val = (isDef ? def->foamDef.rhs : def
->foamSet.rhs); while (((val)->hdr.tag) == FOAM_Cast) val
= val->foamCast.expr; if (((val)->hdr.tag) == FOAM_RRNew
) { rrDefNotEscapes(def); continue; } if (!( (((val)->hdr.
tag) == FOAM_Loc) || (((val)->hdr.tag) == FOAM_Par) )) { rrDefEscapes
(def); return ((int) 0); } if (!rr0NonEscapingLocal(val, seen
, cached, escapes)) { rrDefEscapes(def); return ((int) 0); } rrDefNotEscapes
(def); }; }; } }; }
826 /* Mark as an escaping definition */{ { UdInfoList _l0; UdInfo udInfo; for (_l0 = (udList); _l0; _l0
= ((_l0)->rest)) { udInfo = ((_l0)->first); { { def = udInfo
-> foam; isDef = (((def)->hdr.tag) == FOAM_Def); defno
= ((def)->foamGen.hdr.info.defNo); if (bitvTest(rrInfo.class
, rrInfo.seen, defno)) continue; bitvSet(rrInfo.class, rrInfo
.seen, defno); if (bitvTest(rrInfo.class, rrInfo.cached, defno
)) { if (bitvTest(rrInfo.class, rrInfo.escapes, defno)) return
((int) 0); continue; } val = (isDef ? def->foamDef.rhs : def
->foamSet.rhs); while (((val)->hdr.tag) == FOAM_Cast) val
= val->foamCast.expr; if (((val)->hdr.tag) == FOAM_RRNew
) { rrDefNotEscapes(def); continue; } if (!( (((val)->hdr.
tag) == FOAM_Loc) || (((val)->hdr.tag) == FOAM_Par) )) { rrDefEscapes
(def); return ((int) 0); } if (!rr0NonEscapingLocal(val, seen
, cached, escapes)) { rrDefEscapes(def); return ((int) 0); } rrDefNotEscapes
(def); }; }; } }; }
827 rrDefEscapes(def);{ { UdInfoList _l0; UdInfo udInfo; for (_l0 = (udList); _l0; _l0
= ((_l0)->rest)) { udInfo = ((_l0)->first); { { def = udInfo
-> foam; isDef = (((def)->hdr.tag) == FOAM_Def); defno
= ((def)->foamGen.hdr.info.defNo); if (bitvTest(rrInfo.class
, rrInfo.seen, defno)) continue; bitvSet(rrInfo.class, rrInfo
.seen, defno); if (bitvTest(rrInfo.class, rrInfo.cached, defno
)) { if (bitvTest(rrInfo.class, rrInfo.escapes, defno)) return
((int) 0); continue; } val = (isDef ? def->foamDef.rhs : def
->foamSet.rhs); while (((val)->hdr.tag) == FOAM_Cast) val
= val->foamCast.expr; if (((val)->hdr.tag) == FOAM_RRNew
) { rrDefNotEscapes(def); continue; } if (!( (((val)->hdr.
tag) == FOAM_Loc) || (((val)->hdr.tag) == FOAM_Par) )) { rrDefEscapes
(def); return ((int) 0); } if (!rr0NonEscapingLocal(val, seen
, cached, escapes)) { rrDefEscapes(def); return ((int) 0); } rrDefNotEscapes
(def); }; }; } }; }
828 return false;{ { UdInfoList _l0; UdInfo udInfo; for (_l0 = (udList); _l0; _l0
= ((_l0)->rest)) { udInfo = ((_l0)->first); { { def = udInfo
-> foam; isDef = (((def)->hdr.tag) == FOAM_Def); defno
= ((def)->foamGen.hdr.info.defNo); if (bitvTest(rrInfo.class
, rrInfo.seen, defno)) continue; bitvSet(rrInfo.class, rrInfo
.seen, defno); if (bitvTest(rrInfo.class, rrInfo.cached, defno
)) { if (bitvTest(rrInfo.class, rrInfo.escapes, defno)) return
((int) 0); continue; } val = (isDef ? def->foamDef.rhs : def
->foamSet.rhs); while (((val)->hdr.tag) == FOAM_Cast) val
= val->foamCast.expr; if (((val)->hdr.tag) == FOAM_RRNew
) { rrDefNotEscapes(def); continue; } if (!( (((val)->hdr.
tag) == FOAM_Loc) || (((val)->hdr.tag) == FOAM_Par) )) { rrDefEscapes
(def); return ((int) 0); } if (!rr0NonEscapingLocal(val, seen
, cached, escapes)) { rrDefEscapes(def); return ((int) 0); } rrDefNotEscapes
(def); }; }; } }; }
829 }{ { UdInfoList _l0; UdInfo udInfo; for (_l0 = (udList); _l0; _l0
= ((_l0)->rest)) { udInfo = ((_l0)->first); { { def = udInfo
-> foam; isDef = (((def)->hdr.tag) == FOAM_Def); defno
= ((def)->foamGen.hdr.info.defNo); if (bitvTest(rrInfo.class
, rrInfo.seen, defno)) continue; bitvSet(rrInfo.class, rrInfo
.seen, defno); if (bitvTest(rrInfo.class, rrInfo.cached, defno
)) { if (bitvTest(rrInfo.class, rrInfo.escapes, defno)) return
((int) 0); continue; } val = (isDef ? def->foamDef.rhs : def
->foamSet.rhs); while (((val)->hdr.tag) == FOAM_Cast) val
= val->foamCast.expr; if (((val)->hdr.tag) == FOAM_RRNew
) { rrDefNotEscapes(def); continue; } if (!( (((val)->hdr.
tag) == FOAM_Loc) || (((val)->hdr.tag) == FOAM_Par) )) { rrDefEscapes
(def); return ((int) 0); } if (!rr0NonEscapingLocal(val, seen
, cached, escapes)) { rrDefEscapes(def); return ((int) 0); } rrDefNotEscapes
(def); }; }; } }; }
830
831
832 /* Trace the reaching definitions of this local */{ { UdInfoList _l0; UdInfo udInfo; for (_l0 = (udList); _l0; _l0
= ((_l0)->rest)) { udInfo = ((_l0)->first); { { def = udInfo
-> foam; isDef = (((def)->hdr.tag) == FOAM_Def); defno
= ((def)->foamGen.hdr.info.defNo); if (bitvTest(rrInfo.class
, rrInfo.seen, defno)) continue; bitvSet(rrInfo.class, rrInfo
.seen, defno); if (bitvTest(rrInfo.class, rrInfo.cached, defno
)) { if (bitvTest(rrInfo.class, rrInfo.escapes, defno)) return
((int) 0); continue; } val = (isDef ? def->foamDef.rhs : def
->foamSet.rhs); while (((val)->hdr.tag) == FOAM_Cast) val
= val->foamCast.expr; if (((val)->hdr.tag) == FOAM_RRNew
) { rrDefNotEscapes(def); continue; } if (!( (((val)->hdr.
tag) == FOAM_Loc) || (((val)->hdr.tag) == FOAM_Par) )) { rrDefEscapes
(def); return ((int) 0); } if (!rr0NonEscapingLocal(val, seen
, cached, escapes)) { rrDefEscapes(def); return ((int) 0); } rrDefNotEscapes
(def); }; }; } }; }
833 if (!rr0NonEscapingLocal(val, seen, cached, escapes)){ { UdInfoList _l0; UdInfo udInfo; for (_l0 = (udList); _l0; _l0
= ((_l0)->rest)) { udInfo = ((_l0)->first); { { def = udInfo
-> foam; isDef = (((def)->hdr.tag) == FOAM_Def); defno
= ((def)->foamGen.hdr.info.defNo); if (bitvTest(rrInfo.class
, rrInfo.seen, defno)) continue; bitvSet(rrInfo.class, rrInfo
.seen, defno); if (bitvTest(rrInfo.class, rrInfo.cached, defno
)) { if (bitvTest(rrInfo.class, rrInfo.escapes, defno)) return
((int) 0); continue; } val = (isDef ? def->foamDef.rhs : def
->foamSet.rhs); while (((val)->hdr.tag) == FOAM_Cast) val
= val->foamCast.expr; if (((val)->hdr.tag) == FOAM_RRNew
) { rrDefNotEscapes(def); continue; } if (!( (((val)->hdr.
tag) == FOAM_Loc) || (((val)->hdr.tag) == FOAM_Par) )) { rrDefEscapes
(def); return ((int) 0); } if (!rr0NonEscapingLocal(val, seen
, cached, escapes)) { rrDefEscapes(def); return ((int) 0); } rrDefNotEscapes
(def); }; }; } }; }
834 {{ { UdInfoList _l0; UdInfo udInfo; for (_l0 = (udList); _l0; _l0
= ((_l0)->rest)) { udInfo = ((_l0)->first); { { def = udInfo
-> foam; isDef = (((def)->hdr.tag) == FOAM_Def); defno
= ((def)->foamGen.hdr.info.defNo); if (bitvTest(rrInfo.class
, rrInfo.seen, defno)) continue; bitvSet(rrInfo.class, rrInfo
.seen, defno); if (bitvTest(rrInfo.class, rrInfo.cached, defno
)) { if (bitvTest(rrInfo.class, rrInfo.escapes, defno)) return
((int) 0); continue; } val = (isDef ? def->foamDef.rhs : def
->foamSet.rhs); while (((val)->hdr.tag) == FOAM_Cast) val
= val->foamCast.expr; if (((val)->hdr.tag) == FOAM_RRNew
) { rrDefNotEscapes(def); continue; } if (!( (((val)->hdr.
tag) == FOAM_Loc) || (((val)->hdr.tag) == FOAM_Par) )) { rrDefEscapes
(def); return ((int) 0); } if (!rr0NonEscapingLocal(val, seen
, cached, escapes)) { rrDefEscapes(def); return ((int) 0); } rrDefNotEscapes
(def); }; }; } }; }
835 /* This definition escapes - mark it */{ { UdInfoList _l0; UdInfo udInfo; for (_l0 = (udList); _l0; _l0
= ((_l0)->rest)) { udInfo = ((_l0)->first); { { def = udInfo
-> foam; isDef = (((def)->hdr.tag) == FOAM_Def); defno
= ((def)->foamGen.hdr.info.defNo); if (bitvTest(rrInfo.class
, rrInfo.seen, defno)) continue; bitvSet(rrInfo.class, rrInfo
.seen, defno); if (bitvTest(rrInfo.class, rrInfo.cached, defno
)) { if (bitvTest(rrInfo.class, rrInfo.escapes, defno)) return
((int) 0); continue; } val = (isDef ? def->foamDef.rhs : def
->foamSet.rhs); while (((val)->hdr.tag) == FOAM_Cast) val
= val->foamCast.expr; if (((val)->hdr.tag) == FOAM_RRNew
) { rrDefNotEscapes(def); continue; } if (!( (((val)->hdr.
tag) == FOAM_Loc) || (((val)->hdr.tag) == FOAM_Par) )) { rrDefEscapes
(def); return ((int) 0); } if (!rr0NonEscapingLocal(val, seen
, cached, escapes)) { rrDefEscapes(def); return ((int) 0); } rrDefNotEscapes
(def); }; }; } }; }
836 rrDefEscapes(def);{ { UdInfoList _l0; UdInfo udInfo; for (_l0 = (udList); _l0; _l0
= ((_l0)->rest)) { udInfo = ((_l0)->first); { { def = udInfo
-> foam; isDef = (((def)->hdr.tag) == FOAM_Def); defno
= ((def)->foamGen.hdr.info.defNo); if (bitvTest(rrInfo.class
, rrInfo.seen, defno)) continue; bitvSet(rrInfo.class, rrInfo
.seen, defno); if (bitvTest(rrInfo.class, rrInfo.cached, defno
)) { if (bitvTest(rrInfo.class, rrInfo.escapes, defno)) return
((int) 0); continue; } val = (isDef ? def->foamDef.rhs : def
->foamSet.rhs); while (((val)->hdr.tag) == FOAM_Cast) val
= val->foamCast.expr; if (((val)->hdr.tag) == FOAM_RRNew
) { rrDefNotEscapes(def); continue; } if (!( (((val)->hdr.
tag) == FOAM_Loc) || (((val)->hdr.tag) == FOAM_Par) )) { rrDefEscapes
(def); return ((int) 0); } if (!rr0NonEscapingLocal(val, seen
, cached, escapes)) { rrDefEscapes(def); return ((int) 0); } rrDefNotEscapes
(def); }; }; } }; }
837 return false;{ { UdInfoList _l0; UdInfo udInfo; for (_l0 = (udList); _l0; _l0
= ((_l0)->rest)) { udInfo = ((_l0)->first); { { def = udInfo
-> foam; isDef = (((def)->hdr.tag) == FOAM_Def); defno
= ((def)->foamGen.hdr.info.defNo); if (bitvTest(rrInfo.class
, rrInfo.seen, defno)) continue; bitvSet(rrInfo.class, rrInfo
.seen, defno); if (bitvTest(rrInfo.class, rrInfo.cached, defno
)) { if (bitvTest(rrInfo.class, rrInfo.escapes, defno)) return
((int) 0); continue; } val = (isDef ? def->foamDef.rhs : def
->foamSet.rhs); while (((val)->hdr.tag) == FOAM_Cast) val
= val->foamCast.expr; if (((val)->hdr.tag) == FOAM_RRNew
) { rrDefNotEscapes(def); continue; } if (!( (((val)->hdr.
tag) == FOAM_Loc) || (((val)->hdr.tag) == FOAM_Par) )) { rrDefEscapes
(def); return ((int) 0); } if (!rr0NonEscapingLocal(val, seen
, cached, escapes)) { rrDefEscapes(def); return ((int) 0); } rrDefNotEscapes
(def); }; }; } }; }
838 }{ { UdInfoList _l0; UdInfo udInfo; for (_l0 = (udList); _l0; _l0
= ((_l0)->rest)) { udInfo = ((_l0)->first); { { def = udInfo
-> foam; isDef = (((def)->hdr.tag) == FOAM_Def); defno
= ((def)->foamGen.hdr.info.defNo); if (bitvTest(rrInfo.class
, rrInfo.seen, defno)) continue; bitvSet(rrInfo.class, rrInfo
.seen, defno); if (bitvTest(rrInfo.class, rrInfo.cached, defno
)) { if (bitvTest(rrInfo.class, rrInfo.escapes, defno)) return
((int) 0); continue; } val = (isDef ? def->foamDef.rhs : def
->foamSet.rhs); while (((val)->hdr.tag) == FOAM_Cast) val
= val->foamCast.expr; if (((val)->hdr.tag) == FOAM_RRNew
) { rrDefNotEscapes(def); continue; } if (!( (((val)->hdr.
tag) == FOAM_Loc) || (((val)->hdr.tag) == FOAM_Par) )) { rrDefEscapes
(def); return ((int) 0); } if (!rr0NonEscapingLocal(val, seen
, cached, escapes)) { rrDefEscapes(def); return ((int) 0); } rrDefNotEscapes
(def); }; }; } }; }
839
840
841 /* This definition doesn't appear to escape */{ { UdInfoList _l0; UdInfo udInfo; for (_l0 = (udList); _l0; _l0
= ((_l0)->rest)) { udInfo = ((_l0)->first); { { def = udInfo
-> foam; isDef = (((def)->hdr.tag) == FOAM_Def); defno
= ((def)->foamGen.hdr.info.defNo); if (bitvTest(rrInfo.class
, rrInfo.seen, defno)) continue; bitvSet(rrInfo.class, rrInfo
.seen, defno); if (bitvTest(rrInfo.class, rrInfo.cached, defno
)) { if (bitvTest(rrInfo.class, rrInfo.escapes, defno)) return
((int) 0); continue; } val = (isDef ? def->foamDef.rhs : def
->foamSet.rhs); while (((val)->hdr.tag) == FOAM_Cast) val
= val->foamCast.expr; if (((val)->hdr.tag) == FOAM_RRNew
) { rrDefNotEscapes(def); continue; } if (!( (((val)->hdr.
tag) == FOAM_Loc) || (((val)->hdr.tag) == FOAM_Par) )) { rrDefEscapes
(def); return ((int) 0); } if (!rr0NonEscapingLocal(val, seen
, cached, escapes)) { rrDefEscapes(def); return ((int) 0); } rrDefNotEscapes
(def); }; }; } }; }
842 rrDefNotEscapes(def);{ { UdInfoList _l0; UdInfo udInfo; for (_l0 = (udList); _l0; _l0
= ((_l0)->rest)) { udInfo = ((_l0)->first); { { def = udInfo
-> foam; isDef = (((def)->hdr.tag) == FOAM_Def); defno
= ((def)->foamGen.hdr.info.defNo); if (bitvTest(rrInfo.class
, rrInfo.seen, defno)) continue; bitvSet(rrInfo.class, rrInfo
.seen, defno); if (bitvTest(rrInfo.class, rrInfo.cached, defno
)) { if (bitvTest(rrInfo.class, rrInfo.escapes, defno)) return
((int) 0); continue; } val = (isDef ? def->foamDef.rhs : def
->foamSet.rhs); while (((val)->hdr.tag) == FOAM_Cast) val
= val->foamCast.expr; if (((val)->hdr.tag) == FOAM_RRNew
) { rrDefNotEscapes(def); continue; } if (!( (((val)->hdr.
tag) == FOAM_Loc) || (((val)->hdr.tag) == FOAM_Par) )) { rrDefEscapes
(def); return ((int) 0); } if (!rr0NonEscapingLocal(val, seen
, cached, escapes)) { rrDefEscapes(def); return ((int) 0); } rrDefNotEscapes
(def); }; }; } }; }
843 }){ { UdInfoList _l0; UdInfo udInfo; for (_l0 = (udList); _l0; _l0
= ((_l0)->rest)) { udInfo = ((_l0)->first); { { def = udInfo
-> foam; isDef = (((def)->hdr.tag) == FOAM_Def); defno
= ((def)->foamGen.hdr.info.defNo); if (bitvTest(rrInfo.class
, rrInfo.seen, defno)) continue; bitvSet(rrInfo.class, rrInfo
.seen, defno); if (bitvTest(rrInfo.class, rrInfo.cached, defno
)) { if (bitvTest(rrInfo.class, rrInfo.escapes, defno)) return
((int) 0); continue; } val = (isDef ? def->foamDef.rhs : def
->foamSet.rhs); while (((val)->hdr.tag) == FOAM_Cast) val
= val->foamCast.expr; if (((val)->hdr.tag) == FOAM_RRNew
) { rrDefNotEscapes(def); continue; } if (!( (((val)->hdr.
tag) == FOAM_Loc) || (((val)->hdr.tag) == FOAM_Par) )) { rrDefEscapes
(def); return ((int) 0); } if (!rr0NonEscapingLocal(val, seen
, cached, escapes)) { rrDefEscapes(def); return ((int) 0); } rrDefNotEscapes
(def); }; }; } }; }
;
844
845
846 /* No defs escape */
847 return true1;
848}
849
850
851localstatic void
852rrReplace(BBlock bb)
853{
854 Foam code = bb->code;
855 FoamList newcode = listNil(Foam)((FoamList) 0);
856
857
858 /*
859 * Walk the statements of the block looking for raw
860 * records to replace.
861 */
862 foamIter(code, stmtp,{ { String argf = (foamInfoTable [(int)(((code)->hdr.tag))
-(int)FOAM_START]).argf; Length _i; for (_i = 0; _i < ((code
)->hdr.argc); _i++, argf++) { if (*argf == '*') argf--; if
(*argf == 'C') { Foam *stmtp = (Foam *) ((code)->foamGen.
argv)+_i; { { Foam stmt = *stmtp; if (( (((stmt)->hdr.tag)
== FOAM_Set) || (((stmt)->hdr.tag) == FOAM_Def) )) stmt =
rrReplaceDef(stmt, &newcode); stmt = rrReplaceDeeply(stmt
); newcode = (Foam_listPointer->Cons)(stmt, newcode); }; }
; } } }; }
863 {{ { String argf = (foamInfoTable [(int)(((code)->hdr.tag))
-(int)FOAM_START]).argf; Length _i; for (_i = 0; _i < ((code
)->hdr.argc); _i++, argf++) { if (*argf == '*') argf--; if
(*argf == 'C') { Foam *stmtp = (Foam *) ((code)->foamGen.
argv)+_i; { { Foam stmt = *stmtp; if (( (((stmt)->hdr.tag)
== FOAM_Set) || (((stmt)->hdr.tag) == FOAM_Def) )) stmt =
rrReplaceDef(stmt, &newcode); stmt = rrReplaceDeeply(stmt
); newcode = (Foam_listPointer->Cons)(stmt, newcode); }; }
; } } }; }
864 Foam stmt = *stmtp;{ { String argf = (foamInfoTable [(int)(((code)->hdr.tag))
-(int)FOAM_START]).argf; Length _i; for (_i = 0; _i < ((code
)->hdr.argc); _i++, argf++) { if (*argf == '*') argf--; if
(*argf == 'C') { Foam *stmtp = (Foam *) ((code)->foamGen.
argv)+_i; { { Foam stmt = *stmtp; if (( (((stmt)->hdr.tag)
== FOAM_Set) || (((stmt)->hdr.tag) == FOAM_Def) )) stmt =
rrReplaceDef(stmt, &newcode); stmt = rrReplaceDeeply(stmt
); newcode = (Foam_listPointer->Cons)(stmt, newcode); }; }
; } } }; }
865
866
867 /* Definition to be replaced? */{ { String argf = (foamInfoTable [(int)(((code)->hdr.tag))
-(int)FOAM_START]).argf; Length _i; for (_i = 0; _i < ((code
)->hdr.argc); _i++, argf++) { if (*argf == '*') argf--; if
(*argf == 'C') { Foam *stmtp = (Foam *) ((code)->foamGen.
argv)+_i; { { Foam stmt = *stmtp; if (( (((stmt)->hdr.tag)
== FOAM_Set) || (((stmt)->hdr.tag) == FOAM_Def) )) stmt =
rrReplaceDef(stmt, &newcode); stmt = rrReplaceDeeply(stmt
); newcode = (Foam_listPointer->Cons)(stmt, newcode); }; }
; } } }; }
868 if (rrIsDef(stmt)){ { String argf = (foamInfoTable [(int)(((code)->hdr.tag))
-(int)FOAM_START]).argf; Length _i; for (_i = 0; _i < ((code
)->hdr.argc); _i++, argf++) { if (*argf == '*') argf--; if
(*argf == 'C') { Foam *stmtp = (Foam *) ((code)->foamGen.
argv)+_i; { { Foam stmt = *stmtp; if (( (((stmt)->hdr.tag)
== FOAM_Set) || (((stmt)->hdr.tag) == FOAM_Def) )) stmt =
rrReplaceDef(stmt, &newcode); stmt = rrReplaceDeeply(stmt
); newcode = (Foam_listPointer->Cons)(stmt, newcode); }; }
; } } }; }
869 stmt = rrReplaceDef(stmt, &newcode);{ { String argf = (foamInfoTable [(int)(((code)->hdr.tag))
-(int)FOAM_START]).argf; Length _i; for (_i = 0; _i < ((code
)->hdr.argc); _i++, argf++) { if (*argf == '*') argf--; if
(*argf == 'C') { Foam *stmtp = (Foam *) ((code)->foamGen.
argv)+_i; { { Foam stmt = *stmtp; if (( (((stmt)->hdr.tag)
== FOAM_Set) || (((stmt)->hdr.tag) == FOAM_Def) )) stmt =
rrReplaceDef(stmt, &newcode); stmt = rrReplaceDeeply(stmt
); newcode = (Foam_listPointer->Cons)(stmt, newcode); }; }
; } } }; }
870
871
872 /* Try to replace any RRElts */{ { String argf = (foamInfoTable [(int)(((code)->hdr.tag))
-(int)FOAM_START]).argf; Length _i; for (_i = 0; _i < ((code
)->hdr.argc); _i++, argf++) { if (*argf == '*') argf--; if
(*argf == 'C') { Foam *stmtp = (Foam *) ((code)->foamGen.
argv)+_i; { { Foam stmt = *stmtp; if (( (((stmt)->hdr.tag)
== FOAM_Set) || (((stmt)->hdr.tag) == FOAM_Def) )) stmt =
rrReplaceDef(stmt, &newcode); stmt = rrReplaceDeeply(stmt
); newcode = (Foam_listPointer->Cons)(stmt, newcode); }; }
; } } }; }
873 stmt = rrReplaceDeeply(stmt);{ { String argf = (foamInfoTable [(int)(((code)->hdr.tag))
-(int)FOAM_START]).argf; Length _i; for (_i = 0; _i < ((code
)->hdr.argc); _i++, argf++) { if (*argf == '*') argf--; if
(*argf == 'C') { Foam *stmtp = (Foam *) ((code)->foamGen.
argv)+_i; { { Foam stmt = *stmtp; if (( (((stmt)->hdr.tag)
== FOAM_Set) || (((stmt)->hdr.tag) == FOAM_Def) )) stmt =
rrReplaceDef(stmt, &newcode); stmt = rrReplaceDeeply(stmt
); newcode = (Foam_listPointer->Cons)(stmt, newcode); }; }
; } } }; }
874
875
876 /* Add this statement to the code list */{ { String argf = (foamInfoTable [(int)(((code)->hdr.tag))
-(int)FOAM_START]).argf; Length _i; for (_i = 0; _i < ((code
)->hdr.argc); _i++, argf++) { if (*argf == '*') argf--; if
(*argf == 'C') { Foam *stmtp = (Foam *) ((code)->foamGen.
argv)+_i; { { Foam stmt = *stmtp; if (( (((stmt)->hdr.tag)
== FOAM_Set) || (((stmt)->hdr.tag) == FOAM_Def) )) stmt =
rrReplaceDef(stmt, &newcode); stmt = rrReplaceDeeply(stmt
); newcode = (Foam_listPointer->Cons)(stmt, newcode); }; }
; } } }; }
877 newcode = listCons(Foam)(stmt, newcode);{ { String argf = (foamInfoTable [(int)(((code)->hdr.tag))
-(int)FOAM_START]).argf; Length _i; for (_i = 0; _i < ((code
)->hdr.argc); _i++, argf++) { if (*argf == '*') argf--; if
(*argf == 'C') { Foam *stmtp = (Foam *) ((code)->foamGen.
argv)+_i; { { Foam stmt = *stmtp; if (( (((stmt)->hdr.tag)
== FOAM_Set) || (((stmt)->hdr.tag) == FOAM_Def) )) stmt =
rrReplaceDef(stmt, &newcode); stmt = rrReplaceDeeply(stmt
); newcode = (Foam_listPointer->Cons)(stmt, newcode); }; }
; } } }; }
878 }){ { String argf = (foamInfoTable [(int)(((code)->hdr.tag))
-(int)FOAM_START]).argf; Length _i; for (_i = 0; _i < ((code
)->hdr.argc); _i++, argf++) { if (*argf == '*') argf--; if
(*argf == 'C') { Foam *stmtp = (Foam *) ((code)->foamGen.
argv)+_i; { { Foam stmt = *stmtp; if (( (((stmt)->hdr.tag)
== FOAM_Set) || (((stmt)->hdr.tag) == FOAM_Def) )) stmt =
rrReplaceDef(stmt, &newcode); stmt = rrReplaceDeeply(stmt
); newcode = (Foam_listPointer->Cons)(stmt, newcode); }; }
; } } }; }
;
879
880
881 /* Replace the code for this BBlock */
882 newcode = listNReverse(Foam)(Foam_listPointer->NReverse)(newcode);
883 bb->code = foamNewOfList(FOAM_Seq, newcode);
884
885 /* FIXME: free newcode and the old bb->code top-level seq node */
886}
887
888
889localstatic Foam
890rrReplaceDef(Foam def, FoamList *newcodep)
891{
892 /* See if we can replace the rhs with an array */
893 AInt rfmt;
894 AInt i, defno, argc;
895 Foam uncast, fmt, elt;
896 Bool isDef = (foamTag(def)((def)->hdr.tag) == FOAM_Def);
897 Foam lhs = (isDef ? def->foamDef.lhs : def->foamSet.lhs);
898 Foam rhs = (isDef ? def->foamDef.rhs : def->foamSet.rhs);
899
900
901 /* Safety check (a tad late) */
902 assert((foamTag(def) == FOAM_Set) || (foamTag(def) == FOAM_Def))do { if (!((((def)->hdr.tag) == FOAM_Set) || (((def)->hdr
.tag) == FOAM_Def))) _do_assert(("(foamTag(def) == FOAM_Set) || (foamTag(def) == FOAM_Def)"
),"of_rrfmt.c",902); } while (0)
;
903
904
905 /* Which definition is this? */
906 defno = rrDefNo(def)((def)->foamGen.hdr.info.defNo);
907
908
909 /* Ignore unknown definitions */
910 if (!rrDefIsKnown(defno)bitvTest(rrInfo.class, rrInfo.cached, defno)) return def;
911
912
913 /* Ignore definitions that escape */
914 if (rrDefHasEscaped(defno)bitvTest(rrInfo.class, rrInfo.escapes, defno)) return def;
915
916
917 /* Remove the cast from the rhs */
918 uncast = rhs;
919 while (foamTag(uncast)((uncast)->hdr.tag) == FOAM_Cast)
920 uncast = uncast->foamCast.expr;
921
922
923 /* Do we have anything on the rhs to replace? */
924 if (foamTag(uncast)((uncast)->hdr.tag) != FOAM_RRNew) return def;
925
926
927 /* The lhs MUST be a local */
928 assert(rrIsLocal(lhs))do { if (!(( (((lhs)->hdr.tag) == FOAM_Loc) || (((lhs)->
hdr.tag) == FOAM_Par) ))) _do_assert(("rrIsLocal(lhs)"),"of_rrfmt.c"
,928); } while (0)
;
929
930
931 /* Get the raw format */
932 fmt = uncast->foamRRNew.fmt;
933
934
935 /* Safety check */
936 assert(foamTag(fmt) == FOAM_RRFmt)do { if (!(((fmt)->hdr.tag) == FOAM_RRFmt)) _do_assert(("foamTag(fmt) == FOAM_RRFmt"
),"of_rrfmt.c",936); } while (0)
;
937
938
939 /* Pull out the format value */
940 fmt = fmt->foamRRFmt.fmt;
941
942
943 /* Safety check */
944 assert(foamTag(fmt) == FOAM_Values)do { if (!(((fmt)->hdr.tag) == FOAM_Values)) _do_assert(("foamTag(fmt) == FOAM_Values"
),"of_rrfmt.c",944); } while (0)
;
945
946
947 /* How many fields are there? */
948 argc = foamArgc(fmt)((fmt)->hdr.argc);
949
950
951 /* We are about to modify this prog */
952 rrInfo.changed = true1;
953
954
955 /*
956 * Replace
957 * (Set (Loc r) (RRNew 3 (RRFmt (Values SInt DFlo SFlo)))) with
958 * with
959 * (Set (Loc r) (RNew 9))
960 * (Set (RElt 9 (Loc r) 0) (RNew 6))
961 * (Set (RElt 9 (Loc r) 1) (RNew 7))
962 * (Set (RElt 9 (Loc r) 2) (RNew 8))
963 * and add the declarations:
964 * (DDecl Records (Decl SInt "data" -1 4)) ; fmt 6
965 * (DDecl Records (Decl DFlo "data" -1 4)) ; fmt 7
966 * (DDecl Records (Decl SFlo "data" -1 4)) ; fmt 8
967 * (DDecl Records ; fmt 9
968 * (Decl Word "p1" -1 4)
969 * (Decl Word "p2" -1 4)
970 * (Decl Word "p3" -1 4))
971 *
972 * Actually, to ensure that the reaching definitions are
973 * still valid we keep the original assignment and kill
974 * it by adding the replacement after it. Deadvar ought
975 * to remove the original for us.
976 */
977 *newcodep = listCons(Foam)(Foam_listPointer->Cons)(def, *newcodep);
978
979
980 /* Get the format number for this RRFmt */
981 rfmt = rrTranslateRRFmt(fmt);
982
983
984 /* Create the new record in this format */
985 rhs = foamNewRNew(rfmt)foamNew(FOAM_RNew, 1, rfmt);
986
987
988 /* Create a plain record to replace `def' */
989 def = foamCopy(def);
990 if (isDef)
991 def->foamDef.rhs = rhs;
992 else
993 def->foamSet.rhs = rhs;
994
995
996 /* Add to the code stream */
997 *newcodep = listCons(Foam)(Foam_listPointer->Cons)(def, *newcodep);
998
999
1000 /* Update the fields of the new record */
1001 for (i = 0; i < argc; i++)
1002 {
1003 Foam set;
1004 FoamTag type;
1005
1006
1007 /* Convert the RRFmt element into a type */
1008 type = rrSizeToType(fmt->foamValues.argv[i]);
1009
1010
1011 /*
1012 * Create a new record of this type. We could invent
1013 * a bit of foam to wrap the type in and cache these
1014 * formats just like the main format.
1015 */
1016 rhs = foamNewRNew(rrNewRecordFmt(type, 1))foamNew(FOAM_RNew, 1, rrNewRecordFmt(type, 1));
1017
1018
1019 /* Create a new assignment */
1020 elt = foamNewRElt(rfmt, foamCopy(lhs), i)foamNew(FOAM_RElt,3,(AInt)(rfmt),foamCopy(lhs),(AInt)(i));
1021 set = foamNewSet(elt, rhs)foamNew(FOAM_Set, 2, elt, rhs);
1022
1023
1024 /* Add it to the statement list */
1025 *newcodep = listCons(Foam)(Foam_listPointer->Cons)(set, *newcodep);
1026 }
1027
1028
1029 /* Return nothing */
1030 return foamNewNOp()foamNew(FOAM_NOp, (int) 0);
1031}
1032
1033
1034localstatic Foam
1035rrReplaceDeeply(Foam foam)
1036{
1037 AInt fmt, relt;
1038 Foam rrec, uncast, rfmt;
1039
1040 /* Recursively replace RRElt expressions */
1041 foamIter(foam, expr, {*expr = rrReplaceDeeply(*expr);}){ { String argf = (foamInfoTable [(int)(((foam)->hdr.tag))
-(int)FOAM_START]).argf; Length _i; for (_i = 0; _i < ((foam
)->hdr.argc); _i++, argf++) { if (*argf == '*') argf--; if
(*argf == 'C') { Foam *expr = (Foam *) ((foam)->foamGen.argv
)+_i; { {*expr = rrReplaceDeeply(*expr);}; }; } } }; }
;
1042
1043
1044 /* Ignore non-RRElt expressions */
1045 if (foamTag(foam)((foam)->hdr.tag) != FOAM_RRElt) return foam;
1046
1047
1048 /* Explode the access */
1049 rrec = foam->foamRRElt.data;
1050 rfmt = foam->foamRRElt.fmt;
1051 relt = foam->foamRRElt.field;
1052
1053
1054 /* Remove any casts */
1055 uncast = rrec;
1056 while (foamTag(uncast)((uncast)->hdr.tag) == FOAM_Cast)
1057 uncast = uncast->foamCast.expr;
1058
1059
1060 /* Ignore it if it isn't a local */
1061 if (!rrIsLocal(uncast)( (((uncast)->hdr.tag) == FOAM_Loc) || (((uncast)->hdr.
tag) == FOAM_Par) )
) return foam;
1062
1063
1064 /*
1065 * Ignore if the raw record escapes. Note that this
1066 * call ought not to trace the use-def chains to their
1067 * leaves since all reaching definitions ought to be
1068 * be cached now.
1069 */
1070 if (!rrNonEscapingLocal(uncast)) return foam;
1071
1072
1073 /* Get the literal part of the RRFmt */
1074 assert(foamTag(rfmt) == FOAM_RRFmt)do { if (!(((rfmt)->hdr.tag) == FOAM_RRFmt)) _do_assert(("foamTag(rfmt) == FOAM_RRFmt"
),"of_rrfmt.c",1074); } while (0)
;
1075 rfmt = rfmt->foamRRFmt.fmt;
1076 assert(foamTag(rfmt) == FOAM_Values)do { if (!(((rfmt)->hdr.tag) == FOAM_Values)) _do_assert((
"foamTag(rfmt) == FOAM_Values"),"of_rrfmt.c",1076); } while (
0)
;
1077
1078
1079 /* Get the format number for this RRFmt */
1080 fmt = rrTranslateRRFmt(rfmt);
1081
1082
1083 /* Replace the RRElt with a simple RElt */
1084 rrec = foamNewCast(FOAM_Rec, foamCopy(uncast))foamNew(FOAM_Cast, 2, FOAM_Rec, foamCopy(uncast));
1085 return foamNewRElt(fmt, rrec, relt)foamNew(FOAM_RElt,3,(AInt)(fmt),rrec,(AInt)(relt));
1086}
1087
1088
1089localstatic FoamTag
1090rrSizeToType(Foam size)
1091{
1092 /*
1093 * Convert a RawRepSize or SizeOf* call into a FOAM type.
1094 * We could come seriously unstuck here if we have a set
1095 * of BCalls defining the size but we are unable to work
1096 * out what sort of type to associate with it.
1097 */
1098 assert(foamTag(size) == FOAM_BCall)do { if (!(((size)->hdr.tag) == FOAM_BCall)) _do_assert(("foamTag(size) == FOAM_BCall"
),"of_rrfmt.c",1098); } while (0)
;
1099
1100
1101 /* What is the call? */
1102 switch (size->foamBCall.op)
1103 {
1104 case FOAM_BVal_RawRepSize:
1105 return rrTypeToType(size->foamBCall.argv[0]);
1106
1107#if 0
1108 case FOAM_BVal_SizeOfInt8: return FOAM_Int8;
1109 case FOAM_BVal_SizeOfInt16: return FOAM_Int16;
1110 case FOAM_BVal_SizeOfInt32: return FOAM_Int32;
1111 case FOAM_BVal_SizeOfInt64: return FOAM_Int64;
1112 case FOAM_BVal_SizeOfInt128: return FOAM_Int128;
1113#endif
1114
1115 case FOAM_BVal_SizeOfNil: return FOAM_Nil;
1116 case FOAM_BVal_SizeOfChar: return FOAM_Char;
1117 case FOAM_BVal_SizeOfBool: return FOAM_Bool;
1118 case FOAM_BVal_SizeOfByte: return FOAM_Byte;
1119 case FOAM_BVal_SizeOfHInt: return FOAM_HInt;
1120 case FOAM_BVal_SizeOfSInt: return FOAM_SInt;
1121 case FOAM_BVal_SizeOfBInt: return FOAM_BInt;
1122 case FOAM_BVal_SizeOfSFlo: return FOAM_SFlo;
1123 case FOAM_BVal_SizeOfDFlo: return FOAM_DFlo;
1124 case FOAM_BVal_SizeOfWord: return FOAM_Word;
1125 case FOAM_BVal_SizeOfClos: return FOAM_Clos;
1126 case FOAM_BVal_SizeOfPtr: return FOAM_Ptr;
1127 case FOAM_BVal_SizeOfRec: return FOAM_Rec;
1128 case FOAM_BVal_SizeOfArr: return FOAM_Arr;
1129 case FOAM_BVal_SizeOfTR: return FOAM_TR;
1130 }
1131
1132 bug("rrSizeToType: unknown size");
1133 return FOAM_Word;
1134}
1135
1136
1137localstatic FoamTag
1138rrTypeToType(Foam size)
1139{
1140 /* Convert a Type* call into a FOAM type. */
1141 assert(foamTag(size) == FOAM_BCall)do { if (!(((size)->hdr.tag) == FOAM_BCall)) _do_assert(("foamTag(size) == FOAM_BCall"
),"of_rrfmt.c",1141); } while (0)
;
1142
1143
1144 /* What is the call? */
1145 switch (size->foamBCall.op)
1146 {
1147#if 0
1148 case FOAM_BVal_TypeInt8: return FOAM_Int8;
1149 case FOAM_BVal_TypeInt16: return FOAM_Int16;
1150 case FOAM_BVal_TypeInt32: return FOAM_Int32;
1151 case FOAM_BVal_TypeInt64: return FOAM_Int64;
1152 case FOAM_BVal_TypeInt128: return FOAM_Int128;
1153#endif
1154
1155 case FOAM_BVal_TypeNil: return FOAM_Nil;
1156 case FOAM_BVal_TypeChar: return FOAM_Char;
1157 case FOAM_BVal_TypeBool: return FOAM_Bool;
1158 case FOAM_BVal_TypeByte: return FOAM_Byte;
1159 case FOAM_BVal_TypeHInt: return FOAM_HInt;
1160 case FOAM_BVal_TypeSInt: return FOAM_SInt;
1161 case FOAM_BVal_TypeBInt: return FOAM_BInt;
1162 case FOAM_BVal_TypeSFlo: return FOAM_SFlo;
1163 case FOAM_BVal_TypeDFlo: return FOAM_DFlo;
1164 case FOAM_BVal_TypeWord: return FOAM_Word;
1165 case FOAM_BVal_TypeClos: return FOAM_Clos;
1166 case FOAM_BVal_TypePtr: return FOAM_Ptr;
1167 case FOAM_BVal_TypeRec: return FOAM_Rec;
1168 case FOAM_BVal_TypeArr: return FOAM_Arr;
1169 case FOAM_BVal_TypeTR: return FOAM_TR;
1170 }
1171
1172 bug("rrTypeToType: unknown type");
1173 return FOAM_Word;
1174}
1175
1176
1177localstatic AInt
1178rrNewRecordFmt(FoamTag type, AInt nelts)
1179{
1180 AInt i, fmt;
1181 Foam ddecl;
1182
1183
1184 /* Create new declaration for this record */
1185 ddecl = foamNew(FOAM_DDecl, nelts + 1, FOAM_DDecl_Record);
1186
1187
1188 /* Initialise its fields */
1189 for (i = 0;i < nelts; i++)
1190 {
1191 String name;
1192 Foam decl;
1193
1194
1195 /* Invent a field name */
1196 name = strPrintf("p%d", i);
1197
1198
1199 /* Create a declaration for this field */
1200 decl = foamNewDecl(type, name, emptyFormatSlot)foamNew(FOAM_Decl,4,(AInt)(type),name, (AInt) (0x7FFF), 4);
1201
1202
1203 /* Update the record declaration */
1204 ddecl->foamDDecl.argv[i] = decl;
1205 }
1206
1207
1208 /* Convert the declaration into a format number */
1209 fmt = rrAddFormat(ddecl);
1210
1211
1212 /* Return the format of this record */
1213 return fmt;
1214}
1215
1216
1217localstatic void
1218rrInitFormats(Foam unit)
1219{
1220 /* Store the formats globally in an extendable form */
1221 rrInfo.formats = fboxNew(unit->foamUnit.formats);
1222
1223
1224 /* Create a mapping between RRFmt and foam formats */
1225 rrInfo.remap = tblNew((TblHashFun)foamHash, (TblEqFun)foamEqual);
1226}
1227
1228
1229localstatic AInt
1230rrAddFormat(Foam ddecl)
1231{
1232 return fboxAdd(rrInfo.formats, ddecl);
1233}
1234
1235
1236localstatic void
1237rrMakeNewFormats(Foam unit)
1238{
1239 /* Recreate the format declarations for a Unit */
1240 unit->foamUnit.formats = fboxMake(rrInfo.formats);
1241
1242
1243 /* Free the RRFmt mapping */
1244 tblFreeDeeply(rrInfo.remap, (TblFreeKeyFun)foamFree,
1245 (TblFreeEltFun)NULL((void*)0));
1246}
1247
1248
1249localstatic AInt
1250rrLookupRRFmt(Foam rrfmt)
1251{
1252 /* Safety check */
1253 assert(foamTag(rrfmt) == FOAM_Values)do { if (!(((rrfmt)->hdr.tag) == FOAM_Values)) _do_assert(
("foamTag(rrfmt) == FOAM_Values"),"of_rrfmt.c",1253); } while
(0)
;
1254
1255
1256 /* Hash table lookup */
1257 return (AInt)tblElt(rrInfo.remap, (TblKey)rrfmt, (TblElt)0);
1258}
1259
1260
1261localstatic void
1262rrCacheRRFmt(Foam rrfmt, AInt fmt)
1263{
1264 /* Safety check */
1265 assert(foamTag(rrfmt) == FOAM_Values)do { if (!(((rrfmt)->hdr.tag) == FOAM_Values)) _do_assert(
("foamTag(rrfmt) == FOAM_Values"),"of_rrfmt.c",1265); } while
(0)
;
1266
1267
1268 /* Update the hash table */
1269 tblSetElt(rrInfo.remap, (TblKey)foamCopy(rrfmt), (TblElt)fmt);
1270}
1271
1272
1273localstatic AInt
1274rrTranslateRRFmt(Foam rrfmt)
1275{
1276 AInt fmt = rrLookupRRFmt(rrfmt);
1277
1278
1279 /* Safety check */
1280 assert(foamTag(rrfmt) == FOAM_Values)do { if (!(((rrfmt)->hdr.tag) == FOAM_Values)) _do_assert(
("foamTag(rrfmt) == FOAM_Values"),"of_rrfmt.c",1280); } while
(0)
;
1281
1282
1283 /* Create a new format if necessary */
1284 if (!fmt)
1285 {
1286 /* Create the record and format */
1287 fmt = rrNewRecordFmt(FOAM_Word, foamArgc(rrfmt)((rrfmt)->hdr.argc));
1288
1289
1290 /* Cache the format */
1291 rrCacheRRFmt(rrfmt, fmt);
1292 }
1293
1294
1295 /* Return the format number */
1296 return fmt;
1297}
1298
1299
1300localstatic Bool
1301rrFoamHasRRFmt(Foam foam)
1302{
1303 /* Check this expression */
1304 if (foamTag(foam)((foam)->hdr.tag) == FOAM_RRFmt) return true1;
1305
1306
1307 /* Check each sub-term and return if any RRFmt found */
1308 foamIter(foam, expr, {if (rrFoamHasRRFmt(*expr)) return true;}){ { String argf = (foamInfoTable [(int)(((foam)->hdr.tag))
-(int)FOAM_START]).argf; Length _i; for (_i = 0; _i < ((foam
)->hdr.argc); _i++, argf++) { if (*argf == '*') argf--; if
(*argf == 'C') { Foam *expr = (Foam *) ((foam)->foamGen.argv
)+_i; { {if (rrFoamHasRRFmt(*expr)) return 1;}; }; } } }; }
;
1309 return false((int) 0);
1310}
1311
1312
1313Bool
1314rrRRFmtIsIndependent(Foam rrfmt)
1315{
1316 /*
1317 * Independent RRFmt instructions are those whose value
1318 * does not depend on any other instruction. This means
1319 * that they are entirely composed of literals, or BCalls
1320 * with literal or BCall arguments.
1321 */
1322 AInt i;
1323 Foam fmt;
1324
1325
1326 /* Sanity check */
1327 assert(foamTag(rrfmt) == FOAM_RRFmt)do { if (!(((rrfmt)->hdr.tag) == FOAM_RRFmt)) _do_assert((
"foamTag(rrfmt) == FOAM_RRFmt"),"of_rrfmt.c",1327); } while (
0)
;
1328
1329
1330 /* Get the format of the RRFmt */
1331 fmt = rrfmt->foamRRFmt.fmt;
1332
1333
1334 /* Must be a FOAM_Values to be independent */
1335 if (foamTag(fmt)((fmt)->hdr.tag) != FOAM_Values) return false((int) 0);
1336
1337
1338 /* Check each element of the format */
1339 for (i = 0; i < foamArgc(fmt)((fmt)->hdr.argc); i++)
1340 {
1341 Foam elt = foamArgv(fmt)((fmt)->foamGen.argv)[i].code;
1342
1343
1344 /* Stop checking if not independent */
1345 if (!rrIndepExpr(elt)) return false((int) 0);
1346 }
1347
1348
1349 /* This is an independent RRFmt */
1350 return true1;
1351}
1352
1353
1354localstatic Bool
1355rrIndepExpr(Foam elt)
1356{
1357 AInt i;
1358
1359 /* Does it look like a possible candidate? */
1360 if (foamTag(elt)((elt)->hdr.tag) != FOAM_BCall)
1361 {
1362 /* If not a BCall then it must be a SInt literal */
1363 return (foamTag(elt)((elt)->hdr.tag) == FOAM_SInt);
1364 }
1365
1366
1367 /* Check each of the BCall arguments */
1368 for (i = 1; i < foamArgc(elt)((elt)->hdr.argc); i++)
1369 {
1370 /* Each argument must be independent */
1371 if (!rrIndepExpr(foamArgv(elt)((elt)->foamGen.argv)[i].code))
1372 return false((int) 0);
1373 }
1374
1375
1376 /* Must be okay */
1377 return true1;
1378}
1379