Bug Summary

File:src/of_argsub.c
Warning:line 742, column 2
Value stored to 'parc' 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_argsub.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_argsub.c
1/*****************************************************************************
2 *
3 * of_argsub.c: Perform function-argument substitution.
4 *
5 * Copyright (c) 1990-2007 Aldor Software Organization Ltd (Aldor.org).
6 *
7 ****************************************************************************/
8
9#include "debug.h"
10#include "of_argsub.h"
11#include "store.h"
12#include "util.h"
13#include "sefo.h"
14#include "lib.h"
15#include "symbol.h"
16#include "strops.h"
17
18/*
19 * IMPORTANT: this is code "in progress" so don't link it in yet!
20 */
21
22/*
23 * argsubUnit() is the exported interface to this optimisation and
24 * is only invoked by clients not by us.
25 *
26 * agsDo*() are functions to perform argument substitution on a
27 * function or procedure call. They do not recurse.
28 *
29 * All other ags*() functions are recursive and traverse pieces
30 * of FOAM to identify the parts which can be optimised, apply
31 * the relevent agsDo* optimising function and clean up afterwards.
32 */
33
34
35/* Local helper functions - these recursively traverse FOAM */
36localstatic void agsDDef(Foam);
37localstatic void agsProgram(Foam, Length);
38localstatic void agsCompound(Foam);
39
40localstatic void agsCast(Foam);
41localstatic void agsDef(Foam);
42localstatic void agsIf(Foam);
43localstatic void agsOCall(Foam);
44localstatic void agsReturn(Foam);
45localstatic void agsSeq(Foam);
46localstatic void agsSet(Foam);
47localstatic void agsSelect(Foam);
48
49
50/* These are the crux of the module */
51localstatic void agsTryArgSub(Foam *, String);
52localstatic Foam agsSubsProg(Foam, Foam *, Length, String);
53
54
55/* Local helpers to answer questions about pieces of foam */
56localstatic Bool agsParamIsClean(Foam, AInt);
57localstatic Bool agsFoamHasParam(Foam, AInt);
58
59
60/* More local helpers - these perform argument substitutions. */
61localstatic Foam agsDoOCall(Foam);
62localstatic Foam agsSubsCompound(Foam, Foam *, Length);
63
64
65/* Last set of helpers which perform a variety of simple tasks */
66localstatic void agsAddConstant(Foam, Foam);
67
68
69/* Globals to keep track of Unit/Prog information */
70static struct agsUnitInfoStruct agsUnitInfo;
71static struct agsProgInfoStruct agsProgInfo;
72
73static AgsUnitInfo agsUnit = &agsUnitInfo;
74static AgsProgInfo agsProg = &agsProgInfo;
75
76
77/* Global lists to keep track of new Prog constants */
78static FoamList agsNewConsts = (FoamList)NULL((void*)0);
79static FoamList agsNewDecls = (FoamList)NULL((void*)0);
80static AIntList agsNewFormats = (AIntList)NULL((void*)0);
81static Length agsNumConsts = 0;
82
83
84/* Debugging flags */
85Bool agsDebug = false((int) 0);
86#define agsDEBUGif (!agsDebug) { } else afprintf DEBUG_IF(ags)if (!agsDebug) { } else afprintf
87
88
89/*****************************************************************************
90 *
91 * :: Exported functions
92 *
93 ****************************************************************************/
94
95/*
96 * Perform argument substitutions on the whole unit. For this to work
97 * effectively the unit must have been through the optimiser so that
98 * arguments to functions are likely to be actual FOAM literals such
99 * as (SInt 42). We replace calls of the form:
100 *
101 * (Set (Loc 0 x) (OCall SInt (Const 1) (Env 0) (SInt 42)))
102 *
103 * where
104 *
105 * (Def (Const 1 foo)
106 * (Prog 0 0 SInt 4 8195 0 0 0
107 * (DDecl Params (Decl SInt "n" -1 4))
108 * (DDecl Locals)
109 * (DFluid)
110 * (DEnv 4 4)
111 * (Seq (Return (Par 0 n)))))
112 *
113 * into a call of the form:
114 *
115 * (Set (Loc 0 x) (OCall SInt (Const 23) (Env 0)))
116 *
117 * where (Const 23) is (Const 1) with (Par 0) replaced with (SInt 42):
118 *
119 * (Def (Const 23 foo)
120 * (Prog 0 0 SInt 4 8195 0 0 0
121 * (DDecl Params)
122 * (DDecl Locals)
123 * (DFluid)
124 * (DEnv 4 4)
125 * (Seq (Return (SInt 42)))))
126 *
127 * For such a simple function the next iteration of the optimiser
128 * ought to inline this so that we end up with
129 *
130 * (Set (Loc 0 x) (SInt 42)))
131 *
132 * Care needs to be taken in situations where the prog being optimised
133 * has statements which treat parameters as local variables. We need
134 * to replace any references to parameters used in this way with a
135 * local variable instead.
136 */
137void
138argsubUnit(Foam unit)
139{
140 Length c;
141
142 agsDEBUGif (!agsDebug) { } else afprintf(dbOut, "-> argsubUnit\n");
143
144
145 /* First note which unit we have ... */
146 assert(foamTag(unit) == FOAM_Unit)do { if (!(((unit)->hdr.tag) == FOAM_Unit)) _do_assert(("foamTag(unit) == FOAM_Unit"
),"of_argsub.c",146); } while (0)
;
147 agsUnit->unit = unit;
148
149
150 /* Get information about our unit */
151 agsUnit->fmtc = foamArgc(unit->foamUnit.formats)((unit->foamUnit.formats)->hdr.argc);
152 agsUnit->fmtv = unit->foamUnit.formats->foamDFmt.argv;
153 agsUnit->gloc = foamDDeclArgc(foamUnitGlobals(unit))(((((((unit)->foamUnit.formats)->foamGen.argv)[0].code)
)->hdr.argc) - (1))
;
154 agsUnit->glov = foamUnitGlobals(unit)((((unit)->foamUnit.formats)->foamGen.argv)[0].code)->foamDDecl.argv;
155 agsUnit->constc = c = foamDDeclArgc(foamUnitConstants(unit))(((((((unit)->foamUnit.formats)->foamGen.argv)[1].code)
)->hdr.argc) - (1))
;
156 agsUnit->constv = (Foam *) stoAlloc(OB_Other0, c*sizeof(Foam));
157
158
159 /* Fill in the constant table */
160 foamConstvFrFoam(unit, agsUnit->constc, agsUnit->constv);
161
162
163 /* Initially there are no new constants or formats */
164 agsNewConsts = (FoamList)NULL((void*)0);
165 agsNewDecls = (FoamList)NULL((void*)0);
166 agsNewFormats = (AIntList)NULL((void*)0);
167 agsNumConsts = 0;
168
169
170 /* [debug] Initialise the agsProg structure status */
171 agsProg->status = Uninitialised;
172
173
174 /* Optimise all the Defs in this unit */
175 agsDDef(unit->foamUnit.defs);
176
177
178 /* Do we have to add constants to this unit? */
179 if (agsNumConsts)
180 {
181 agsDEBUGif (!agsDebug) { } else afprintf(dbOut, "(%d new constants)\n",
182 (int)agsNumConsts);
183 }
184
185
186 /* Clear up after ourselves */
187 stoFree(agsUnit->constv);
188 agsDEBUGif (!agsDebug) { } else afprintf(dbOut, "<- argsubUnit\n\n");
189}
190
191/*****************************************************************************
192 *
193 * :: Local helper functions.
194 *
195 ****************************************************************************/
196
197/* Walk a DDef so that we can optimise each Def */
198localstatic void
199agsDDef(Foam defs)
200{
201 Length i;
202
203 assert(foamTag(defs) == FOAM_DDef)do { if (!(((defs)->hdr.tag) == FOAM_DDef)) _do_assert(("foamTag(defs) == FOAM_DDef"
),"of_argsub.c",203); } while (0)
;
204 for (i = 0; i < foamArgc(defs)((defs)->hdr.argc); i++)
205 {
206 Foam def = defs->foamDDef.argv[i];
207 Foam rhs = def->foamDef.rhs;
208 assert(foamTag(def) == FOAM_Def)do { if (!(((def)->hdr.tag) == FOAM_Def)) _do_assert(("foamTag(def) == FOAM_Def"
),"of_argsub.c",208); } while (0)
;
209 if (foamTag(rhs)((rhs)->hdr.tag) == FOAM_Prog)
210 agsProgram(rhs, i);
211 }
212}
213
214
215/*
216 * Now we're getting closer to the point where we can do
217 * some optimisations. We note various information about
218 * this Prog and then recurse into its body. This works
219 * because Progs can't be nested - if they can then we
220 * need to start using fluids.
221 */
222localstatic void
223agsProgram(Foam prog, Length n)
224{
225 /* Check for unexpected recursion */
226 if (DEBUG(ags)agsDebug) {
227 switch (agsProg->status)
228 {
229 case Uninitialised:
230 break;
231 case Initialised:
232 fprintf(dbOut, "*** agsProg already initialised\n");
233 break;
234 default:
235 fprintf(dbOut, "*** agsProg is garbage\n");
236 break;
237 }
238 }
239
240
241 /* First note which prog we have ... */
242 assert(foamTag(prog) == FOAM_Prog)do { if (!(((prog)->hdr.tag) == FOAM_Prog)) _do_assert(("foamTag(prog) == FOAM_Prog"
),"of_argsub.c",242); } while (0)
;
243 agsProg->prog = prog;
244 agsProg->cnum = n;
245
246
247 /* Note the environment */
248 agsProg->levels = prog->foamProg.levels;
249
250
251 /* Note the locals and parameters */
252 agsProg->lexc = 0;
253 agsProg->lexv = (AInt *)NULL((void*)0);
254 agsProg->locc = foamDDeclArgc(prog->foamProg.locals)(((prog->foamProg.locals)->hdr.argc) - (1));
255 agsProg->locv = prog->foamProg.locals->foamDDecl.argv;
256 agsProg->parc = foamDDeclArgc(prog->foamProg.params)(((prog->foamProg.params)->hdr.argc) - (1));
257 agsProg->parv = prog->foamProg.params->foamDDecl.argv;
258
259 /* Lexicals only exist if we have formats */
260 if (agsUnit->fmtc)
261 {
262 AInt fmt = agsProg->levels->foamDEnv.argv[0];
263 agsProg->lexc = foamDDeclArgc(agsUnit->fmtv[fmt])(((agsUnit->fmtv[fmt])->hdr.argc) - (1));
264 agsProg->lexv = agsProg->levels->foamDEnv.argv;
265 }
266
267
268 /* Our structure is now initialised */
269 if (DEBUG(ags)agsDebug) {
270 agsProg->status = Initialised;
271 }
272
273
274 /* Now walk over the Prog body */
275 agsCompound(prog->foamProg.body);
276
277
278 /* Mark our structure as uninitialised */
279 if (DEBUG(ags)agsDebug) {
280 agsProg->status = Uninitialised;
281 }
282}
283
284
285/*
286 * This is a generic routine to walk across a piece of FOAM
287 * that we might expect to find inside a Prog and optimise
288 * function applications by argument substitution. At the
289 * moment we only deal with OCalls but the others can be
290 * added later.
291 */
292localstatic void
293agsCompound(Foam foam)
294{
295 /*
296 * We don't need to check every possible foam tag
297 * but it's probably worth it during development.
298 */
299 switch (foamTag(foam)((foam)->hdr.tag))
300 {
301 /* FOAM_CONTROL nodes that we examine */
302 case FOAM_Return: agsReturn(foam); break;
303 case FOAM_Cast: agsCast(foam); break;
304 case FOAM_Set: agsSet(foam); break;
305 case FOAM_Def: agsDef(foam); break;
306 case FOAM_If: agsIf(foam); break;
307
308
309 /* FOAM_NARY nodes that we examine */
310 case FOAM_Select: agsSelect(foam); break;
311 case FOAM_OCall: agsOCall(foam); break;
312 case FOAM_Seq: agsSeq(foam); break;
313
314
315 /* FOAM_CONTROL nodes that we ignore */
316 case FOAM_NOp: /* Fall through */
317 case FOAM_BVal: /* Fall through */
318 case FOAM_Ptr: /* Fall through */
319 case FOAM_CProg: /* Fall through */
320 case FOAM_CEnv: /* Fall through */
321 case FOAM_Loose: /* Fall through */
322 case FOAM_EEnsure: /* Fall through */
323 case FOAM_EInfo: /* Fall through */
324 case FOAM_Kill: /* Fall through */
325 case FOAM_Free: /* Fall through */
326 case FOAM_ANew: /* Fall through */
327 case FOAM_RRNew: /* Fall through */
328 case FOAM_RRec: /* Fall through */
329 case FOAM_Clos: /* Fall through */
330 case FOAM_AElt: /* Fall through */
331 case FOAM_Goto: /* Fall through */
332 case FOAM_Throw: /* Fall through */
333 case FOAM_Catch: /* Fall through */
334 case FOAM_Protect: /* Fall through */
335 case FOAM_Unit: /* Fall through */
336 case FOAM_PushEnv: /* Fall through */
337 case FOAM_PopEnv: /* Fall through */
338 case FOAM_MFmt: /* Fall through */
339 case FOAM_RRFmt: /* Fall through */
340
341
342 /* FOAM_VECTOR nodes that we ignore */
343 case FOAM_Unimp: /* Fall through */
344 case FOAM_GDecl: /* Fall through */
345 case FOAM_Decl: /* Fall through */
346 case FOAM_BInt: /* Fall through */
347
348
349 /* FOAM_INDEX nodes that we ignore */
350 case FOAM_Par: /* Fall through */
351 case FOAM_Loc: /* Fall through */
352 case FOAM_Glo: /* Fall through */
353 case FOAM_Fluid: /* Fall through */
354 case FOAM_Const: /* Fall through */
355 case FOAM_Env: /* Fall through */
356 case FOAM_EEnv: /* Fall through */
357 case FOAM_RNew: /* Fall through */
358 case FOAM_PRef: /* Fall through */
359 case FOAM_TRNew: /* Fall through */
360 case FOAM_RRElt: /* Fall through */
361 case FOAM_Label: /* Fall through */
362
363
364 /* FOAM_MULTINT nodes that we ignore */
365 case FOAM_Lex: /* Fall through */
366 case FOAM_RElt: /* Fall through */
367 case FOAM_IRElt: /* Fall through */
368 case FOAM_TRElt: /* Fall through */
369 case FOAM_EElt: /* Fall through */
370 case FOAM_CFCall: /* Fall through */
371 case FOAM_OFCall: /* Fall through */
372
373
374 /* FOAM_NARY nodes that we ignore */
375 case FOAM_DDecl: /* Fall through */
376 case FOAM_DFluid: /* Fall through */
377 case FOAM_DEnv: /* Fall through */
378 case FOAM_DDef: /* Fall through */
379 case FOAM_DFmt: /* Fall through */
380 case FOAM_Rec: /* Fall through */
381 case FOAM_Arr: /* Fall through */
382 case FOAM_TR: /* Fall through */
383 case FOAM_PCall: /* Fall through */
384 case FOAM_BCall: /* Fall through */
385 case FOAM_CCall: /* Fall through */
386 case FOAM_Values: /* Fall through */
387 case FOAM_Prog: /* Fall through */
388
389
390 /* Just ignore this case */
391 break;
392 default :
393 /* Missing anything other than FOAM_DATA is a bug */
394 if (foamTag(foam)((foam)->hdr.tag) >= FOAM_DATA_LIMIT)
395 bug("agsCompound: unrecognised foam");
396 break;
397 }
398}
399
400/*****************************************************************************
401 *
402 * :: Recursive FOAM traversal functions in alphabetical order
403 *
404 ****************************************************************************/
405
406localstatic void
407agsCast(Foam foam)
408{
409}
410
411
412localstatic void
413agsDef(Foam foam)
414{
415}
416
417
418localstatic void
419agsIf(Foam foam)
420{
421}
422
423
424localstatic void
425agsOCall(Foam foam)
426{
427}
428
429
430localstatic void
431agsReturn(Foam foam)
432{
433}
434
435
436localstatic void
437agsSeq(Foam foam)
438{
439 Length i;
440 Length n = foamArgc(foam)((foam)->hdr.argc);
441
442 for (i = 0;i < n; i++)
443 agsTryArgSub(&(foamArgv(foam)((foam)->foamGen.argv)[i].code), "agsSeq");
444}
445
446
447localstatic void
448agsSet(Foam foam)
449{
450 /* Sanity check (a little late perhaps!) */
451 assert(foamTag(foam) == FOAM_Set)do { if (!(((foam)->hdr.tag) == FOAM_Set)) _do_assert(("foamTag(foam) == FOAM_Set"
),"of_argsub.c",451); } while (0)
;
452
453
454 /* Only optimise the RHS for the time being */
455 agsTryArgSub(&(foam->foamSet.rhs), "agsSet");
456}
457
458
459localstatic void
460agsSelect(Foam foam)
461{
462}
463
464
465/*****************************************************************************
466 *
467 * :: The following calls actually perform the argument substitutions
468 *
469 ****************************************************************************/
470
471/*
472 * Given a pointer to a piece of FOAM, see if we can replace
473 * it with a similar piece that has been optimised.
474 */
475localstatic void
476agsTryArgSub(Foam *ptr, String fun)
477{
478 Foam elt = *ptr;
479 Foam new = elt;
480
481 /*
482 * Recurse into the node. This may modify deeper
483 * nodes or leaves but we don't mind.
484 */
485 agsCompound(elt);
486
487
488 /*
489 * Check to see if we have something that
490 * can have its arguments substituted.
491 */
492 switch (foamTag(elt)((elt)->hdr.tag))
493 {
494 case FOAM_OCall:
495 new = agsDoOCall(elt);
496 break;
497 default:
498 break;
499 }
500
501
502 /* Did a substitution take place? */
503 if (new != elt)
504 {
505 /* Yes - modify the FOAM */
506 /* Show what happened */
507 if (DEBUG(ags)agsDebug) {
508 (void)fprintf(dbOut, "** %s substitution\n", fun);
509 (void)fprintf(dbOut, ">>\n");
510 foamPrintDb(elt);
511 (void)fprintf(dbOut, "<<\n");
512 foamPrintDb(new);
513 (void)fprintf(dbOut, "\n");
514 }
515
516 foamFreeNode(elt);
517 *ptr = new;
518 }
519}
520
521
522/*
523 * Given an OCall, perform any argument substitutions that are
524 * possible and allowed. We return a new OCall to replace the
525 * original one. Note that we don't recurse into the OCall as
526 * this has already been done at a higher level.
527 */
528localstatic Foam
529agsDoOCall(Foam foam)
530{
531 Foam op, body, new;
532 Length i, argc, rargc, nargc;
533 Syme opSyme;
534 UShort cnum;
535 Bool isLocal;
536 Foam *sigma;
537
538
539 /* Safety check */
540 assert(foamTag(foam) == FOAM_OCall)do { if (!(((foam)->hdr.tag) == FOAM_OCall)) _do_assert(("foamTag(foam) == FOAM_OCall"
),"of_argsub.c",540); } while (0)
;
541
542
543 /* What do we have here? */
544 argc = foamArgc(foam)((foam)->hdr.argc);
545 op = foam->foamOCall.op;
546
547
548 /* Get the symbol meaning associated with op */
549 opSyme = foamSyme(op)((op)->hdr.syme);
550 if (!opSyme)
551 return foam;
552
553
554 /* We can only handle constants */
555 if (!genHasConstNum(opSyme))
556 return foam;
557
558
559 /* Get the constant number for this operator */
560 cnum = genGetConstNum(opSyme);
561
562
563 /* Is this a local or a library operator? */
564 isLocal = symeIsLocalConst(opSyme)(symeConstLib(opSyme) == ((void*)0));
565 if (isLocal)
566 {
567 assert(cnum < agsUnit->constc)do { if (!(cnum < agsUnit->constc)) _do_assert(("cnum < agsUnit->constc"
),"of_argsub.c",567); } while (0)
;
568 body = agsUnit->constv[cnum];
569 }
570 else
571 {
572 Lib origin = symeConstLib(opSyme);
573 body = libGetFoamConstant(origin, cnum);
574 }
575
576
577 /* More sanity checks */
578 assert(body)do { if (!(body)) _do_assert(("body"),"of_argsub.c",578); } while
(0)
;
579 assert(foamTag(body) == FOAM_Prog)do { if (!(((body)->hdr.tag) == FOAM_Prog)) _do_assert(("foamTag(body) == FOAM_Prog"
),"of_argsub.c",579); } while (0)
;
580
581
582 /* Display what we've got here */
583 if (DEBUG(ags)agsDebug) {
584 (void)fprintf(dbOut,"** agsDoOCall: ");
585 (void)symePrintDb(opSyme);
586
587 for (i = 3;i < argc;i++)
588 {
589 Foam arg = foamArgv(foam)((foam)->foamGen.argv)[i].code;
590 Syme syme = foamSyme(arg)((arg)->hdr.syme);
591
592 (void)fprintf(dbOut," Arg: ");
593 if (syme)
594 (void)symePrintDb(syme);
595 else
596 (void)foamPrintDb(arg);
597 }
598 (void)fprintf(dbOut,"\n");
599 }
600
601
602 /* How many arguments are we giving this function? */
603 rargc = argc - 3;
604 assert(rargc == agsProg->parc)do { if (!(rargc == agsProg->parc)) _do_assert(("rargc == agsProg->parc"
),"of_argsub.c",604); } while (0)
;
605
606
607 /*
608 * Decide which arguments need changing. We do this
609 * by creating an array of substitutions, with one
610 * slot for each parameter in order. Parameters which
611 * are not substituted are initialised to their actual
612 * foam par number.
613 */
614 sigma = (Foam *)stoAlloc(OB_Other0, rargc*sizeof(Foam));
615 nargc = 0;
616 for (i = 3; i < argc; i++)
617 {
618 Foam nocast;
619 Foam arg = foamArgv(foam)((foam)->foamGen.argv)[i].code;
620
621 /* Strip off any cast */
622 if (foamTag(arg)((arg)->hdr.tag) == FOAM_Cast)
623 nocast = arg->foamCast.expr;
624 else
625 nocast = arg;
626
627
628 /* Can we do any substitutions? */
629 if (foamTag(nocast)((nocast)->hdr.tag) == FOAM_SInt)
630 {
631 /* Only if this param is clean */
632 if (agsParamIsClean(body, i-3))
633 {
634 sigma[i-3] = arg;
635 continue;
636 }
637 }
638
639
640 /* Remap the parameter */
641 sigma[i-3] = foamNewPar(nargc)foamNew(FOAM_Par, 1, (AInt)(nargc));
642 nargc++;
643 }
644
645 if (DEBUG(ags)agsDebug) {
646 for (i = 0; i < rargc; i++)
647 {
648 (void)fprintf(dbOut, " [%d] = ", (int)i);
649 foamPrintDb(sigma[i]);
650 }
651 }
652
653
654 /*
655 * Do the substitution - this gives us a new function
656 * to call which we need to add to the unit and then
657 * call correctly using the new signature.
658 */
659 new = agsSubsProg(body, sigma, rargc, symString(symeId(opSyme))((((opSyme)->id))->str));
660
661
662 /* Clean up after ourselves */
663 stoFree(sigma);
664 return foam;
665}
666
667
668/*
669 * Return `true' if the specified parameter never appears on the LHS
670 * of a set/assignment otherwise return `false'. Clean parameters
671 * are those which aren't used as local variables.
672 */
673localstatic Bool
674agsParamIsClean(Foam body, AInt param)
675{
676 assert(body)do { if (!(body)) _do_assert(("body"),"of_argsub.c",676); } while
(0)
;
677
678
679 /* Base case - we are looking for a foamSet node */
680 if (foamTag(body)((body)->hdr.tag) == FOAM_Set)
681 {
682 /*
683 * Does this foamPar appear on the LHS of the
684 * foamSet. If it does then it is probably being
685 * used as a local variable which is naughty.
686 */
687 if (agsFoamHasParam(body->foamSet.lhs, param))
688 return false((int) 0);
689 }
690
691
692 /* Check each sub-node */
693 foamIter(body, arg,{ { String argf = (foamInfoTable [(int)(((body)->hdr.tag))
-(int)FOAM_START]).argf; Length _i; for (_i = 0; _i < ((body
)->hdr.argc); _i++, argf++) { if (*argf == '*') argf--; if
(*argf == 'C') { Foam *arg = (Foam *) ((body)->foamGen.argv
)+_i; { { if (!agsParamIsClean(*arg, param)) return ((int) 0)
; }; }; } } }; }
694 {{ { String argf = (foamInfoTable [(int)(((body)->hdr.tag))
-(int)FOAM_START]).argf; Length _i; for (_i = 0; _i < ((body
)->hdr.argc); _i++, argf++) { if (*argf == '*') argf--; if
(*argf == 'C') { Foam *arg = (Foam *) ((body)->foamGen.argv
)+_i; { { if (!agsParamIsClean(*arg, param)) return ((int) 0)
; }; }; } } }; }
695 if (!agsParamIsClean(*arg, param)){ { String argf = (foamInfoTable [(int)(((body)->hdr.tag))
-(int)FOAM_START]).argf; Length _i; for (_i = 0; _i < ((body
)->hdr.argc); _i++, argf++) { if (*argf == '*') argf--; if
(*argf == 'C') { Foam *arg = (Foam *) ((body)->foamGen.argv
)+_i; { { if (!agsParamIsClean(*arg, param)) return ((int) 0)
; }; }; } } }; }
696 return false;{ { String argf = (foamInfoTable [(int)(((body)->hdr.tag))
-(int)FOAM_START]).argf; Length _i; for (_i = 0; _i < ((body
)->hdr.argc); _i++, argf++) { if (*argf == '*') argf--; if
(*argf == 'C') { Foam *arg = (Foam *) ((body)->foamGen.argv
)+_i; { { if (!agsParamIsClean(*arg, param)) return ((int) 0)
; }; }; } } }; }
697 }){ { String argf = (foamInfoTable [(int)(((body)->hdr.tag))
-(int)FOAM_START]).argf; Length _i; for (_i = 0; _i < ((body
)->hdr.argc); _i++, argf++) { if (*argf == '*') argf--; if
(*argf == 'C') { Foam *arg = (Foam *) ((body)->foamGen.argv
)+_i; { { if (!agsParamIsClean(*arg, param)) return ((int) 0)
; }; }; } } }; }
;
698
699 return true1;
700}
701
702
703/*
704 * Returns `true' if the foam contains a reference to the
705 * parameter `param'. This is probably too restrictive since
706 * it may be possible for a (Par n) to appear on the LHS of
707 * a foamSet and not be modified. However, the optimiser is
708 * probably going to flatten the LHS anyway and if the node
709 * is read-only then we will get to optimise it next time.
710 */
711localstatic Bool
712agsFoamHasParam(Foam foam, AInt param)
713{
714 assert(foam)do { if (!(foam)) _do_assert(("foam"),"of_argsub.c",714); } while
(0)
;
715
716
717 /* Base case - we want a foamPar */
718 if (foamTag(foam)((foam)->hdr.tag) == FOAM_Par)
719 return (foam->foamPar.index == param);
720
721
722 /* Check each sub-node */
723 foamIter(foam, 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; { { if (agsFoamHasParam(*arg, param)) return 1; }; }; }
} }; }
724 {{ { 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; { { if (agsFoamHasParam(*arg, param)) return 1; }; }; }
} }; }
725 if (agsFoamHasParam(*arg, param)){ { 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; { { if (agsFoamHasParam(*arg, param)) return 1; }; }; }
} }; }
726 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 *arg = (Foam *) ((foam)->foamGen.argv
)+_i; { { if (agsFoamHasParam(*arg, param)) return 1; }; }; }
} }; }
727 }){ { 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; { { if (agsFoamHasParam(*arg, param)) return 1; }; }; }
} }; }
;
728
729 return false((int) 0);
730}
731
732
733localstatic Foam
734agsSubsProg(Foam foam, Foam *sigma, Length argc, String name)
735{
736 Foam prog, decl;
737 Foam *parv;
738 Length parc;
739
740
741 /* Pull out the list of function parameters */
742 parc = foamDDeclArgc(foam->foamProg.params)(((foam->foamProg.params)->hdr.argc) - (1));
Value stored to 'parc' is never read
743 parv = foam->foamProg.params->foamDDecl.argv;
744
745 /* Create a new prog */
746 prog = foamNewProgfoamNew(FOAM_Prog, 13, (AInt)(foam->foamGen.argv[0].data),
(AInt)(foam->foamGen.argv[1].data),(AInt)(foam->foamGen
.argv[2].data),(AInt)(foam->foamGen.argv[3].data), (AInt)(
foam->foamGen.argv[4].data), (AInt)0, (AInt)0, (AInt)0 , (
(void*)0), foamCopy(foam->foamProg.locals), foamCopy(foam->
foamProg.fluids), foamCopy(foam->foamProg.levels), ((void*
)0))
747 (foamNew(FOAM_Prog, 13, (AInt)(foam->foamGen.argv[0].data),
(AInt)(foam->foamGen.argv[1].data),(AInt)(foam->foamGen
.argv[2].data),(AInt)(foam->foamGen.argv[3].data), (AInt)(
foam->foamGen.argv[4].data), (AInt)0, (AInt)0, (AInt)0 , (
(void*)0), foamCopy(foam->foamProg.locals), foamCopy(foam->
foamProg.fluids), foamCopy(foam->foamProg.levels), ((void*
)0))
748 /* Leading fields accessed anonymously */foamNew(FOAM_Prog, 13, (AInt)(foam->foamGen.argv[0].data),
(AInt)(foam->foamGen.argv[1].data),(AInt)(foam->foamGen
.argv[2].data),(AInt)(foam->foamGen.argv[3].data), (AInt)(
foam->foamGen.argv[4].data), (AInt)0, (AInt)0, (AInt)0 , (
(void*)0), foamCopy(foam->foamProg.locals), foamCopy(foam->
foamProg.fluids), foamCopy(foam->foamProg.levels), ((void*
)0))
749 foam->foamGen.argv[0].data, /* endOffset */foamNew(FOAM_Prog, 13, (AInt)(foam->foamGen.argv[0].data),
(AInt)(foam->foamGen.argv[1].data),(AInt)(foam->foamGen
.argv[2].data),(AInt)(foam->foamGen.argv[3].data), (AInt)(
foam->foamGen.argv[4].data), (AInt)0, (AInt)0, (AInt)0 , (
(void*)0), foamCopy(foam->foamProg.locals), foamCopy(foam->
foamProg.fluids), foamCopy(foam->foamProg.levels), ((void*
)0))
750 foam->foamGen.argv[1].data, /* nLabels */foamNew(FOAM_Prog, 13, (AInt)(foam->foamGen.argv[0].data),
(AInt)(foam->foamGen.argv[1].data),(AInt)(foam->foamGen
.argv[2].data),(AInt)(foam->foamGen.argv[3].data), (AInt)(
foam->foamGen.argv[4].data), (AInt)0, (AInt)0, (AInt)0 , (
(void*)0), foamCopy(foam->foamProg.locals), foamCopy(foam->
foamProg.fluids), foamCopy(foam->foamProg.levels), ((void*
)0))
751 foam->foamGen.argv[2].data, /* retType */foamNew(FOAM_Prog, 13, (AInt)(foam->foamGen.argv[0].data),
(AInt)(foam->foamGen.argv[1].data),(AInt)(foam->foamGen
.argv[2].data),(AInt)(foam->foamGen.argv[3].data), (AInt)(
foam->foamGen.argv[4].data), (AInt)0, (AInt)0, (AInt)0 , (
(void*)0), foamCopy(foam->foamProg.locals), foamCopy(foam->
foamProg.fluids), foamCopy(foam->foamProg.levels), ((void*
)0))
752 foam->foamGen.argv[3].data, /* format */foamNew(FOAM_Prog, 13, (AInt)(foam->foamGen.argv[0].data),
(AInt)(foam->foamGen.argv[1].data),(AInt)(foam->foamGen
.argv[2].data),(AInt)(foam->foamGen.argv[3].data), (AInt)(
foam->foamGen.argv[4].data), (AInt)0, (AInt)0, (AInt)0 , (
(void*)0), foamCopy(foam->foamProg.locals), foamCopy(foam->
foamProg.fluids), foamCopy(foam->foamProg.levels), ((void*
)0))
753 foam->foamGen.argv[4].data, /* infoBits */foamNew(FOAM_Prog, 13, (AInt)(foam->foamGen.argv[0].data),
(AInt)(foam->foamGen.argv[1].data),(AInt)(foam->foamGen
.argv[2].data),(AInt)(foam->foamGen.argv[3].data), (AInt)(
foam->foamGen.argv[4].data), (AInt)0, (AInt)0, (AInt)0 , (
(void*)0), foamCopy(foam->foamProg.locals), foamCopy(foam->
foamProg.fluids), foamCopy(foam->foamProg.levels), ((void*
)0))
754 NULL, /* (Foam)params */foamNew(FOAM_Prog, 13, (AInt)(foam->foamGen.argv[0].data),
(AInt)(foam->foamGen.argv[1].data),(AInt)(foam->foamGen
.argv[2].data),(AInt)(foam->foamGen.argv[3].data), (AInt)(
foam->foamGen.argv[4].data), (AInt)0, (AInt)0, (AInt)0 , (
(void*)0), foamCopy(foam->foamProg.locals), foamCopy(foam->
foamProg.fluids), foamCopy(foam->foamProg.levels), ((void*
)0))
755 foamCopy(foam->foamProg.locals),foamNew(FOAM_Prog, 13, (AInt)(foam->foamGen.argv[0].data),
(AInt)(foam->foamGen.argv[1].data),(AInt)(foam->foamGen
.argv[2].data),(AInt)(foam->foamGen.argv[3].data), (AInt)(
foam->foamGen.argv[4].data), (AInt)0, (AInt)0, (AInt)0 , (
(void*)0), foamCopy(foam->foamProg.locals), foamCopy(foam->
foamProg.fluids), foamCopy(foam->foamProg.levels), ((void*
)0))
756 foamCopy(foam->foamProg.fluids),foamNew(FOAM_Prog, 13, (AInt)(foam->foamGen.argv[0].data),
(AInt)(foam->foamGen.argv[1].data),(AInt)(foam->foamGen
.argv[2].data),(AInt)(foam->foamGen.argv[3].data), (AInt)(
foam->foamGen.argv[4].data), (AInt)0, (AInt)0, (AInt)0 , (
(void*)0), foamCopy(foam->foamProg.locals), foamCopy(foam->
foamProg.fluids), foamCopy(foam->foamProg.levels), ((void*
)0))
757 foamCopy(foam->foamProg.levels),foamNew(FOAM_Prog, 13, (AInt)(foam->foamGen.argv[0].data),
(AInt)(foam->foamGen.argv[1].data),(AInt)(foam->foamGen
.argv[2].data),(AInt)(foam->foamGen.argv[3].data), (AInt)(
foam->foamGen.argv[4].data), (AInt)0, (AInt)0, (AInt)0 , (
(void*)0), foamCopy(foam->foamProg.locals), foamCopy(foam->
foamProg.fluids), foamCopy(foam->foamProg.levels), ((void*
)0))
758 NULL /* body */foamNew(FOAM_Prog, 13, (AInt)(foam->foamGen.argv[0].data),
(AInt)(foam->foamGen.argv[1].data),(AInt)(foam->foamGen
.argv[2].data),(AInt)(foam->foamGen.argv[3].data), (AInt)(
foam->foamGen.argv[4].data), (AInt)0, (AInt)0, (AInt)0 , (
(void*)0), foamCopy(foam->foamProg.locals), foamCopy(foam->
foamProg.fluids), foamCopy(foam->foamProg.levels), ((void*
)0))
759 )foamNew(FOAM_Prog, 13, (AInt)(foam->foamGen.argv[0].data),
(AInt)(foam->foamGen.argv[1].data),(AInt)(foam->foamGen
.argv[2].data),(AInt)(foam->foamGen.argv[3].data), (AInt)(
foam->foamGen.argv[4].data), (AInt)0, (AInt)0, (AInt)0 , (
(void*)0), foamCopy(foam->foamProg.locals), foamCopy(foam->
foamProg.fluids), foamCopy(foam->foamProg.levels), ((void*
)0))
;
760
761 /* Create a declaration for this prog */
762 decl = foamNewDecl(FOAM_Prog, strCopy(name), emptyFormatSlot)foamNew(FOAM_Decl,4,(AInt)(FOAM_Prog),strCopy(name), (AInt) (
0x7FFF), 4)
;
763
764
765 /* Add this prog to the list of new constants */
766 agsAddConstant(prog, decl);
767
768
769 /* Perform the substitutions on the function body. */
770 prog->foamProg.body = agsSubsCompound(foam->foamProg.body, sigma, argc);
771
772
773 /* Patch up the parameter list */
774 /* prog->params = ... */
775 prog->foamProg.params = foam->foamProg.params; /* WRONG!!!! */
776
777
778 /* Perhaps we ought to sort out the size and execution times? */
779
780
781 /* Return the new const */
782 return prog;
783}
784
785
786/*
787 * Copy a piece of foam substituting each (Par i) with sigma[i]
788 */
789localstatic Foam
790agsSubsCompound(Foam foam, Foam *sigma, Length argc)
791{
792 Foam new;
793
794 assert(foam)do { if (!(foam)) _do_assert(("foam"),"of_argsub.c",794); } while
(0)
;
795
796
797 /* Create a new node sharing original storage */
798 new = foamCopyNode(foam);
799
800
801 /* Base case - deal with foamPar nodes */
802 if (foamTag(foam)((foam)->hdr.tag) == FOAM_Par)
803 {
804 assert(foam->foamPar.index < argc)do { if (!(foam->foamPar.index < argc)) _do_assert(("foam->foamPar.index < argc"
),"of_argsub.c",804); } while (0)
;
805 return foamCopy(sigma[foam->foamPar.index]);
806 }
807
808
809 /* Recurse into nodes overwriting shared storage */
810 foamIter(foam, 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; { { *arg = agsSubsCompound(*arg, sigma, argc); }; }; } }
}; }
811 {{ { 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; { { *arg = agsSubsCompound(*arg, sigma, argc); }; }; } }
}; }
812 *arg = agsSubsCompound(*arg, sigma, argc);{ { 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; { { *arg = agsSubsCompound(*arg, sigma, argc); }; }; } }
}; }
813 }){ { 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; { { *arg = agsSubsCompound(*arg, sigma, argc); }; }; } }
}; }
;
814
815
816 /* Return the modified foam */
817 return new;
818}
819
820
821localstatic void
822agsAddConstant(Foam foam, Foam decl)
823{
824 agsNewConsts = listCons(Foam)(Foam_listPointer->Cons)(foam, agsNewConsts);
825 agsNewDecls = listCons(Foam)(Foam_listPointer->Cons)(decl, agsNewConsts);
826 agsNumConsts++;
827}
828
829