Line data Source code
1 : /* do not edit automatically generated by mc from M2Quads. */
2 : /* M2Quads.mod generates quadruples.
3 :
4 : Copyright (C) 2001-2026 Free Software Foundation, Inc.
5 : Contributed by Gaius Mulley <gaius.mulley@southwales.ac.uk>.
6 :
7 : This file is part of GNU Modula-2.
8 :
9 : GNU Modula-2 is free software; you can redistribute it and/or modify
10 : it under the terms of the GNU General Public License as published by
11 : the Free Software Foundation; either version 3, or (at your option)
12 : any later version.
13 :
14 : GNU Modula-2 is distributed in the hope that it will be useful, but
15 : WITHOUT ANY WARRANTY; without even the implied warranty of
16 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 : General Public License for more details.
18 :
19 : You should have received a copy of the GNU General Public License
20 : along with GNU Modula-2; see the file COPYING3. If not see
21 : <http://www.gnu.org/licenses/>. */
22 :
23 : #include "config.h"
24 : #include "system.h"
25 : #include "gcc-consolidation.h"
26 :
27 : #include <stdbool.h>
28 : # if !defined (PROC_D)
29 : # define PROC_D
30 : typedef void (*PROC_t) (void);
31 : typedef struct { PROC_t proc; } PROC;
32 : # endif
33 :
34 : # if !defined (TRUE)
35 : # define TRUE (1==1)
36 : # endif
37 :
38 : # if !defined (FALSE)
39 : # define FALSE (1==0)
40 : # endif
41 :
42 : # include "GStorage.h"
43 : # include "Gmcrts.h"
44 : #if defined(__cplusplus)
45 : # undef NULL
46 : # define NULL 0
47 : #endif
48 : #define _M2Quads_C
49 :
50 : #include "GM2Quads.h"
51 : # include "GStorage.h"
52 : # include "GM2Debug.h"
53 : # include "GNameKey.h"
54 : # include "GFormatStrings.h"
55 : # include "GM2DebugStack.h"
56 : # include "GStrLib.h"
57 : # include "GM2Scaffold.h"
58 : # include "GM2MetaError.h"
59 : # include "GDynamicStrings.h"
60 : # include "GSymbolTable.h"
61 : # include "GM2Batch.h"
62 : # include "GM2GCCDeclare.h"
63 : # include "GFifoQueue.h"
64 : # include "GM2Comp.h"
65 : # include "GM2LexBuf.h"
66 : # include "GM2Error.h"
67 : # include "GM2Printf.h"
68 : # include "GM2Reserved.h"
69 : # include "GM2Base.h"
70 : # include "GM2System.h"
71 : # include "GM2Size.h"
72 : # include "GM2Bitset.h"
73 : # include "GM2ALU.h"
74 : # include "GLists.h"
75 : # include "GM2Options.h"
76 : # include "GM2LangDump.h"
77 : # include "GM2Pass.h"
78 : # include "GM2StackAddress.h"
79 : # include "GM2StackWord.h"
80 : # include "GIndexing.h"
81 : # include "GM2Range.h"
82 : # include "GM2CaseList.h"
83 : # include "GPCSymBuild.h"
84 : # include "Gm2builtins.h"
85 : # include "GSymbolConversion.h"
86 : # include "GM2Diagnostic.h"
87 : # include "GFIO.h"
88 : # include "GSFIO.h"
89 : # include "GStdIO.h"
90 : # include "GM2StackSpell.h"
91 :
92 : # define DebugStackOn true
93 : # define DebugVarients false
94 : # define DebugTokPos false
95 : typedef struct M2Quads__T1_r M2Quads__T1;
96 :
97 : typedef M2Quads__T1 *M2Quads_ConstructorFrame;
98 :
99 : typedef struct M2Quads__T2_r M2Quads__T2;
100 :
101 : typedef M2Quads__T2 *M2Quads_BoolFrame;
102 :
103 : typedef struct M2Quads__T3_r M2Quads__T3;
104 :
105 : typedef M2Quads__T3 *M2Quads_QuadFrame;
106 :
107 : typedef struct M2Quads__T4_r M2Quads__T4;
108 :
109 : typedef M2Quads__T4 *M2Quads_WithFrame;
110 :
111 : typedef struct M2Quads__T5_r M2Quads__T5;
112 :
113 : typedef M2Quads__T5 *M2Quads_ForLoopInfo;
114 :
115 : typedef struct M2Quads__T6_r M2Quads__T6;
116 :
117 : typedef M2Quads__T6 *M2Quads_LineNote;
118 :
119 : # define DebugAsmTokPos false
120 : struct M2Quads__T1_r {
121 : unsigned int type;
122 : unsigned int index;
123 : };
124 :
125 : struct M2Quads__T2_r {
126 : unsigned int TrueExit;
127 : unsigned int FalseExit;
128 : unsigned int Unbounded;
129 : bool BooleanOp;
130 : unsigned int Dimension;
131 : unsigned int ReadWrite;
132 : unsigned int name;
133 : unsigned int RangeDep;
134 : DynamicStrings_String Annotation;
135 : unsigned int tokenno;
136 : };
137 :
138 : struct M2Quads__T3_r {
139 : M2Quads_QuadOperator Operator;
140 : unsigned int Operand1;
141 : unsigned int Operand2;
142 : unsigned int Operand3;
143 : unsigned int Trash;
144 : unsigned int Next;
145 : unsigned int LineNo;
146 : unsigned int TokenNo;
147 : unsigned int NoOfTimesReferenced;
148 : bool ConstExpr;
149 : bool CheckType;
150 : bool CheckOverflow;
151 : unsigned int op1pos;
152 : unsigned int op2pos;
153 : unsigned int op3pos;
154 : };
155 :
156 : struct M2Quads__T4_r {
157 : unsigned int RecordSym;
158 : unsigned int RecordType;
159 : unsigned int RecordRef;
160 : unsigned int rw;
161 : unsigned int RecordTokPos;
162 : };
163 :
164 : struct M2Quads__T5_r {
165 : unsigned int IncrementQuad;
166 : unsigned int StartOfForLoop;
167 : unsigned int EndOfForLoop;
168 : unsigned int ForLoopIndex;
169 : unsigned int IndexTok;
170 : };
171 :
172 : struct M2Quads__T6_r {
173 : unsigned int Line;
174 : NameKey_Name File;
175 : M2Quads_LineNote Next;
176 : };
177 :
178 : static M2StackAddress_StackOfAddress ConstructorStack;
179 : static M2StackAddress_StackOfAddress LineStack;
180 : static M2StackAddress_StackOfAddress BoolStack;
181 : static M2StackAddress_StackOfAddress WithStack;
182 : static M2StackWord_StackOfWord TryStack;
183 : static M2StackWord_StackOfWord CatchStack;
184 : static M2StackWord_StackOfWord ExceptStack;
185 : static M2StackWord_StackOfWord ConstExprStack;
186 : static M2StackWord_StackOfWord ConstParamStack;
187 : static M2StackWord_StackOfWord AutoStack;
188 : static M2StackWord_StackOfWord RepeatStack;
189 : static M2StackWord_StackOfWord WhileStack;
190 : static M2StackWord_StackOfWord ForStack;
191 : static M2StackWord_StackOfWord ExitStack;
192 : static M2StackWord_StackOfWord ReturnStack;
193 : static M2StackWord_StackOfWord PriorityStack;
194 : static bool SuppressWith;
195 : static Indexing_Index QuadArray;
196 : static unsigned int NextQuad;
197 : static unsigned int FreeList;
198 : static unsigned int CurrentProc;
199 : static unsigned int InitQuad;
200 : static unsigned int LastQuadNo;
201 : static NameKey_Name ArithPlusTok;
202 : static NameKey_Name LogicalOrTok;
203 : static NameKey_Name LogicalAndTok;
204 : static NameKey_Name LogicalXorTok;
205 : static NameKey_Name LogicalDifferenceTok;
206 : static bool InConstExpression;
207 : static bool InConstParameters;
208 : static bool IsAutoOn;
209 : static bool MustNotCheckBounds;
210 : static Indexing_Index ForInfo;
211 : static unsigned int GrowInitialization;
212 : static bool BuildingHigh;
213 : static bool BuildingSize;
214 : static bool QuadrupleGeneration;
215 : static M2Quads_LineNote FreeLineList;
216 : static Lists_List VarientFields;
217 : static unsigned int VarientFieldNo;
218 : static unsigned int NoOfQuads;
219 : static unsigned int Head;
220 : static M2Diagnostic_Diagnostic QuadMemDiag;
221 : static unsigned int BreakQuad;
222 :
223 : /*
224 : SetOptionCoding - builds a code quadruple if the profiling
225 : option was given to the compiler.
226 : */
227 :
228 : extern "C" void M2Quads_SetOptionCoding (bool b);
229 :
230 : /*
231 : SetOptionProfiling - builds a profile quadruple if the profiling
232 : option was given to the compiler.
233 : */
234 :
235 : extern "C" void M2Quads_SetOptionProfiling (bool b);
236 :
237 : /*
238 : SetOptionOptimizing - builds a quadruple to say that the optimization option
239 : has been found in a comment.
240 : */
241 :
242 : extern "C" void M2Quads_SetOptionOptimizing (bool b);
243 :
244 : /*
245 : Opposite - returns the opposite comparison operator.
246 : */
247 :
248 : extern "C" M2Quads_QuadOperator M2Quads_Opposite (M2Quads_QuadOperator Operator);
249 :
250 : /*
251 : IsReferenced - returns true if QuadNo is referenced by another quadruple.
252 : */
253 :
254 : extern "C" bool M2Quads_IsReferenced (unsigned int QuadNo);
255 :
256 : /*
257 : IsBackReference - returns TRUE if quadruple, q, is referenced from a quad further on.
258 : */
259 :
260 : extern "C" bool M2Quads_IsBackReference (unsigned int q);
261 :
262 : /*
263 : IsUnConditional - returns true if QuadNo is an unconditional jump.
264 : */
265 :
266 : extern "C" bool M2Quads_IsUnConditional (unsigned int QuadNo);
267 :
268 : /*
269 : IsConditional - returns true if QuadNo is a conditional jump.
270 : */
271 :
272 : extern "C" bool M2Quads_IsConditional (unsigned int QuadNo);
273 :
274 : /*
275 : IsBackReferenceConditional - returns TRUE if quadruple, q, is referenced from
276 : a conditional quad further on.
277 : */
278 :
279 : extern "C" bool M2Quads_IsBackReferenceConditional (unsigned int q);
280 :
281 : /*
282 : IsGoto - returns true if QuadNo is a goto operation.
283 : */
284 :
285 : extern "C" bool M2Quads_IsGoto (unsigned int QuadNo);
286 :
287 : /*
288 : IsCall - returns true if QuadNo is a call operation.
289 : */
290 :
291 : extern "C" bool M2Quads_IsCall (unsigned int QuadNo);
292 :
293 : /*
294 : IsReturn - returns true if QuadNo is a return operation.
295 : */
296 :
297 : extern "C" bool M2Quads_IsReturn (unsigned int QuadNo);
298 :
299 : /*
300 : IsProcedureScope - returns true if QuadNo is a ProcedureScope operation.
301 : */
302 :
303 : extern "C" bool M2Quads_IsProcedureScope (unsigned int QuadNo);
304 :
305 : /*
306 : IsNewLocalVar - returns true if QuadNo is a NewLocalVar operation.
307 : */
308 :
309 : extern "C" bool M2Quads_IsNewLocalVar (unsigned int QuadNo);
310 :
311 : /*
312 : IsKillLocalVar - returns true if QuadNo is a KillLocalVar operation.
313 : */
314 :
315 : extern "C" bool M2Quads_IsKillLocalVar (unsigned int QuadNo);
316 :
317 : /*
318 : IsCatchBegin - returns true if QuadNo is a catch begin quad.
319 : */
320 :
321 : extern "C" bool M2Quads_IsCatchBegin (unsigned int QuadNo);
322 :
323 : /*
324 : IsCatchEnd - returns true if QuadNo is a catch end quad.
325 : */
326 :
327 : extern "C" bool M2Quads_IsCatchEnd (unsigned int QuadNo);
328 :
329 : /*
330 : IsInitStart - returns true if QuadNo is a init start quad.
331 : */
332 :
333 : extern "C" bool M2Quads_IsInitStart (unsigned int QuadNo);
334 :
335 : /*
336 : IsInitEnd - returns true if QuadNo is a init end quad.
337 : */
338 :
339 : extern "C" bool M2Quads_IsInitEnd (unsigned int QuadNo);
340 :
341 : /*
342 : IsFinallyStart - returns true if QuadNo is a finally start quad.
343 : */
344 :
345 : extern "C" bool M2Quads_IsFinallyStart (unsigned int QuadNo);
346 :
347 : /*
348 : IsFinallyEnd - returns true if QuadNo is a finally end quad.
349 : */
350 :
351 : extern "C" bool M2Quads_IsFinallyEnd (unsigned int QuadNo);
352 :
353 : /*
354 : IsBecomes - return TRUE if QuadNo is a BecomesOp.
355 : */
356 :
357 : extern "C" bool M2Quads_IsBecomes (unsigned int QuadNo);
358 :
359 : /*
360 : IsDummy - return TRUE if QuadNo is a DummyOp.
361 : */
362 :
363 : extern "C" bool M2Quads_IsDummy (unsigned int QuadNo);
364 :
365 : /*
366 : IsQuadConstExpr - returns TRUE if QuadNo is part of a constant expression.
367 : */
368 :
369 : extern "C" bool M2Quads_IsQuadConstExpr (unsigned int QuadNo);
370 :
371 : /*
372 : SetQuadConstExpr - sets the constexpr field to value.
373 : */
374 :
375 : extern "C" void M2Quads_SetQuadConstExpr (unsigned int QuadNo, bool value);
376 :
377 : /*
378 : GetQuadDest - returns the jump destination associated with quad.
379 : */
380 :
381 : extern "C" unsigned int M2Quads_GetQuadDest (unsigned int QuadNo);
382 :
383 : /*
384 : GetQuadOp1 - returns the 1st operand associated with quad.
385 : */
386 :
387 : extern "C" unsigned int M2Quads_GetQuadOp1 (unsigned int QuadNo);
388 :
389 : /*
390 : GetQuadOp2 - returns the 2nd operand associated with quad.
391 : */
392 :
393 : extern "C" unsigned int M2Quads_GetQuadOp2 (unsigned int QuadNo);
394 :
395 : /*
396 : GetQuadOp3 - returns the 3rd operand associated with quad.
397 : */
398 :
399 : extern "C" unsigned int M2Quads_GetQuadOp3 (unsigned int QuadNo);
400 :
401 : /*
402 : IsInitialisingConst - returns TRUE if the quadruple is setting
403 : a const (op1) with a value.
404 : */
405 :
406 : extern "C" bool M2Quads_IsInitialisingConst (unsigned int QuadNo);
407 :
408 : /*
409 : IsConstQuad - return TRUE if the quadruple is marked as a constexpr.
410 : */
411 :
412 : extern "C" bool M2Quads_IsConstQuad (unsigned int quad);
413 :
414 : /*
415 : IsConditionalBooleanQuad - return TRUE if operand 1 is a boolean result.
416 : */
417 :
418 : extern "C" bool M2Quads_IsConditionalBooleanQuad (unsigned int quad);
419 :
420 : /*
421 : IsOptimizeOn - returns true if the Optimize flag was true at QuadNo.
422 : */
423 :
424 : extern "C" bool M2Quads_IsOptimizeOn (unsigned int QuadNo);
425 :
426 : /*
427 : IsProfileOn - returns true if the Profile flag was true at QuadNo.
428 : */
429 :
430 : extern "C" bool M2Quads_IsProfileOn (unsigned int QuadNo);
431 :
432 : /*
433 : IsCodeOn - returns true if the Code flag was true at QuadNo.
434 : */
435 :
436 : extern "C" bool M2Quads_IsCodeOn (unsigned int QuadNo);
437 :
438 : /*
439 : IsPseudoQuad - returns true if QuadNo is a compiler directive.
440 : ie code, profile and optimize.
441 : StartFile, EndFile,
442 : */
443 :
444 : extern "C" bool M2Quads_IsPseudoQuad (unsigned int QuadNo);
445 :
446 : /*
447 : IsDefOrModFile - returns TRUE if QuadNo is a start of Module or Def file
448 : directive.
449 : */
450 :
451 : extern "C" bool M2Quads_IsDefOrModFile (unsigned int QuadNo);
452 :
453 : /*
454 : DumpQuadruples - dump all quadruples providing the -fq, -fdump-lang-quad,
455 : -fdump-lang-quad= or -fdump-lang-all were issued to the
456 : command line.
457 : */
458 :
459 : extern "C" void M2Quads_DumpQuadruples (const char *title_, unsigned int _title_high);
460 :
461 : /*
462 : DisplayQuadRange - displays all quads in list range, start..end.
463 : */
464 :
465 : extern "C" void M2Quads_DisplayQuadRange (unsigned int scope, unsigned int start, unsigned int end);
466 :
467 : /*
468 : DisplayQuad - displays a quadruple, QuadNo.
469 : */
470 :
471 : extern "C" void M2Quads_DisplayQuad (unsigned int QuadNo);
472 :
473 : /*
474 : GetLastFileQuad - returns the Quadruple number of the last StartDefFile or
475 : StartModFile quadruple.
476 : */
477 :
478 : extern "C" unsigned int M2Quads_GetLastFileQuad (unsigned int QuadNo);
479 :
480 : /*
481 : GetLastQuadNo - returns the last quadruple number referenced
482 : by a GetQuad.
483 : */
484 :
485 : extern "C" unsigned int M2Quads_GetLastQuadNo (void);
486 :
487 : /*
488 : QuadToTokenNo - Converts a QuadNo into the approprate token number of the
489 : source file, the line number is returned.
490 :
491 : This may be used to yield an idea where abouts in the
492 : source file the code generetion is
493 : processing.
494 : */
495 :
496 : extern "C" unsigned int M2Quads_QuadToTokenNo (unsigned int QuadNo);
497 :
498 : /*
499 : QuadToLineNo - Converts a QuadNo into the approprate line number of the
500 : source file, the line number is returned.
501 :
502 : This may be used to yield an idea where abouts in the
503 : source file the code generetion is
504 : processing.
505 : */
506 :
507 : extern "C" unsigned int M2Quads_QuadToLineNo (unsigned int QuadNo);
508 :
509 : /*
510 : GetQuad - returns the Quadruple QuadNo.
511 : */
512 :
513 : extern "C" void M2Quads_GetQuad (unsigned int QuadNo, M2Quads_QuadOperator *Op, unsigned int *Oper1, unsigned int *Oper2, unsigned int *Oper3);
514 :
515 : /*
516 : GetQuadOp - returns the operator for quad.
517 : */
518 :
519 : extern "C" M2Quads_QuadOperator M2Quads_GetQuadOp (unsigned int quad);
520 :
521 : /*
522 : GetM2OperatorDesc - returns the Modula-2 string associated with the quad operator
523 : (if possible). It returns NIL if no there is not an obvious match
524 : in Modula-2. It is assummed that the string will be used during
525 : construction of error messages and therefore keywords are
526 : wrapped with a format specifier.
527 : */
528 :
529 : extern "C" DynamicStrings_String M2Quads_GetM2OperatorDesc (M2Quads_QuadOperator op);
530 :
531 : /*
532 : GetQuadtok - returns the Quadruple QuadNo.
533 : */
534 :
535 : extern "C" void M2Quads_GetQuadtok (unsigned int QuadNo, M2Quads_QuadOperator *Op, unsigned int *Oper1, unsigned int *Oper2, unsigned int *Oper3, unsigned int *Op1Pos, unsigned int *Op2Pos, unsigned int *Op3Pos);
536 :
537 : /*
538 : GetQuadOtok - returns the Quadruple QuadNo.
539 : */
540 :
541 : extern "C" void M2Quads_GetQuadOtok (unsigned int QuadNo, unsigned int *tok, M2Quads_QuadOperator *Op, unsigned int *Oper1, unsigned int *Oper2, unsigned int *Oper3, bool *overflowChecking, bool *constExpr, unsigned int *Op1Pos, unsigned int *Op2Pos, unsigned int *Op3Pos);
542 :
543 : /*
544 : GetQuadOTypetok - returns the fields associated with quadruple QuadNo.
545 : */
546 :
547 : extern "C" void M2Quads_GetQuadOTypetok (unsigned int QuadNo, unsigned int *tok, M2Quads_QuadOperator *Op, unsigned int *Oper1, unsigned int *Oper2, unsigned int *Oper3, bool *overflowChecking, bool *typeChecking, bool *constExpr, unsigned int *Op1Pos, unsigned int *Op2Pos, unsigned int *Op3Pos);
548 :
549 : /*
550 : PutQuadOtok - alters a quadruple QuadNo with Op, Oper1, Oper2, Oper3, and
551 : sets a boolean to determinine whether overflow should be checked.
552 : */
553 :
554 : extern "C" void M2Quads_PutQuadOtok (unsigned int QuadNo, unsigned int tok, M2Quads_QuadOperator Op, unsigned int Oper1, unsigned int Oper2, unsigned int Oper3, bool overflowChecking, bool constExpr, unsigned int Op1Pos, unsigned int Op2Pos, unsigned int Op3Pos);
555 :
556 : /*
557 : PutQuad - overwrites a quadruple QuadNo with Op, Oper1, Oper2, Oper3
558 : */
559 :
560 : extern "C" void M2Quads_PutQuad (unsigned int QuadNo, M2Quads_QuadOperator Op, unsigned int Oper1, unsigned int Oper2, unsigned int Oper3);
561 :
562 : /*
563 : GetFirstQuad - returns the first quadruple.
564 : */
565 :
566 : extern "C" unsigned int M2Quads_GetFirstQuad (void);
567 :
568 : /*
569 : GetNextQuad - returns the Quadruple number following QuadNo.
570 : */
571 :
572 : extern "C" unsigned int M2Quads_GetNextQuad (unsigned int QuadNo);
573 :
574 : /*
575 : GetRealQuad - returns the Quadruple number of the real quadruple
576 : at QuadNo or beyond.
577 : */
578 :
579 : extern "C" unsigned int M2Quads_GetRealQuad (unsigned int QuadNo);
580 :
581 : /*
582 : SubQuad - subtracts a quadruple QuadNo from a list Head.
583 : */
584 :
585 : extern "C" void M2Quads_SubQuad (unsigned int QuadNo);
586 :
587 : /*
588 : EraseQuad - erases a quadruple QuadNo, the quadruple is still in the list
589 : but wiped clean.
590 : */
591 :
592 : extern "C" void M2Quads_EraseQuad (unsigned int QuadNo);
593 :
594 : /*
595 : CountQuads - returns the number of quadruples.
596 : */
597 :
598 : extern "C" unsigned int M2Quads_CountQuads (void);
599 :
600 : /*
601 : BuildScaffold - generate the main, init, finish functions if
602 : no -c and this is the application module.
603 : */
604 :
605 : extern "C" void M2Quads_BuildScaffold (unsigned int tok, unsigned int moduleSym);
606 :
607 : /*
608 : StartBuildDefFile - generates a StartFileDefOp quadruple indicating the file
609 : that has produced the subsequent quadruples.
610 : The code generator uses the StartDefFileOp quadruples
611 : to relate any error to the appropriate file.
612 :
613 :
614 : Entry Exit
615 : ===== ====
616 :
617 :
618 : Ptr -> <- Ptr
619 : +------------+ +------------+
620 : | ModuleName | | ModuleName |
621 : |------------| |------------|
622 :
623 :
624 : Quadruples Produced
625 :
626 : q StartDefFileOp _ _ ModuleSym
627 : */
628 :
629 : extern "C" void M2Quads_StartBuildDefFile (unsigned int tok);
630 :
631 : /*
632 : StartBuildModFile - generates a StartModFileOp quadruple indicating the file
633 : that has produced the subsequent quadruples.
634 : The code generator uses the StartModFileOp quadruples
635 : to relate any error to the appropriate file.
636 :
637 :
638 : Entry Exit
639 : ===== ====
640 :
641 :
642 : Ptr -> <- Ptr
643 : +------------+ +------------+
644 : | ModuleName | | ModuleName |
645 : |------------| |------------|
646 :
647 :
648 : Quadruples Produced
649 :
650 : q StartModFileOp lineno filename ModuleSym
651 : */
652 :
653 : extern "C" void M2Quads_StartBuildModFile (unsigned int tok);
654 :
655 : /*
656 : EndBuildFile - generates an EndFileOp quadruple indicating the file
657 : that has produced the previous quadruples has ended.
658 :
659 : Entry Exit
660 : ===== ====
661 :
662 :
663 : Ptr -> <- Ptr
664 : +------------+ +------------+
665 : | ModuleName | | ModuleName |
666 : |------------| |------------|
667 :
668 :
669 : Quadruples Produced
670 :
671 : q EndFileOp _ _ ModuleSym
672 : */
673 :
674 : extern "C" void M2Quads_EndBuildFile (unsigned int tok);
675 :
676 : /*
677 : StartBuildInit - Sets the start of initialization code of the
678 : current module to the next quadruple.
679 : */
680 :
681 : extern "C" void M2Quads_StartBuildInit (unsigned int tok);
682 :
683 : /*
684 : EndBuildInit - Sets the end initialization code of a module.
685 : */
686 :
687 : extern "C" void M2Quads_EndBuildInit (unsigned int tok);
688 :
689 : /*
690 : StartBuildFinally - Sets the start of finalization code of the
691 : current module to the next quadruple.
692 : */
693 :
694 : extern "C" void M2Quads_StartBuildFinally (unsigned int tok);
695 :
696 : /*
697 : EndBuildFinally - Sets the end finalization code of a module.
698 : */
699 :
700 : extern "C" void M2Quads_EndBuildFinally (unsigned int tok);
701 :
702 : /*
703 : BuildExceptInitial - adds an CatchBeginOp, CatchEndOp quadruple
704 : in the current block.
705 : */
706 :
707 : extern "C" void M2Quads_BuildExceptInitial (unsigned int tok);
708 :
709 : /*
710 : BuildExceptFinally - adds an ExceptOp quadruple in a modules
711 : finally block.
712 : */
713 :
714 : extern "C" void M2Quads_BuildExceptFinally (unsigned int tok);
715 :
716 : /*
717 : BuildExceptProcedure - adds an ExceptOp quadruple in a procedure
718 : block.
719 : */
720 :
721 : extern "C" void M2Quads_BuildExceptProcedure (unsigned int tok);
722 :
723 : /*
724 : BuildRetry - adds an RetryOp quadruple.
725 : */
726 :
727 : extern "C" void M2Quads_BuildRetry (unsigned int tok);
728 :
729 : /*
730 : BuildReThrow - creates a ThrowOp _ _ NulSym, indicating that
731 : the exception needs to be rethrown. The stack
732 : is unaltered.
733 : */
734 :
735 : extern "C" void M2Quads_BuildReThrow (unsigned int tokenno);
736 :
737 : /*
738 : StartBuildInnerInit - Sets the start of initialization code of the
739 : inner module to the next quadruple.
740 : */
741 :
742 : extern "C" void M2Quads_StartBuildInnerInit (unsigned int tok);
743 :
744 : /*
745 : EndBuildInnerInit - Sets the end initialization code of a module.
746 : */
747 :
748 : extern "C" void M2Quads_EndBuildInnerInit (unsigned int tok);
749 :
750 : /*
751 : BuildBuiltinConst - makes reference to a builtin constant within gm2.
752 :
753 : Entry Exit
754 :
755 : Ptr ->
756 : +------------+ +------------+
757 : | Ident | | Sym |
758 : |------------| |------------|
759 :
760 : Quadruple produced:
761 :
762 : q Sym BuiltinConstOp Ident
763 : */
764 :
765 : extern "C" void M2Quads_BuildBuiltinConst (void);
766 :
767 : /*
768 : BuildBuiltinTypeInfo - make reference to a builtin typeinfo function
769 : within gm2.
770 :
771 : Entry Exit
772 :
773 : Ptr ->
774 : +-------------+
775 : | Type |
776 : |-------------| +------------+
777 : | Ident | | Sym |
778 : |-------------| |------------|
779 :
780 : Quadruple produced:
781 :
782 : q Sym BuiltinTypeInfoOp Type Ident
783 : */
784 :
785 : extern "C" void M2Quads_BuildBuiltinTypeInfo (void);
786 :
787 : /*
788 : BuildAssignment - Builds an assignment from the values given on the
789 : quad stack. Either an assignment to an
790 : arithmetic expression or an assignment to a
791 : boolean expression. This procedure should not
792 : be called in CONST declarations.
793 : The Stack is expected to contain:
794 :
795 :
796 : Either
797 :
798 : Entry Exit
799 : ===== ====
800 :
801 : Ptr ->
802 : +------------+
803 : | Expression |
804 : |------------|
805 : | Designator |
806 : |------------| +------------+
807 : | | | | <- Ptr
808 : |------------| |------------|
809 :
810 :
811 : Quadruples Produced
812 :
813 : q BecomesOp Designator _ Expression
814 :
815 : OR
816 :
817 : Entry Exit
818 : ===== ====
819 :
820 : Ptr ->
821 : +------------+
822 : | True |False|
823 : |------------|
824 : | Designator |
825 : |------------| +------------+
826 : | | | | <- Ptr
827 : |------------| |------------|
828 :
829 :
830 : Quadruples Produced
831 :
832 : q BecomesOp Designator _ TRUE
833 : q+1 GotoOp q+3
834 : q+2 BecomesOp Designator _ FALSE
835 :
836 : */
837 :
838 : extern "C" void M2Quads_BuildAssignment (unsigned int becomesTokNo);
839 :
840 : /*
841 : BuildAssignConstant - used to create constant in the CONST declaration.
842 : The stack is expected to contain:
843 :
844 : Either
845 :
846 : Entry Exit
847 : ===== ====
848 :
849 : Ptr ->
850 : +------------+
851 : | Expression |
852 : |------------|
853 : | Designator |
854 : |------------| +------------+
855 : | | | | <- Ptr
856 : |------------| |------------|
857 :
858 :
859 : Quadruples Produced
860 :
861 : q BecomesOp Designator _ Expression
862 :
863 : OR
864 :
865 : Entry Exit
866 : ===== ====
867 :
868 : Ptr ->
869 : +------------+
870 : | True |False|
871 : |------------|
872 : | Designator |
873 : |------------| +------------+
874 : | | | | <- Ptr
875 : |------------| |------------|
876 :
877 :
878 : Quadruples Produced
879 :
880 : q BecomesOp Designator _ TRUE
881 : q+1 GotoOp q+3
882 : q+2 BecomesOp Designator _ FALSE
883 : */
884 :
885 : extern "C" void M2Quads_BuildAssignConstant (unsigned int equalsTokNo);
886 :
887 : /*
888 : BuildAlignment - builds an assignment to an alignment constant.
889 :
890 : The Stack is expected to contain:
891 :
892 :
893 : Entry Exit
894 : ===== ====
895 :
896 : Ptr ->
897 : +---------------+
898 : | Expression |
899 : |---------------|
900 : | bytealignment |
901 : |---------------| empty
902 : */
903 :
904 : extern "C" void M2Quads_BuildAlignment (unsigned int tokno);
905 :
906 : /*
907 : BuildBitLength - builds an assignment to a bit length constant.
908 :
909 : The Stack is expected to contain:
910 :
911 :
912 : Entry Exit
913 : ===== ====
914 :
915 : Ptr ->
916 : +------------+
917 : | Expression |
918 : |------------| empty
919 : */
920 :
921 : extern "C" void M2Quads_BuildBitLength (unsigned int tokno);
922 :
923 : /*
924 : BuildPragmaField - builds an assignment to an alignment constant.
925 :
926 : The Stack is expected to contain:
927 :
928 :
929 : Entry Exit
930 : ===== ====
931 :
932 : Ptr ->
933 : +------------+
934 : | Expression |
935 : |------------| empty
936 : */
937 :
938 : extern "C" void M2Quads_BuildPragmaField (void);
939 :
940 : /*
941 : BuildDefaultFieldAlignment - builds an assignment to an alignment constant.
942 :
943 : The Stack is expected to contain:
944 :
945 :
946 : Entry Exit
947 : ===== ====
948 :
949 : Ptr ->
950 : +------------+
951 : | Expression |
952 : |------------| empty
953 : */
954 :
955 : extern "C" void M2Quads_BuildDefaultFieldAlignment (void);
956 :
957 : /*
958 : BuildRepeat - Builds the repeat statement from the quad stack.
959 : The Stack is expected to contain:
960 :
961 :
962 : Entry Exit
963 : ===== ====
964 :
965 :
966 : Empty
967 : <- Ptr
968 : +------------+
969 : | RepeatQuad |
970 : |------------|
971 :
972 : */
973 :
974 : extern "C" void M2Quads_BuildRepeat (void);
975 :
976 : /*
977 : BuildUntil - Builds the until part of the repeat statement
978 : from the quad stack.
979 : The Stack is expected to contain:
980 :
981 :
982 : Entry Exit
983 : ===== ====
984 :
985 : Ptr ->
986 : +------------+
987 : | t | f |
988 : |------------|
989 : | RepeatQuad | Empty
990 : |------------|
991 : */
992 :
993 : extern "C" void M2Quads_BuildUntil (void);
994 :
995 : /*
996 : BuildWhile - Builds the While part of the While statement
997 : from the quad stack.
998 : The Stack is expected to contain:
999 :
1000 :
1001 : Entry Exit
1002 : ===== ====
1003 :
1004 : <- Ptr
1005 : |------------|
1006 : Empty | WhileQuad |
1007 : |------------|
1008 : */
1009 :
1010 : extern "C" void M2Quads_BuildWhile (void);
1011 :
1012 : /*
1013 : BuildDoWhile - Builds the Do part of the while statement
1014 : from the quad stack.
1015 : The Stack is expected to contain:
1016 :
1017 :
1018 : Entry Exit
1019 : ===== ====
1020 :
1021 : Ptr ->
1022 : +------------+ +------------+
1023 : | t | f | | 0 | f |
1024 : |------------| |------------|
1025 : | WhileQuad | | WhileQuad |
1026 : |------------| |------------|
1027 :
1028 : Quadruples
1029 :
1030 : BackPatch t exit to the NextQuad
1031 : */
1032 :
1033 : extern "C" void M2Quads_BuildDoWhile (void);
1034 :
1035 : /*
1036 : BuildEndWhile - Builds the end part of the while statement
1037 : from the quad stack.
1038 : The Stack is expected to contain:
1039 :
1040 :
1041 : Entry Exit
1042 : ===== ====
1043 :
1044 : Ptr ->
1045 : +------------+
1046 : | t | f |
1047 : |------------|
1048 : | WhileQuad | Empty
1049 : |------------|
1050 :
1051 : Quadruples
1052 :
1053 : q GotoOp WhileQuad
1054 : False exit is backpatched with q+1
1055 : */
1056 :
1057 : extern "C" void M2Quads_BuildEndWhile (int reltokpos);
1058 :
1059 : /*
1060 : BuildLoop - Builds the Loop part of the Loop statement
1061 : from the quad stack.
1062 : The Stack is expected to contain:
1063 :
1064 :
1065 : Entry Exit
1066 : ===== ====
1067 :
1068 : <- Ptr
1069 : Empty +------------+
1070 : | LoopQuad |
1071 : |------------|
1072 : */
1073 :
1074 : extern "C" void M2Quads_BuildLoop (void);
1075 :
1076 : /*
1077 : BuildExit - Builds the Exit part of the Loop statement.
1078 : */
1079 :
1080 : extern "C" void M2Quads_BuildExit (void);
1081 :
1082 : /*
1083 : BuildEndLoop - Builds the End part of the Loop statement
1084 : from the quad stack.
1085 : The Stack is expected to contain:
1086 :
1087 :
1088 : Entry Exit
1089 : ===== ====
1090 :
1091 : Ptr ->
1092 : +------------+
1093 : | LoopQuad | Empty
1094 : |------------|
1095 :
1096 : Quadruples
1097 :
1098 : Goto _ _ LoopQuad
1099 : */
1100 :
1101 : extern "C" void M2Quads_BuildEndLoop (void);
1102 :
1103 : /*
1104 : BuildThenIf - Builds the Then part of the If statement
1105 : from the quad stack.
1106 : The Stack is expected to contain:
1107 :
1108 :
1109 : Entry Exit
1110 : ===== ====
1111 :
1112 : Ptr -> <- Ptr
1113 : +------------+ +------------+
1114 : | t | f | | 0 | f |
1115 : |------------| |------------|
1116 :
1117 : Quadruples
1118 :
1119 : The true exit is BackPatched to point to
1120 : the NextQuad.
1121 : */
1122 :
1123 : extern "C" void M2Quads_BuildThenIf (void);
1124 :
1125 : /*
1126 : BuildElse - Builds the Else part of the If statement
1127 : from the quad stack.
1128 : The Stack is expected to contain:
1129 :
1130 :
1131 : Entry Exit
1132 : ===== ====
1133 :
1134 : Ptr ->
1135 : +------------+ +------------+
1136 : | t | f | | t+q | 0 |
1137 : |------------| |------------|
1138 :
1139 : Quadruples
1140 :
1141 : q GotoOp _ _ 0
1142 : q+1 <- BackPatched from f
1143 : */
1144 :
1145 : extern "C" void M2Quads_BuildElse (void);
1146 :
1147 : /*
1148 : BuildEndIf - Builds the End part of the If statement
1149 : from the quad stack.
1150 : The Stack is expected to contain:
1151 :
1152 :
1153 : Entry Exit
1154 : ===== ====
1155 :
1156 : Ptr ->
1157 : +------------+
1158 : | t | f | Empty
1159 : |------------|
1160 :
1161 : Quadruples
1162 :
1163 : Both t and f are backpatched to point to the NextQuad
1164 : */
1165 :
1166 : extern "C" void M2Quads_BuildEndIf (void);
1167 :
1168 : /*
1169 : BuildElsif1 - Builds the Elsif part of the If statement
1170 : from the quad stack.
1171 : The Stack is expected to contain:
1172 :
1173 :
1174 : Entry Exit
1175 : ===== ====
1176 :
1177 : Ptr ->
1178 : +------------+ +------------+
1179 : | t | f | | t+q | 0 |
1180 : |------------| |------------|
1181 :
1182 : Quadruples
1183 :
1184 : q GotoOp _ _ 0
1185 : q+1 <- BackPatched from f
1186 : */
1187 :
1188 : extern "C" void M2Quads_BuildElsif1 (void);
1189 :
1190 : /*
1191 : BuildElsif2 - Builds the Elsif until part of the If statement
1192 : from the quad stack.
1193 : The Stack is expected to contain:
1194 :
1195 :
1196 : Entry Exit
1197 : ===== ====
1198 :
1199 : Ptr ->
1200 : +--------------+
1201 : | 0 | f1 | <- Ptr
1202 : |--------------| +---------------+
1203 : | t2 | f2 | | t2 | f1+f2 |
1204 : |--------------| |---------------|
1205 : */
1206 :
1207 : extern "C" void M2Quads_BuildElsif2 (void);
1208 :
1209 : /*
1210 : BuildForToByDo - Builds the For To By Do part of the For statement
1211 : from the quad stack.
1212 : The Stack is expected to contain:
1213 :
1214 :
1215 : Entry Exit
1216 : ===== ====
1217 :
1218 : <- Ptr
1219 : +----------------+
1220 : Ptr -> | RangeId |
1221 : +----------------+ |----------------|
1222 : | BySym | ByType | | ForQuad |
1223 : |----------------| |----------------|
1224 : | e2 | | LastValue |
1225 : |----------------| |----------------|
1226 : | e1 | | BySym | ByType |
1227 : |----------------| |----------------|
1228 : | Ident | | IdentSym |
1229 : |----------------| |----------------|
1230 :
1231 :
1232 : x := e1 ;
1233 : Note that LASTVALUE is calculated during M2GenGCC
1234 : after all the types have been resolved.
1235 : LASTVALUE := ((e2-e1) DIV BySym) * BySym + e1
1236 : IF BySym<0
1237 : THEN
1238 : IF e1<e2
1239 : THEN
1240 : goto exit
1241 : END
1242 : ELSE
1243 : IF e1>e2
1244 : THEN
1245 : goto exit
1246 : END
1247 : END ;
1248 : LOOP
1249 : body
1250 : IF x=LASTVALUE
1251 : THEN
1252 : goto exit
1253 : END ;
1254 : INC(x, BySym)
1255 : END
1256 :
1257 : Quadruples:
1258 :
1259 : q BecomesOp IdentSym _ e1
1260 : q+ LastForIteratorOp LastValue := ((e1-e2) DIV by) * by + e1
1261 : q+1 if >= by 0 q+..2
1262 : q+2 GotoOp q+3
1263 : q+3 If >= e1 e2 q+5
1264 : q+4 GotoOp exit
1265 : q+5 ..
1266 : q+..1 Goto q+..5
1267 : q+..2 If >= e2 e1 q+..4
1268 : q+..3 GotoOp exit
1269 : q+..4 ..
1270 :
1271 : The For Loop is regarded:
1272 :
1273 : For ident := e1 To e2 By by Do
1274 :
1275 : End
1276 : */
1277 :
1278 : extern "C" void M2Quads_BuildForToByDo (void);
1279 :
1280 : /*
1281 : BuildPseudoBy - Builds the Non existant part of the By
1282 : clause of the For statement
1283 : from the quad stack.
1284 : The Stack is expected to contain:
1285 :
1286 :
1287 : Entry Exit
1288 : ===== ====
1289 :
1290 : <- Ptr
1291 : +------------+
1292 : Ptr -> | BySym | t |
1293 : +------------+ |------------|
1294 : | e | t | | e | t |
1295 : |------------| |------------|
1296 : */
1297 :
1298 : extern "C" void M2Quads_BuildPseudoBy (void);
1299 :
1300 : /*
1301 : BuildEndFor - Builds the End part of the For statement
1302 : from the quad stack.
1303 : The Stack is expected to contain:
1304 :
1305 :
1306 : Entry Exit
1307 : ===== ====
1308 :
1309 : Ptr ->
1310 : +----------------+
1311 : | RangeId |
1312 : |----------------|
1313 : | ForQuad |
1314 : |----------------|
1315 : | LastValue |
1316 : |----------------|
1317 : | BySym | ByType |
1318 : |----------------|
1319 : | IdSym | Empty
1320 : |----------------|
1321 : */
1322 :
1323 : extern "C" void M2Quads_BuildEndFor (unsigned int endpostok);
1324 :
1325 : /*
1326 : BuildCaseStart - starts the case statement.
1327 : It initializes a backpatch list on the compile
1328 : time stack, the list is used to contain all
1329 : case break points. The list is later backpatched
1330 : and contains all positions of the case statement
1331 : which jump to the end of the case statement.
1332 : The stack also contains room for a boolean
1333 : expression, this is needed to allow , operator
1334 : in the CaseField alternatives.
1335 :
1336 : The Stack is expected to contain:
1337 :
1338 :
1339 : Entry Exit
1340 : ===== ====
1341 :
1342 : <- Ptr
1343 : +------------+
1344 : | 0 | 0 |
1345 : |------------|
1346 : | 0 | 0 |
1347 : +-------------+ |------------|
1348 : | Expr | | | Expr | |
1349 : |-------------| |------------|
1350 : */
1351 :
1352 : extern "C" void M2Quads_BuildCaseStart (void);
1353 :
1354 : /*
1355 : BuildCaseStartStatementSequence - starts the statement sequence
1356 : inside a case clause.
1357 : BackPatches the true exit to the
1358 : NextQuad.
1359 : The Stack:
1360 :
1361 : Entry Exit
1362 :
1363 : Ptr -> <- Ptr
1364 : +-----------+ +------------+
1365 : | t | f | | 0 | f |
1366 : |-----------| |------------|
1367 : */
1368 :
1369 : extern "C" void M2Quads_BuildCaseStartStatementSequence (void);
1370 :
1371 : /*
1372 : BuildCaseEndStatementSequence - ends the statement sequence
1373 : inside a case clause.
1374 : BackPatches the false exit f1 to the
1375 : NextQuad.
1376 : Asserts that t1 and f2 is 0
1377 : Pushes t2+q and 0
1378 :
1379 : Quadruples:
1380 :
1381 : q GotoOp _ _ 0
1382 :
1383 : The Stack:
1384 :
1385 : Entry Exit
1386 :
1387 : Ptr -> <- Ptr
1388 : +-----------+ +------------+
1389 : | t1 | f1 | | 0 | 0 |
1390 : |-----------| |------------|
1391 : | t2 | f2 | | t2+q | 0 |
1392 : |-----------| |------------|
1393 : */
1394 :
1395 : extern "C" void M2Quads_BuildCaseEndStatementSequence (void);
1396 :
1397 : /*
1398 : BuildCaseRange - builds the range testing quaruples for
1399 : a case clause.
1400 :
1401 : IF (e1>=ce1) AND (e1<=ce2)
1402 : THEN
1403 :
1404 : ELS..
1405 :
1406 : The Stack:
1407 :
1408 : Entry Exit
1409 :
1410 : Ptr ->
1411 : +-----------+
1412 : | ce2 | <- Ptr
1413 : |-----------| +-----------+
1414 : | ce1 | | t | f |
1415 : |-----------| |-----------|
1416 : | t1 | f1 | | t1 | f1 |
1417 : |-----------| |-----------|
1418 : | t2 | f2 | | t2 | f2 |
1419 : |-----------| |-----------|
1420 : | e1 | | e1 |
1421 : |-----------| |-----------|
1422 : */
1423 :
1424 : extern "C" void M2Quads_BuildCaseRange (void);
1425 :
1426 : /*
1427 : BuildCaseEquality - builds the range testing quadruples for
1428 : a case clause.
1429 :
1430 : IF e1=ce1
1431 : THEN
1432 :
1433 : ELS..
1434 :
1435 : The Stack:
1436 :
1437 : Entry Exit
1438 :
1439 : Ptr ->
1440 : +-----------+ +-----------+
1441 : | ce1 | | t | f |
1442 : |-----------| |-----------|
1443 : | t1 | f1 | | t1 | f1 |
1444 : |-----------| |-----------|
1445 : | t2 | f2 | | t2 | f2 |
1446 : |-----------| |-----------|
1447 : | e1 | | e1 |
1448 : |-----------| |-----------|
1449 : */
1450 :
1451 : extern "C" void M2Quads_BuildCaseEquality (void);
1452 :
1453 : /*
1454 : BuildCaseList - merges two case tests into one
1455 :
1456 : The Stack:
1457 :
1458 : Entry Exit
1459 :
1460 : Ptr ->
1461 : +-----------+
1462 : | t2 | f2 |
1463 : |-----------| +-------------+
1464 : | t1 | f1 | | t1+t2| f1+f2|
1465 : |-----------| |-------------|
1466 : */
1467 :
1468 : extern "C" void M2Quads_BuildCaseList (void);
1469 :
1470 : /*
1471 : BuildCaseOr - builds the , in the case clause.
1472 :
1473 : The Stack:
1474 :
1475 : Entry Exit
1476 :
1477 : Ptr -> <- Ptr
1478 : +-----------+ +------------+
1479 : | t | f | | t | 0 |
1480 : |-----------| |------------|
1481 : */
1482 :
1483 : extern "C" void M2Quads_BuildCaseOr (void);
1484 :
1485 : /*
1486 : BuildCaseElse - builds the else of case clause.
1487 :
1488 : The Stack:
1489 :
1490 : Entry Exit
1491 :
1492 : Ptr -> <- Ptr
1493 : +-----------+ +------------+
1494 : | t | f | | t | 0 |
1495 : |-----------| |------------|
1496 : */
1497 :
1498 : extern "C" void M2Quads_BuildCaseElse (void);
1499 :
1500 : /*
1501 : BuildCaseEnd - builds the end of case clause.
1502 :
1503 : The Stack:
1504 :
1505 : Entry Exit
1506 :
1507 : Ptr ->
1508 : +-----------+
1509 : | t1 | f1 |
1510 : |-----------|
1511 : | t2 | f2 |
1512 : |-----------|
1513 : | e1 |
1514 : |-----------| Empty
1515 : */
1516 :
1517 : extern "C" void M2Quads_BuildCaseEnd (void);
1518 :
1519 : /*
1520 : BuildCaseCheck - builds the case checking code to ensure that
1521 : the program does not need an else clause at runtime.
1522 : The stack is unaltered.
1523 : */
1524 :
1525 : extern "C" void M2Quads_BuildCaseCheck (void);
1526 :
1527 : /*
1528 : BuildNulParam - Builds a nul parameter on the stack.
1529 : The Stack:
1530 :
1531 : Entry Exit
1532 :
1533 : <- Ptr
1534 : Empty +------------+
1535 : | 0 |
1536 : |------------|
1537 : */
1538 :
1539 : extern "C" void M2Quads_BuildNulParam (void);
1540 :
1541 : /*
1542 : BuildProcedureCall - builds a procedure call.
1543 : Although this procedure does not directly
1544 : destroy the procedure parameters, it calls
1545 : routine which will manipulate the stack and
1546 : so the entry and exit states of the stack are shown.
1547 :
1548 : The Stack:
1549 :
1550 :
1551 : Entry Exit
1552 :
1553 : Ptr ->
1554 : +----------------+
1555 : | NoOfParam |
1556 : |----------------|
1557 : | Param 1 |
1558 : |----------------|
1559 : | Param 2 |
1560 : |----------------|
1561 : . .
1562 : . .
1563 : . .
1564 : |----------------|
1565 : | Param # |
1566 : |----------------|
1567 : | ProcSym | Type | Empty
1568 : |----------------|
1569 : */
1570 :
1571 : extern "C" void M2Quads_BuildProcedureCall (unsigned int tokno);
1572 :
1573 : /*
1574 : CheckBuildFunction - checks to see whether ProcSym is a function
1575 : and if so it adds a TempSym value which will
1576 : hold the return value once the function finishes.
1577 : This procedure also generates an error message
1578 : if the user is calling a function and ignoring
1579 : the return result. The additional TempSym
1580 : is not created if ProcSym is a procedure
1581 : and the stack is unaltered.
1582 :
1583 : The Stack:
1584 :
1585 :
1586 : Entry Exit
1587 :
1588 : Ptr ->
1589 :
1590 : +----------------+
1591 : | ProcSym | Type |
1592 : +----------------+ |----------------|
1593 : | ProcSym | Type | | TempSym | Type |
1594 : |----------------| |----------------|
1595 : */
1596 :
1597 : extern "C" bool M2Quads_CheckBuildFunction (void);
1598 :
1599 : /*
1600 : BuildFunctionCall - builds a function call.
1601 : The Stack:
1602 :
1603 :
1604 : Entry Exit
1605 :
1606 : Ptr ->
1607 : +----------------+
1608 : | NoOfParam |
1609 : |----------------|
1610 : | Param 1 |
1611 : |----------------|
1612 : | Param 2 |
1613 : |----------------|
1614 : . .
1615 : . .
1616 : . .
1617 : |----------------|
1618 : | Param # | <- Ptr
1619 : |----------------| +------------+
1620 : | ProcSym | Type | | ReturnVar |
1621 : |----------------| |------------|
1622 : */
1623 :
1624 : extern "C" void M2Quads_BuildFunctionCall (bool ConstExpr);
1625 :
1626 : /*
1627 : BuildConstFunctionCall - builds a function call and checks that this function can be
1628 : called inside a ConstExpression.
1629 :
1630 : The Stack:
1631 :
1632 :
1633 : Entry Exit
1634 :
1635 : Ptr ->
1636 : +----------------+
1637 : | NoOfParam |
1638 : |----------------|
1639 : | Param 1 |
1640 : |----------------|
1641 : | Param 2 |
1642 : |----------------|
1643 : . .
1644 : . .
1645 : . .
1646 : |----------------|
1647 : | Param # | <- Ptr
1648 : |----------------| +------------+
1649 : | ProcSym | Type | | ReturnVar |
1650 : |----------------| |------------|
1651 :
1652 : */
1653 :
1654 : extern "C" void M2Quads_BuildConstFunctionCall (void);
1655 :
1656 : /*
1657 : BuildBooleanVariable - tests to see whether top of stack is a boolean
1658 : conditional and if so it converts it into a boolean
1659 : variable.
1660 : */
1661 :
1662 : extern "C" void M2Quads_BuildBooleanVariable (void);
1663 :
1664 : /*
1665 : BuildModuleStart - starts current module scope.
1666 : */
1667 :
1668 : extern "C" void M2Quads_BuildModuleStart (unsigned int tok);
1669 :
1670 : /*
1671 : BuildProcedureStart - Builds start of the procedure. Generates a
1672 : quadruple which indicated the start of
1673 : this procedure declarations scope.
1674 : The Stack is expected to contain:
1675 :
1676 :
1677 : Entry Exit
1678 : ===== ====
1679 :
1680 : Ptr -> <- Ptr
1681 : +------------+ +-----------+
1682 : | ProcSym | | ProcSym |
1683 : |------------| |-----------|
1684 : | Name | | Name |
1685 : |------------| |-----------|
1686 :
1687 :
1688 : Quadruples:
1689 :
1690 : q ProcedureScopeOp Line# Scope ProcSym
1691 : */
1692 :
1693 : extern "C" void M2Quads_BuildProcedureStart (void);
1694 :
1695 : /*
1696 : BuildProcedureBegin - determines the start of the BEGIN END block of
1697 : the procedure.
1698 : The Stack is expected to contain:
1699 :
1700 :
1701 : Entry Exit
1702 : ===== ====
1703 :
1704 : Ptr -> <- Ptr
1705 : +------------+ +-----------+
1706 : | ProcSym | | ProcSym |
1707 : |------------| |-----------|
1708 : | Name | | Name |
1709 : |------------| |-----------|
1710 :
1711 :
1712 : Quadruples:
1713 :
1714 : q NewLocalVarOp TokenNo(BEGIN) _ ProcSym
1715 : */
1716 :
1717 : extern "C" void M2Quads_BuildProcedureBegin (void);
1718 :
1719 : /*
1720 : BuildProcedureEnd - Builds end of the procedure. Destroys space for
1721 : the local variables.
1722 : The Stack is expected to contain:
1723 :
1724 :
1725 : Entry Exit
1726 : ===== ====
1727 :
1728 : Ptr -> <- Ptr
1729 : +------------+ +-----------+
1730 : | ProcSym | | ProcSym |
1731 : |------------| |-----------|
1732 : | Name | | Name |
1733 : |------------| |-----------|
1734 :
1735 :
1736 : Quadruples:
1737 :
1738 : q KillLocalVarOp TokenNo(END) _ ProcSym
1739 : */
1740 :
1741 : extern "C" void M2Quads_BuildProcedureEnd (void);
1742 :
1743 : /*
1744 : BuildReturn - Builds the Return part of the procedure.
1745 : tokreturn is the location of the RETURN keyword.
1746 : The Stack is expected to contain:
1747 :
1748 :
1749 : Entry Exit
1750 : ===== ====
1751 :
1752 : Ptr ->
1753 : +------------+
1754 : | e1 | Empty
1755 : |------------|
1756 : */
1757 :
1758 : extern "C" void M2Quads_BuildReturn (unsigned int tokreturn);
1759 :
1760 : /*
1761 : BuildModulePriority - assigns the current module with a priority
1762 : from the top of stack.
1763 :
1764 : Entry Exit
1765 : ===== ====
1766 :
1767 :
1768 : Ptr -> Empty
1769 : +------------+
1770 : | Priority |
1771 : |------------|
1772 : */
1773 :
1774 : extern "C" void M2Quads_BuildModulePriority (void);
1775 :
1776 : /*
1777 : StartBuildWith - performs the with statement.
1778 : The Stack:
1779 :
1780 : Entry Exit
1781 :
1782 : +------------+
1783 : | Sym | Type | Empty
1784 : |------------|
1785 : */
1786 :
1787 : extern "C" void M2Quads_StartBuildWith (unsigned int withTok);
1788 :
1789 : /*
1790 : EndBuildWith - terminates the innermost with scope.
1791 : */
1792 :
1793 : extern "C" void M2Quads_EndBuildWith (void);
1794 :
1795 : /*
1796 : CheckWithReference - performs the with statement.
1797 : The Stack:
1798 :
1799 : Entry Exit
1800 :
1801 : +------------+ +------------+
1802 : | Sym | Type | | Sym | Type |
1803 : |------------| |------------|
1804 : */
1805 :
1806 : extern "C" void M2Quads_CheckWithReference (void);
1807 :
1808 : /*
1809 : BuildDesignatorRecord - Builds the record referencing.
1810 : The Stack is expected to contain:
1811 :
1812 :
1813 : Entry Exit
1814 : ===== ====
1815 :
1816 : Ptr ->
1817 : +--------------+
1818 : | n |
1819 : |--------------|
1820 : | fld1 | type1 |
1821 : |--------------|
1822 : . .
1823 : . .
1824 : . .
1825 : |--------------|
1826 : | fldn | typen | <- Ptr
1827 : |--------------| +-------------+
1828 : | Sym | Type | | S | type1|
1829 : |--------------| |-------------|
1830 : */
1831 :
1832 : extern "C" void M2Quads_BuildDesignatorRecord (unsigned int dottok);
1833 :
1834 : /*
1835 : BuildDesignatorArray - Builds the array referencing.
1836 : The purpose of this procedure is to work out
1837 : whether the DesignatorArray is a constant string or
1838 : dynamic array/static array and to call the appropriate
1839 : BuildRoutine.
1840 :
1841 : The Stack is expected to contain:
1842 :
1843 : Entry Exit
1844 : ===== ====
1845 :
1846 : Ptr ->
1847 : +--------------+
1848 : | e | <- Ptr
1849 : |--------------| +------------+
1850 : | Sym | Type | | S | T |
1851 : |--------------| |------------|
1852 : */
1853 :
1854 : extern "C" void M2Quads_BuildDesignatorArray (void);
1855 :
1856 : /*
1857 : BuildDesignatorPointer - Builds a pointer reference.
1858 : The Stack is expected to contain:
1859 :
1860 :
1861 : Entry Exit
1862 : ===== ====
1863 :
1864 : Ptr -> <- Ptr
1865 : +--------------+ +--------------+
1866 : | Sym1 | Type1| | Sym2 | Type2|
1867 : |--------------| |--------------|
1868 : */
1869 :
1870 : extern "C" void M2Quads_BuildDesignatorPointer (unsigned int ptrtok);
1871 :
1872 : /*
1873 : BuildNulExpression - Builds a nul expression on the stack.
1874 : The Stack:
1875 :
1876 : Entry Exit
1877 :
1878 : <- Ptr
1879 : Empty +------------+
1880 : | NulSym |
1881 : |------------|
1882 : tokpos is the position of the RETURN token.
1883 : */
1884 :
1885 : extern "C" void M2Quads_BuildNulExpression (unsigned int tokpos);
1886 :
1887 : /*
1888 : BuildSetStart - Pushes a Bitset type on the stack.
1889 :
1890 : The Stack:
1891 :
1892 : Entry Exit
1893 :
1894 : Ptr -> <- Ptr
1895 :
1896 : Empty +--------------+
1897 : | Bitset |
1898 : |--------------|
1899 : */
1900 :
1901 : extern "C" void M2Quads_BuildSetStart (unsigned int tokpos);
1902 :
1903 : /*
1904 : BuildSetEnd - pops the set value and type from the stack
1905 : and pushes the value,type pair.
1906 :
1907 : Entry Exit
1908 :
1909 : Ptr ->
1910 : +--------------+
1911 : | Set Value | <- Ptr
1912 : |--------------| +--------------+
1913 : | Set Type | | Value | Type |
1914 : |--------------| |--------------|
1915 : */
1916 :
1917 : extern "C" void M2Quads_BuildSetEnd (void);
1918 :
1919 : /*
1920 : BuildEmptySet - Builds an empty set on the stack.
1921 : The Stack:
1922 :
1923 : Entry Exit
1924 :
1925 : <- Ptr
1926 : +-------------+
1927 : Ptr -> | Value |
1928 : +-----------+ |-------------|
1929 : | SetType | | SetType |
1930 : |-----------| |-------------|
1931 :
1932 : tokpos points to the opening '{'.
1933 : */
1934 :
1935 : extern "C" void M2Quads_BuildEmptySet (unsigned int tokpos);
1936 :
1937 : /*
1938 : BuildInclRange - includes a set range with a set.
1939 :
1940 :
1941 : Entry Exit
1942 : ===== ====
1943 :
1944 :
1945 : Ptr ->
1946 : +------------+
1947 : | El2 |
1948 : |------------|
1949 : | El1 | <- Ptr
1950 : |------------| +-------------------+
1951 : | Set Value | | Value + {El1..El2}|
1952 : |------------| |-------------------|
1953 :
1954 : No quadruples produced as the range info is contained within
1955 : the set value.
1956 : */
1957 :
1958 : extern "C" void M2Quads_BuildInclRange (void);
1959 :
1960 : /*
1961 : BuildInclBit - includes a bit into the set.
1962 :
1963 : Entry Exit
1964 : ===== ====
1965 :
1966 :
1967 : Ptr ->
1968 : +------------+
1969 : | Element | <- Ptr
1970 : |------------| +------------+
1971 : | Value | | Value |
1972 : |------------| |------------|
1973 :
1974 : */
1975 :
1976 : extern "C" void M2Quads_BuildInclBit (void);
1977 :
1978 : /*
1979 : SilentBuildConstructor - places NulSym into the constructor fifo queue.
1980 : */
1981 :
1982 : extern "C" void M2Quads_SilentBuildConstructor (void);
1983 :
1984 : /*
1985 : SilentBuildConstructorStart - removes an entry from the constructor fifo queue.
1986 : */
1987 :
1988 : extern "C" void M2Quads_SilentBuildConstructorStart (void);
1989 :
1990 : /*
1991 : BuildConstructor - builds a constructor.
1992 : Stack
1993 :
1994 : Entry Exit
1995 :
1996 : Ptr ->
1997 : +------------+
1998 : | Type | <- Ptr
1999 : |------------+
2000 : */
2001 :
2002 : extern "C" void M2Quads_BuildConstructor (unsigned int tokcbrpos);
2003 :
2004 : /*
2005 : BuildConstructorStart - builds a constructor.
2006 : Stack
2007 :
2008 : Entry Exit
2009 :
2010 : Ptr -> <- Ptr
2011 : +------------+ +----------------+
2012 : | Type | | ConstructorSym |
2013 : |------------+ |----------------|
2014 : */
2015 :
2016 : extern "C" void M2Quads_BuildConstructorStart (unsigned int cbratokpos);
2017 :
2018 : /*
2019 : BuildConstructorEnd - removes the current constructor frame from the
2020 : constructor stack (it does not effect the quad
2021 : stack)
2022 :
2023 : Entry Exit
2024 :
2025 : Ptr -> <- Ptr
2026 : +------------+ +------------+
2027 : | const | | const |
2028 : |------------| |------------|
2029 :
2030 : startpos is the start of the constructor, either the typename or '{'
2031 : cbratokpos is the '}'.
2032 : */
2033 :
2034 : extern "C" void M2Quads_BuildConstructorEnd (unsigned int startpos, unsigned int cbratokpos);
2035 :
2036 : /*
2037 : NextConstructorField - increments the top of constructor stacks index by one.
2038 : */
2039 :
2040 : extern "C" void M2Quads_NextConstructorField (void);
2041 :
2042 : /*
2043 : BuildTypeForConstructor - pushes the type implied by the current constructor.
2044 : If no constructor is currently being built then
2045 : it Pushes a Bitset type.
2046 : */
2047 :
2048 : extern "C" void M2Quads_BuildTypeForConstructor (unsigned int tokpos);
2049 :
2050 : /*
2051 : BuildComponentValue - builds a component value.
2052 :
2053 : Entry Exit
2054 :
2055 : Ptr -> <- Ptr
2056 :
2057 :
2058 : +------------+ +------------+
2059 : | const | | const |
2060 : |------------| |------------|
2061 : */
2062 :
2063 : extern "C" void M2Quads_BuildComponentValue (void);
2064 :
2065 : /*
2066 : PopConstructor - removes the top constructor from the top of stack.
2067 : */
2068 :
2069 : extern "C" void M2Quads_PopConstructor (void);
2070 :
2071 : /*
2072 : BuildNot - Builds a NOT operation from the quad stack.
2073 : The Stack is expected to contain:
2074 :
2075 :
2076 : Entry Exit
2077 : ===== ====
2078 :
2079 : Ptr -> <- Ptr
2080 : +------------+ +------------+
2081 : | t | f | | f | t |
2082 : |------------| |------------|
2083 : */
2084 :
2085 : extern "C" void M2Quads_BuildNot (unsigned int notTokPos);
2086 :
2087 : /*
2088 : RecordOp - Records the operator passed on the stack.
2089 : This is called when a boolean operator is found in an
2090 : expression. It is called just after the lhs has been built
2091 : and pushed to the quad stack and prior to the rhs build.
2092 : It checks to see if AND OR or equality tests are required.
2093 : It will short circuit AND and OR expressions. It also
2094 : converts a lhs to a boolean variable if an xor comparison
2095 : is about to be performed.
2096 :
2097 : Checks for AND operator or OR operator
2098 : if either of these operators are found then BackPatching
2099 : takes place.
2100 : The Expected Stack:
2101 :
2102 : Entry Exit
2103 :
2104 : Ptr -> <- Ptr
2105 : +-------------+ +-------------+
2106 : | OperatorTok | | OperatorTok |
2107 : |-------------| |-------------|
2108 : | t | f | | t | f |
2109 : |-------------| |-------------|
2110 :
2111 :
2112 : If OperatorTok=AndTok
2113 : Then
2114 : BackPatch(f, NextQuad)
2115 : Elsif OperatorTok=OrTok
2116 : Then
2117 : BackPatch(t, NextQuad)
2118 : End
2119 : */
2120 :
2121 : extern "C" void M2Quads_RecordOp (void);
2122 :
2123 : /*
2124 : BuildRelOp - Builds a relative operation from the quad stack.
2125 : The Stack is expected to contain:
2126 :
2127 :
2128 : Entry Exit
2129 : ===== ====
2130 :
2131 : Ptr ->
2132 : +------------+
2133 : | e1 |
2134 : |------------| <- Ptr
2135 : | Operator |
2136 : |------------| +------------+
2137 : | e2 | | t | f |
2138 : |------------| |------------|
2139 :
2140 :
2141 : Quadruples Produced
2142 :
2143 : q IFOperator e2 e1 TrueExit ; e2 e1 since
2144 : q+1 GotoOp FalseExit ; relation > etc
2145 : ; requires order.
2146 : */
2147 :
2148 : extern "C" void M2Quads_BuildRelOp (unsigned int optokpos);
2149 :
2150 : /*
2151 : BuildBinaryOp - Builds a binary operation from the quad stack.
2152 : Be aware that this procedure will check for
2153 : the overloading of the bitset operators + - \ *.
2154 : So do NOT call this procedure if you are building
2155 : a reference to an array which has a bitset type or
2156 : the address arithmetic will be wrongly coersed into
2157 : logical ORs.
2158 :
2159 : The Stack is expected to contain:
2160 :
2161 :
2162 : Entry Exit
2163 : ===== ====
2164 :
2165 : Ptr ->
2166 : +------------+
2167 : | Sym1 |
2168 : |------------|
2169 : | Operator | <- Ptr
2170 : |------------| +------------+
2171 : | Sym2 | | Temporary |
2172 : |------------| |------------|
2173 :
2174 :
2175 : Quadruples Produced
2176 :
2177 : q Operator Temporary Sym1 Sym2
2178 :
2179 :
2180 : OR
2181 :
2182 :
2183 : Entry Exit
2184 : ===== ====
2185 :
2186 : Ptr ->
2187 : +------------+
2188 : | T1 | F1 |
2189 : |------------|
2190 : | OrTok | <- Ptr
2191 : |------------| +------------+
2192 : | T2 | F2 | | T1+T2| F1 |
2193 : |------------| |------------|
2194 :
2195 :
2196 : Quadruples Produced
2197 :
2198 : */
2199 :
2200 : extern "C" void M2Quads_BuildBinaryOp (void);
2201 :
2202 : /*
2203 : BuildUnaryOp - Builds a unary operation from the quad stack.
2204 : The Stack is expected to contain:
2205 :
2206 :
2207 : Entry Exit
2208 : ===== ====
2209 :
2210 : Ptr ->
2211 : +------------+
2212 : | Sym |
2213 : |------------| +------------+
2214 : | Operator | | Temporary | <- Ptr
2215 : |------------| |------------|
2216 :
2217 :
2218 : Quadruples Produced
2219 :
2220 : q Operator Temporary _ Sym
2221 :
2222 : */
2223 :
2224 : extern "C" void M2Quads_BuildUnaryOp (void);
2225 :
2226 : /*
2227 : OperandT - returns the ident operand stored in the true position on the boolean stack.
2228 : */
2229 :
2230 : extern "C" unsigned int M2Quads_OperandT (unsigned int pos);
2231 :
2232 : /*
2233 : OperandF - returns the ident operand stored in the false position on the boolean stack.
2234 : */
2235 :
2236 : extern "C" unsigned int M2Quads_OperandF (unsigned int pos);
2237 :
2238 : /*
2239 : PushTF - Push a True and False numbers onto the True/False stack.
2240 : True and False are assumed to contain Symbols or Ident etc.
2241 : */
2242 :
2243 : extern "C" void M2Quads_PushTF (unsigned int True, unsigned int False);
2244 :
2245 : /*
2246 : PopTF - Pop a True and False number from the True/False stack.
2247 : True and False are assumed to contain Symbols or Ident etc.
2248 : */
2249 :
2250 : extern "C" void M2Quads_PopTF (unsigned int *True, unsigned int *False);
2251 :
2252 : /*
2253 : PushT - Push an item onto the stack in the T (true) position.
2254 : */
2255 :
2256 : extern "C" void M2Quads_PushT (unsigned int True);
2257 :
2258 : /*
2259 : PopT - Pops the T value from the stack.
2260 : */
2261 :
2262 : extern "C" void M2Quads_PopT (unsigned int *True);
2263 :
2264 : /*
2265 : PushTtok - Push an item onto the stack in the T (true) position,
2266 : it is assummed to be a token and its token location is recorded.
2267 : */
2268 :
2269 : extern "C" void M2Quads_PushTtok (unsigned int True, unsigned int tokno);
2270 :
2271 : /*
2272 : PushTFtok - Push an item onto the stack in the T (true) position,
2273 : it is assummed to be a token and its token location is recorded.
2274 : */
2275 :
2276 : extern "C" void M2Quads_PushTFtok (unsigned int True, unsigned int False, unsigned int tokno);
2277 :
2278 : /*
2279 : PopTFtok - Pop T/F/tok from the stack.
2280 : */
2281 :
2282 : extern "C" void M2Quads_PopTFtok (unsigned int *True, unsigned int *False, unsigned int *tokno);
2283 :
2284 : /*
2285 : PushTFAtok - Push T/F/A/tok to the stack.
2286 : */
2287 :
2288 : extern "C" void M2Quads_PushTFAtok (unsigned int True, unsigned int False, unsigned int Array, unsigned int tokno);
2289 :
2290 : /*
2291 : PopTtok - Pops the T value from the stack and token position.
2292 : */
2293 :
2294 : extern "C" void M2Quads_PopTtok (unsigned int *True, unsigned int *tok);
2295 :
2296 : /*
2297 : PushTFn - Push a True and False numbers onto the True/False stack.
2298 : True and False are assumed to contain Symbols or Ident etc.
2299 : */
2300 :
2301 : extern "C" void M2Quads_PushTFn (unsigned int True, unsigned int False, unsigned int n);
2302 :
2303 : /*
2304 : PushTFntok - Push a True and False numbers onto the True/False stack.
2305 : True and False are assumed to contain Symbols or Ident etc.
2306 : */
2307 :
2308 : extern "C" void M2Quads_PushTFntok (unsigned int True, unsigned int False, unsigned int n, unsigned int tokno);
2309 :
2310 : /*
2311 : PopTFn - Pop a True and False number from the True/False stack.
2312 : True and False are assumed to contain Symbols or Ident etc.
2313 : */
2314 :
2315 : extern "C" void M2Quads_PopTFn (unsigned int *True, unsigned int *False, unsigned int *n);
2316 :
2317 : /*
2318 : PopNothing - pops the top element on the boolean stack.
2319 : */
2320 :
2321 : extern "C" void M2Quads_PopNothing (void);
2322 :
2323 : /*
2324 : PopN - pops multiple elements from the BoolStack.
2325 : */
2326 :
2327 : extern "C" void M2Quads_PopN (unsigned int n);
2328 :
2329 : /*
2330 : PushTFA - Push True, False, Array, numbers onto the
2331 : True/False stack. True and False are assumed to
2332 : contain Symbols or Ident etc.
2333 : */
2334 :
2335 : extern "C" void M2Quads_PushTFA (unsigned int True, unsigned int False, unsigned int Array);
2336 :
2337 : /*
2338 : OperandTok - returns the token associated with pos, on the stack.
2339 : */
2340 :
2341 : extern "C" unsigned int M2Quads_OperandTok (unsigned int pos);
2342 :
2343 : /*
2344 : OperandA - returns possible array symbol associated with the ident
2345 : operand stored on the boolean stack.
2346 : */
2347 :
2348 : extern "C" unsigned int M2Quads_OperandA (unsigned int pos);
2349 :
2350 : /*
2351 : OperandAnno - returns the annotation string associated with the
2352 : position, n, on the stack.
2353 : */
2354 :
2355 : extern "C" DynamicStrings_String M2Quads_OperandAnno (unsigned int n);
2356 :
2357 : /*
2358 : Annotate - annotate the top of stack.
2359 : */
2360 :
2361 : extern "C" void M2Quads_Annotate (const char *a_, unsigned int _a_high);
2362 :
2363 : /*
2364 : DisplayStack - displays the compile time symbol stack.
2365 : */
2366 :
2367 : extern "C" void M2Quads_DisplayStack (void);
2368 :
2369 : /*
2370 : Top - returns the no of items held in the stack.
2371 : */
2372 :
2373 : extern "C" unsigned int M2Quads_Top (void);
2374 :
2375 : /*
2376 : DupFrame - duplicate the top of stack and push the new frame.
2377 : */
2378 :
2379 : extern "C" void M2Quads_DupFrame (void);
2380 :
2381 : /*
2382 : WriteOperand - displays the operands name, symbol id and mode of addressing.
2383 : */
2384 :
2385 : extern "C" void M2Quads_WriteOperand (unsigned int Sym);
2386 :
2387 : /*
2388 : BeginVarient - begin a varient record.
2389 : */
2390 :
2391 : extern "C" void M2Quads_BeginVarient (void);
2392 :
2393 : /*
2394 : EndVarient - end a varient record.
2395 : */
2396 :
2397 : extern "C" void M2Quads_EndVarient (void);
2398 :
2399 : /*
2400 : ElseVarient - associate an ELSE clause with a varient record.
2401 : */
2402 :
2403 : extern "C" void M2Quads_ElseVarient (void);
2404 :
2405 : /*
2406 : BeginVarientList - begin an ident list containing ranges belonging to a
2407 : varient list.
2408 : */
2409 :
2410 : extern "C" void M2Quads_BeginVarientList (void);
2411 :
2412 : /*
2413 : EndVarientList - end a range list for a varient field.
2414 : */
2415 :
2416 : extern "C" void M2Quads_EndVarientList (void);
2417 :
2418 : /*
2419 : AddRecordToList - adds the record held on the top of stack to the
2420 : list of records and varient fields.
2421 : */
2422 :
2423 : extern "C" void M2Quads_AddRecordToList (void);
2424 :
2425 : /*
2426 : AddVarientToList - adds varient held on the top of stack to the list.
2427 : */
2428 :
2429 : extern "C" void M2Quads_AddVarientToList (void);
2430 :
2431 : /*
2432 : AddVarientFieldToList - adds varient field, f, to the list of all varient
2433 : fields created.
2434 : */
2435 :
2436 : extern "C" void M2Quads_AddVarientFieldToList (unsigned int f);
2437 :
2438 : /*
2439 : AddVarientRange - creates a range from the top two contant expressions
2440 : on the stack which are recorded with the current
2441 : varient field. The stack is unaltered.
2442 : */
2443 :
2444 : extern "C" void M2Quads_AddVarientRange (void);
2445 :
2446 : /*
2447 : AddVarientEquality - adds the contant expression on the top of the stack
2448 : to the current varient field being recorded.
2449 : The stack is unaltered.
2450 : */
2451 :
2452 : extern "C" void M2Quads_AddVarientEquality (void);
2453 :
2454 : /*
2455 : BuildCodeOn - generates a quadruple declaring that code should be
2456 : emmitted from henceforth.
2457 :
2458 : The Stack is unnaffected.
2459 : */
2460 :
2461 : extern "C" void M2Quads_BuildCodeOn (void);
2462 :
2463 : /*
2464 : BuildCodeOff - generates a quadruple declaring that code should not be
2465 : emmitted from henceforth.
2466 :
2467 : The Stack is unnaffected.
2468 : */
2469 :
2470 : extern "C" void M2Quads_BuildCodeOff (void);
2471 :
2472 : /*
2473 : BuildProfileOn - generates a quadruple declaring that profile timings
2474 : should be emmitted from henceforth.
2475 :
2476 : The Stack is unnaffected.
2477 : */
2478 :
2479 : extern "C" void M2Quads_BuildProfileOn (void);
2480 : extern "C" void M2Quads_BuildProfileOff (void);
2481 :
2482 : /*
2483 : BuildOptimizeOn - generates a quadruple declaring that optimization
2484 : should occur from henceforth.
2485 :
2486 : The Stack is unnaffected.
2487 : */
2488 :
2489 : extern "C" void M2Quads_BuildOptimizeOn (void);
2490 :
2491 : /*
2492 : BuildOptimizeOff - generates a quadruple declaring that optimization
2493 : should not occur from henceforth.
2494 :
2495 : The Stack is unnaffected.
2496 : */
2497 :
2498 : extern "C" void M2Quads_BuildOptimizeOff (void);
2499 :
2500 : /*
2501 : BuildAsm - builds an Inline pseudo quadruple operator.
2502 : The inline interface, Sym, is stored as the operand
2503 : to the operator InlineOp.
2504 :
2505 : The stack is expected to contain:
2506 :
2507 :
2508 : Entry Exit
2509 : ===== ====
2510 :
2511 : Ptr ->
2512 : +--------------+
2513 : | Sym | Empty
2514 : |--------------|
2515 : */
2516 :
2517 : extern "C" void M2Quads_BuildAsm (unsigned int tok);
2518 :
2519 : /*
2520 : BuildLineNo - builds a LineNumberOp pseudo quadruple operator.
2521 : This quadruple indicates which source line has been
2522 : processed, these quadruples are only generated if we
2523 : are producing runtime debugging information.
2524 :
2525 : The stack is not affected, read or altered in any way.
2526 :
2527 :
2528 : Entry Exit
2529 : ===== ====
2530 :
2531 : Ptr -> <- Ptr
2532 : */
2533 :
2534 : extern "C" void M2Quads_BuildLineNo (void);
2535 :
2536 : /*
2537 : PushLineNo - pushes the current file and line number to the stack.
2538 : */
2539 :
2540 : extern "C" void M2Quads_PushLineNo (void);
2541 :
2542 : /*
2543 : BuildStmtNote - builds a StatementNoteOp pseudo quadruple operator.
2544 : This quadruple indicates which source line has been
2545 : processed and it represents the start of a statement
2546 : sequence.
2547 : It differs from LineNumberOp in that multiple successive
2548 : LineNumberOps will be removed and the final one is attached to
2549 : the next real GCC tree. Whereas a StatementNoteOp is always left
2550 : alone. Depending upon the debugging level it will issue a nop
2551 : instruction to ensure that the gdb single step will step into
2552 : this line. Practically it allows pedalogical debugging to
2553 : occur when there is syntax sugar such as:
2554 :
2555 :
2556 : END step
2557 : END step
2558 : END ; step
2559 : a := 1 ; step
2560 :
2561 : REPEAT step
2562 : i := 1 step
2563 :
2564 : The stack is not affected, read or altered in any way.
2565 :
2566 :
2567 : Entry Exit
2568 : ===== ====
2569 :
2570 : Ptr -> <- Ptr
2571 : */
2572 :
2573 : extern "C" void M2Quads_BuildStmtNote (int offset);
2574 :
2575 : /*
2576 : LoopAnalysis - checks whether an infinite loop exists.
2577 : */
2578 :
2579 : extern "C" void M2Quads_LoopAnalysis (unsigned int Scope, unsigned int Current, unsigned int End);
2580 :
2581 : /*
2582 : ForLoopAnalysis - checks all the FOR loops for index variable manipulation
2583 : and dangerous usage outside the loop.
2584 : */
2585 :
2586 : extern "C" void M2Quads_ForLoopAnalysis (void);
2587 :
2588 : /*
2589 : BuildSizeCheckStart - switches off all quadruple generation if the function SIZE or HIGH
2590 : is being "called". This should be done as SIZE only requires the
2591 : actual type of the expression, not its value. Consider the problem of
2592 : SIZE(UninitializedPointer^) which is quite legal and it must
2593 : also be safe!
2594 : ISO Modula-2 also allows HIGH(a[0]) for a two dimensional array
2595 : and there is no need to compute a[0], we just need to follow the
2596 : type and count dimensions. However if SIZE(a) or HIGH(a) occurs
2597 : and, a, is an unbounded array then we turn on quadruple generation.
2598 :
2599 : The Stack is expected to contain:
2600 :
2601 :
2602 : Entry Exit
2603 : ===== ====
2604 :
2605 : Ptr -> <- Ptr
2606 : +----------------------+ +----------------------+
2607 : | ProcSym | Type | tok | | ProcSym | Type | tok |
2608 : |----------------------| |----------------------|
2609 : */
2610 :
2611 : extern "C" void M2Quads_BuildSizeCheckStart (void);
2612 :
2613 : /*
2614 : BackPatchSubrangesAndOptParam - runs through all the quadruples and finds SubrangeLow or SubrangeHigh
2615 : quadruples and replaces it by an assignment to the Low or High component
2616 : of the subrange type.
2617 :
2618 : Input:
2619 : SubrangeLow op1 op3 op3 is a subrange
2620 :
2621 : Output:
2622 : Becomes op1 low
2623 :
2624 : Input:
2625 : SubrangeHigh op1 op3 op3 is a subrange
2626 :
2627 : Output:
2628 : Becomes op1 high
2629 :
2630 : Input:
2631 : OptParam op1 op2 op3
2632 :
2633 : Output:
2634 : Param op1 op2 GetOptArgInit(op3)
2635 : */
2636 :
2637 : extern "C" void M2Quads_BackPatchSubrangesAndOptParam (void);
2638 :
2639 : /*
2640 : WriteOperator - writes the name of the quadruple operator.
2641 : */
2642 :
2643 : extern "C" void M2Quads_WriteOperator (M2Quads_QuadOperator Operator);
2644 :
2645 : /*
2646 : PushAutoOn - push the auto flag and then set it to TRUE.
2647 : Any call to ident in the parser will result in the token being pushed.
2648 : */
2649 :
2650 : extern "C" void M2Quads_PushAutoOn (void);
2651 :
2652 : /*
2653 : PushAutoOff - push the auto flag and then set it to FALSE.
2654 : */
2655 :
2656 : extern "C" void M2Quads_PushAutoOff (void);
2657 :
2658 : /*
2659 : IsAutoPushOn - returns the value of the current Auto ident push flag.
2660 : */
2661 :
2662 : extern "C" bool M2Quads_IsAutoPushOn (void);
2663 :
2664 : /*
2665 : PopAuto - restores the previous value of the Auto flag.
2666 : */
2667 :
2668 : extern "C" void M2Quads_PopAuto (void);
2669 :
2670 : /*
2671 : MustCheckOverflow - returns TRUE if the quadruple should test for overflow.
2672 : */
2673 :
2674 : extern "C" bool M2Quads_MustCheckOverflow (unsigned int q);
2675 :
2676 : /*
2677 : PushInConstExpression - push the InConstExpression flag and then set it to TRUE.
2678 : */
2679 :
2680 : extern "C" void M2Quads_PushInConstExpression (void);
2681 :
2682 : /*
2683 : PopInConstExpression - restores the previous value of the InConstExpression.
2684 : */
2685 :
2686 : extern "C" void M2Quads_PopInConstExpression (void);
2687 :
2688 : /*
2689 : IsInConstExpression - returns the value of the InConstExpression.
2690 : */
2691 :
2692 : extern "C" bool M2Quads_IsInConstExpression (void);
2693 :
2694 : /*
2695 : PushInConstParameters - push the InConstParameters flag and then set it to TRUE.
2696 : */
2697 :
2698 : extern "C" void M2Quads_PushInConstParameters (void);
2699 :
2700 : /*
2701 : PopInConstParameters - restores the previous value of the InConstParameters.
2702 : */
2703 :
2704 : extern "C" void M2Quads_PopInConstParameters (void);
2705 :
2706 : /*
2707 : IsInConstParameters - returns the value of the InConstParameters.
2708 : */
2709 :
2710 : extern "C" bool M2Quads_IsInConstParameters (void);
2711 :
2712 : /*
2713 : BuildAsmElement - the stack is expected to contain:
2714 :
2715 :
2716 : Entry Exit
2717 : ===== ====
2718 :
2719 : Ptr ->
2720 : +------------------+
2721 : | expr | tokpos |
2722 : |------------------|
2723 : | str |
2724 : |------------------|
2725 : | name |
2726 : |------------------| +------------------+
2727 : | CurrentInterface | | CurrentInterface |
2728 : |------------------| |------------------|
2729 : | CurrentAsm | | CurrentAsm |
2730 : |------------------| |------------------|
2731 : | n | | n |
2732 : |------------------| |------------------|
2733 : */
2734 :
2735 : extern "C" void M2Quads_BuildAsmElement (bool input, bool output);
2736 :
2737 : /*
2738 : BuildAsmTrash - the stack is expected to contain:
2739 :
2740 :
2741 : Entry Exit
2742 : ===== ====
2743 :
2744 : Ptr ->
2745 : +------------------+
2746 : | expr | tokpos |
2747 : |------------------| +------------------+
2748 : | CurrentInterface | | CurrentInterface |
2749 : |------------------| |------------------|
2750 : | CurrentAsm | | CurrentAsm |
2751 : |------------------| |------------------|
2752 : | n | | n |
2753 : |------------------| |------------------|
2754 : */
2755 :
2756 : extern "C" void M2Quads_BuildAsmTrash (void);
2757 :
2758 : /*
2759 : GetQuadTrash - return the symbol associated with the trashed operand.
2760 : */
2761 :
2762 : extern "C" unsigned int M2Quads_GetQuadTrash (unsigned int quad);
2763 :
2764 : /*
2765 : DSdbEnter -
2766 : */
2767 :
2768 : static void DSdbEnter (void);
2769 :
2770 : /*
2771 : DSdbExit -
2772 : */
2773 :
2774 : static void DSdbExit (void);
2775 :
2776 : /*
2777 : GetQF - returns the QuadFrame associated with, q.
2778 : */
2779 :
2780 : static M2Quads_QuadFrame GetQF (unsigned int q);
2781 :
2782 : /*
2783 : IsQuadA - returns true if QuadNo is a op.
2784 : */
2785 :
2786 : static bool IsQuadA (unsigned int QuadNo, M2Quads_QuadOperator op);
2787 :
2788 : /*
2789 : OpUsesOp1 - return TRUE if op allows op1.
2790 : */
2791 :
2792 : static bool OpUsesOp1 (M2Quads_QuadOperator op);
2793 :
2794 : /*
2795 : AddQuadInformation - adds variable analysis and jump analysis to the new quadruple.
2796 : */
2797 :
2798 : static void AddQuadInformation (unsigned int QuadNo, M2Quads_QuadOperator Op, unsigned int Oper1, unsigned int Oper2, unsigned int Oper3);
2799 :
2800 : /*
2801 : PutQuadO - alters a quadruple QuadNo with Op, Oper1, Oper2, Oper3, and
2802 : sets a boolean to determinine whether overflow should be checked.
2803 : */
2804 :
2805 : static void PutQuadO (unsigned int QuadNo, M2Quads_QuadOperator Op, unsigned int Oper1, unsigned int Oper2, unsigned int Oper3, bool overflow);
2806 :
2807 : /*
2808 : PutQuadOType -
2809 : */
2810 :
2811 : static void PutQuadOType (unsigned int QuadNo, M2Quads_QuadOperator Op, unsigned int Oper1, unsigned int Oper2, unsigned int Oper3, bool overflow, bool checktype);
2812 :
2813 : /*
2814 : UndoReadWriteInfo -
2815 : */
2816 :
2817 : static void UndoReadWriteInfo (unsigned int QuadNo, M2Quads_QuadOperator Op, unsigned int Oper1, unsigned int Oper2, unsigned int Oper3);
2818 :
2819 : /*
2820 : CheckAddTuple2Read - checks to see whether symbol tuple contains variables or
2821 : parameters and if so it then adds them to the quadruple
2822 : variable list.
2823 : */
2824 :
2825 : static void CheckAddTuple2Read (unsigned int tuple, bool canDereference, unsigned int Quad);
2826 :
2827 : /*
2828 : CheckAddVariableRead - checks to see whether symbol, Sym, is a variable or
2829 : a parameter and if so it then adds this quadruple
2830 : to the variable list.
2831 : */
2832 :
2833 : static void CheckAddVariableRead (unsigned int Sym, bool canDereference, unsigned int Quad);
2834 :
2835 : /*
2836 : CheckRemoveVariableRead - checks to see whether, Sym, is a variable or
2837 : a parameter and if so then it removes the
2838 : quadruple from the variable list.
2839 : */
2840 :
2841 : static void CheckRemoveVariableRead (unsigned int Sym, bool canDereference, unsigned int Quad);
2842 :
2843 : /*
2844 : CheckAddVariableWrite - checks to see whether symbol, Sym, is a variable and
2845 : if so it then adds this quadruple to the variable list.
2846 : */
2847 :
2848 : static void CheckAddVariableWrite (unsigned int Sym, bool canDereference, unsigned int Quad);
2849 :
2850 : /*
2851 : CheckRemoveVariableWrite - checks to see whether, Sym, is a variable and
2852 : if so then it removes the quadruple from the
2853 : variable list.
2854 : */
2855 :
2856 : static void CheckRemoveVariableWrite (unsigned int Sym, bool canDereference, unsigned int Quad);
2857 :
2858 : /*
2859 : CheckConst -
2860 : */
2861 :
2862 : static void CheckConst (unsigned int sym);
2863 :
2864 : /*
2865 : AlterReference - alters all references from OldQuad, to NewQuad in a
2866 : quadruple list Head.
2867 : */
2868 :
2869 : static void AlterReference (unsigned int Head, unsigned int OldQuad, unsigned int NewQuad);
2870 :
2871 : /*
2872 : GrowQuads - grows the list of quadruples to the quadruple, to.
2873 : */
2874 :
2875 : static void GrowQuads (unsigned int to);
2876 :
2877 : /*
2878 : ManipulateReference - manipulates the quadruple, q, so that it now points to quad, to.
2879 : */
2880 :
2881 : static void ManipulateReference (unsigned int q, unsigned int to);
2882 :
2883 : /*
2884 : RemoveReference - remove the reference by quadruple q to wherever
2885 : it was pointing.
2886 : */
2887 :
2888 : static void RemoveReference (unsigned int q);
2889 :
2890 : /*
2891 : NewQuad - sets QuadNo to a new quadruple.
2892 : */
2893 :
2894 : static void NewQuad (unsigned int *QuadNo);
2895 :
2896 : /*
2897 : CheckVariableAt - checks to see whether, sym, was declared at a particular address.
2898 : */
2899 :
2900 : static void CheckVariableAt (unsigned int sym);
2901 :
2902 : /*
2903 : CheckVariablesAt - checks to see whether we need to initialize any pointers
2904 : which point to variable declared at addresses.
2905 : */
2906 :
2907 : static void CheckVariablesAt (unsigned int scope);
2908 :
2909 : /*
2910 : GetTurnInterrupts - returns the TurnInterrupts procedure function.
2911 : */
2912 :
2913 : static unsigned int GetTurnInterrupts (unsigned int tok);
2914 :
2915 : /*
2916 : GetProtection - returns the PROTECTION data type.
2917 : */
2918 :
2919 : static unsigned int GetProtection (unsigned int tok);
2920 :
2921 : /*
2922 : CheckNeedPriorityBegin - checks to see whether we need to save the old
2923 : module priority and change to another module
2924 : priority.
2925 : The current module initialization or procedure
2926 : being built is defined by, scope. The module whose
2927 : priority will be used is defined by, module.
2928 : */
2929 :
2930 : static void CheckNeedPriorityBegin (unsigned int tok, unsigned int scope, unsigned int module);
2931 :
2932 : /*
2933 : CheckNeedPriorityEnd - checks to see whether we need to restore the old
2934 : module priority.
2935 : The current module initialization or procedure
2936 : being built is defined by, scope.
2937 : */
2938 :
2939 : static void CheckNeedPriorityEnd (unsigned int tok, unsigned int scope, unsigned int module);
2940 :
2941 : /*
2942 : BuildRTExceptEnter - informs RTExceptions that we are about to enter the except state.
2943 : */
2944 :
2945 : static void BuildRTExceptEnter (unsigned int tok);
2946 :
2947 : /*
2948 : BuildRTExceptLeave - informs RTExceptions that we are about to leave the except state.
2949 : If, destroy, is TRUE then pop the ExceptStack.
2950 : */
2951 :
2952 : static void BuildRTExceptLeave (unsigned int tok, bool destroy);
2953 :
2954 : /*
2955 : SafeRequestSym - only used during scaffold to get argc, argv, envp.
2956 : It attempts to get symbol name from the current scope(s) and if
2957 : it fails then it falls back onto default constants.
2958 : */
2959 :
2960 : static unsigned int SafeRequestSym (unsigned int tok, NameKey_Name name);
2961 :
2962 : /*
2963 : callRequestDependant - create a call:
2964 : RequestDependant (GetSymName (modulesym), GetLibName (modulesym),
2965 : GetSymName (depModuleSym), GetLibName (depModuleSym));
2966 : */
2967 :
2968 : static void callRequestDependant (unsigned int tokno, unsigned int moduleSym, unsigned int depModuleSym, unsigned int requestDep);
2969 :
2970 : /*
2971 : ForeachImportInDepDo -
2972 : */
2973 :
2974 : static void ForeachImportInDepDo (Lists_List importStatements, unsigned int moduleSym, unsigned int requestDep);
2975 :
2976 : /*
2977 : ForeachImportedModuleDo -
2978 : */
2979 :
2980 : static void ForeachImportedModuleDo (unsigned int moduleSym, unsigned int requestDep);
2981 :
2982 : /*
2983 : BuildM2DepFunction - creates the dependency graph procedure using IR:
2984 : static void
2985 : dependencies (void)
2986 : {
2987 : M2RTS_RequestDependant (module_name, libname, "b", "b libname");
2988 : M2RTS_RequestDependant (module_name, libname, NULL, NULL);
2989 : }
2990 : */
2991 :
2992 : static void BuildM2DepFunction (unsigned int tokno, unsigned int moduleSym);
2993 :
2994 : /*
2995 : BuildM2LinkFunction - creates the _M2_link procedure which will
2996 : cause the linker to pull in all the module ctors.
2997 : */
2998 :
2999 : static void BuildM2LinkFunction (unsigned int tokno);
3000 :
3001 : /*
3002 : BuildTry - build the try statement for main.
3003 : */
3004 :
3005 : static void BuildTry (unsigned int tokno);
3006 :
3007 : /*
3008 : BuildExcept - build the except block for main.
3009 : */
3010 :
3011 : static void BuildExcept (unsigned int tokno);
3012 :
3013 : /*
3014 : BuildM2MainFunction - creates the main function with appropriate calls to the scaffold.
3015 : */
3016 :
3017 : static void BuildM2MainFunction (unsigned int tokno);
3018 :
3019 : /*
3020 : DeferMakeConstStringCnul - return a C const string which will be nul terminated.
3021 : */
3022 :
3023 : static unsigned int DeferMakeConstStringCnul (unsigned int tok, unsigned int sym);
3024 :
3025 : /*
3026 : DeferMakeConstStringM2nul - return a const string which will be nul terminated.
3027 : */
3028 :
3029 : static unsigned int DeferMakeConstStringM2nul (unsigned int tok, unsigned int sym);
3030 :
3031 : /*
3032 : BuildStringAdrParam - push the address of a nul terminated string onto the quad stack.
3033 : */
3034 :
3035 : static void BuildStringAdrParam (unsigned int tok, NameKey_Name name);
3036 :
3037 : /*
3038 : BuildM2InitFunction -
3039 : */
3040 :
3041 : static void BuildM2InitFunction (unsigned int tok, unsigned int moduleSym);
3042 :
3043 : /*
3044 : BuildM2FiniFunction -
3045 : */
3046 :
3047 : static void BuildM2FiniFunction (unsigned int tok, unsigned int moduleSym);
3048 :
3049 : /*
3050 : BuildM2CtorFunction - create a constructor function associated with moduleSym.
3051 :
3052 : void
3053 : ctorFunction ()
3054 : {
3055 : M2RTS_RegisterModule (GetSymName (moduleSym), GetLibName (moduleSym),
3056 : init, fini, dependencies);
3057 : }
3058 : */
3059 :
3060 : static void BuildM2CtorFunction (unsigned int tok, unsigned int moduleSym);
3061 :
3062 : /*
3063 : AddForInfo - adds the description of the FOR loop into the record list.
3064 : This is used if -pedantic is turned on to check index variable
3065 : usage.
3066 : */
3067 :
3068 : static void AddForInfo (unsigned int Start, unsigned int End, unsigned int IncQuad, unsigned int Sym, unsigned int idtok);
3069 :
3070 : /*
3071 : CheckForIndex - checks the quadruples: Start..End to see whether a
3072 : for loop index is manipulated by the programmer.
3073 : It generates a warning if this is the case.
3074 : It also checks to see whether the IndexSym is read
3075 : immediately outside the loop in which case a warning
3076 : is issued.
3077 : */
3078 :
3079 : static void CheckForIndex (M2Quads_ForLoopInfo forDesc);
3080 :
3081 : /*
3082 : BuildRange - generates a RangeCheckOp quad with, r, as its operand.
3083 : */
3084 :
3085 : static void BuildRange (unsigned int r);
3086 :
3087 : /*
3088 : BuildError - generates a ErrorOp quad, indicating that if this
3089 : quadruple is reachable, then a runtime error would
3090 : occur.
3091 : */
3092 :
3093 : static void BuildError (unsigned int r);
3094 :
3095 : /*
3096 : CheckPointerThroughNil - builds a range quadruple, providing, sym, is
3097 : a candidate for checking against NIL.
3098 : This range quadruple is only expanded into
3099 : code during the code generation phase
3100 : thus allowing limited compile time checking.
3101 : */
3102 :
3103 : static void CheckPointerThroughNil (unsigned int tokpos, unsigned int sym);
3104 :
3105 : /*
3106 : CollectLow - returns the low of the subrange value.
3107 : */
3108 :
3109 : static unsigned int CollectLow (unsigned int sym);
3110 :
3111 : /*
3112 : CollectHigh - returns the high of the subrange value, sym.
3113 : */
3114 :
3115 : static unsigned int CollectHigh (unsigned int sym);
3116 :
3117 : /*
3118 : CheckCompatibleWithBecomes - checks to see that symbol, sym, is
3119 : compatible with the := operator.
3120 : */
3121 :
3122 : static void CheckCompatibleWithBecomes (unsigned int des, unsigned int expr, unsigned int destok, unsigned int exprtok);
3123 :
3124 : /*
3125 : BuildAssignmentWithoutBounds - calls BuildAssignment but makes sure we do not
3126 : check bounds.
3127 : */
3128 :
3129 : static void BuildAssignmentWithoutBounds (unsigned int tok, bool checkTypes, bool checkOverflow);
3130 :
3131 : /*
3132 : MarkArrayWritten - marks, Array, as being written.
3133 : */
3134 :
3135 : static void MarkArrayWritten (unsigned int Array);
3136 :
3137 : /*
3138 : MarkAsReadWrite - marks the variable or parameter as being
3139 : read/write.
3140 : */
3141 :
3142 : static void MarkAsReadWrite (unsigned int sym);
3143 :
3144 : /*
3145 : MarkAsRead - marks the variable or parameter as being read.
3146 : */
3147 :
3148 : static void MarkAsRead (unsigned int sym);
3149 :
3150 : /*
3151 : MarkAsWrite - marks the variable or parameter as being written.
3152 : */
3153 :
3154 : static void MarkAsWrite (unsigned int sym);
3155 :
3156 : /*
3157 : doVal - return an expression which is VAL(type, expr). If
3158 : expr is a constant then return expr.
3159 : */
3160 :
3161 : static unsigned int doVal (unsigned int type, unsigned int expr);
3162 :
3163 : /*
3164 : MoveWithMode -
3165 : */
3166 :
3167 : static void MoveWithMode (unsigned int tokno, unsigned int Des, unsigned int Exp, unsigned int Array, unsigned int destok, unsigned int exptok, bool checkOverflow);
3168 :
3169 : /*
3170 : CheckBecomesMeta - checks to make sure that we are not
3171 : assigning a variable to a constant.
3172 : Also check we are not assigning to an
3173 : unbounded array.
3174 : */
3175 :
3176 : static void CheckBecomesMeta (unsigned int Des, unsigned int Exp, unsigned int combinedtok, unsigned int destok, unsigned int exprtok);
3177 :
3178 : /*
3179 : BuildAssignmentBoolean - build the quadruples for a boolean variable or constant
3180 : which will be assigned to the result of a boolean expression.
3181 : For example:
3182 :
3183 : foo := a = b ;
3184 : foo := a IN b ;
3185 :
3186 : The boolean result is contained in the control flow
3187 : the true value will emerge from the quad path t.
3188 : The false value will emerge from the quad path f.
3189 : This procedure terminates both paths by backpatching
3190 : and assigns TRUE or FALSE to the variable/constant.
3191 : A variable maybe an L value so it will require dereferencing.
3192 : */
3193 :
3194 : static void BuildAssignmentBoolean (unsigned int becomesTokNo, bool checkOverflow, unsigned int t, unsigned int f, unsigned int Des, unsigned int destok);
3195 :
3196 : /*
3197 : doBuildAssignment - subsiduary procedure of BuildAssignment.
3198 : It builds the assignment and optionally
3199 : checks the types are compatible.
3200 : */
3201 :
3202 : static void doBuildAssignment (unsigned int becomesTokNo, bool checkTypes, bool checkOverflow);
3203 :
3204 : /*
3205 : CheckAssignCompatible - checks to see that an assignment is compatible.
3206 : It performs limited checking - thorough checking
3207 : is done in pass 3. But we do what we can here
3208 : given knowledge so far.
3209 : */
3210 :
3211 : static void CheckAssignCompatible (unsigned int Des, unsigned int Exp, unsigned int combinedtok, unsigned int destok, unsigned int exprtok);
3212 :
3213 : /*
3214 : CheckBooleanId - Checks to see if the top operand is a boolean.
3215 : If the operand is not a boolean then it is tested
3216 : with true and a boolean is generated.
3217 : The Stack:
3218 :
3219 :
3220 : Entry Exit
3221 : Ptr -> <- Ptr
3222 : +------------+ +------------+
3223 : | Sym | | t | f |
3224 : |------------| |------------|
3225 :
3226 : Quadruples
3227 :
3228 : q If= Sym True _
3229 : q+1 GotoOp _ _ _
3230 : */
3231 :
3232 : static void CheckBooleanId (void);
3233 :
3234 : /*
3235 : PushOne - pushes the value one to the stack.
3236 : The Stack is changed:
3237 :
3238 :
3239 : Entry Exit
3240 : ===== ====
3241 :
3242 : <- Ptr
3243 : +------------+
3244 : Ptr -> | 1 | type |
3245 : |------------|
3246 : */
3247 :
3248 : static void PushOne (unsigned int tok, unsigned int type, const char *message_, unsigned int _message_high);
3249 :
3250 : /*
3251 : PushZero - pushes the value zero to the stack.
3252 : The Stack is changed:
3253 :
3254 :
3255 : Entry Exit
3256 : ===== ====
3257 :
3258 : <- Ptr
3259 : +------------+
3260 : Ptr -> | 0 | type |
3261 : |------------|
3262 : */
3263 :
3264 : static void PushZero (unsigned int tok, unsigned int type);
3265 :
3266 : /*
3267 : ForLoopLastIterator - calculate the last iterator value but avoid setting
3268 : LastIterator twice if it is a constant (in the quads).
3269 : In the ForLoopLastIteratorVariable case only one
3270 : path will be chosen but at the time of quadruple
3271 : generation we do not know the value of BySym.
3272 : */
3273 :
3274 : static void ForLoopLastIterator (unsigned int LastIterator, unsigned int e1, unsigned int e2, unsigned int BySym, unsigned int e1tok, unsigned int e2tok, unsigned int bytok);
3275 :
3276 : /*
3277 : BuildSizeCheckEnd - checks to see whether the function "called" was in fact SIZE.
3278 : If so then we restore quadruple generation.
3279 : */
3280 :
3281 : static void BuildSizeCheckEnd (unsigned int ProcSym);
3282 :
3283 : /*
3284 : BuildRealProcedureCall - builds a real procedure call.
3285 : The Stack:
3286 :
3287 :
3288 : Entry Exit
3289 :
3290 : Ptr ->
3291 : +----------------+
3292 : | NoOfParam |
3293 : |----------------|
3294 : | Param 1 |
3295 : |----------------|
3296 : | Param 2 |
3297 : |----------------|
3298 : . .
3299 : . .
3300 : . .
3301 : |----------------|
3302 : | Param # |
3303 : |----------------|
3304 : | ProcSym | Type | Empty
3305 : |----------------|
3306 : */
3307 :
3308 : static void BuildRealProcedureCall (unsigned int tokno);
3309 :
3310 : /*
3311 : BuildRealFuncProcCall - builds a real procedure or function call.
3312 : The Stack:
3313 :
3314 :
3315 : Entry Exit
3316 :
3317 : Ptr ->
3318 : +----------------+
3319 : | NoOfParam |
3320 : |----------------|
3321 : | Param 1 |
3322 : |----------------|
3323 : | Param 2 |
3324 : |----------------|
3325 : . .
3326 : . .
3327 : . .
3328 : |----------------|
3329 : | Param # |
3330 : |----------------|
3331 : | ProcSym | Type | Empty
3332 : |----------------|
3333 : */
3334 :
3335 : static void BuildRealFuncProcCall (unsigned int tokno, bool IsFunc, bool IsForC, bool ConstExpr);
3336 :
3337 : /*
3338 : CheckProcedureParameters - Checks the parameters which are being passed to
3339 : procedure ProcSym.
3340 :
3341 : The Stack:
3342 :
3343 :
3344 : Entry Exit
3345 :
3346 : Ptr -> <- Ptr
3347 : +----------------+ +----------------+
3348 : | NoOfParam | | NoOfParam |
3349 : |----------------| |----------------|
3350 : | Param 1 | | Param 1 |
3351 : |----------------| |----------------|
3352 : | Param 2 | | Param 2 |
3353 : |----------------| |----------------|
3354 : . . . .
3355 : . . . .
3356 : . . . .
3357 : |----------------| |----------------|
3358 : | Param # | | Param # |
3359 : |----------------| |----------------|
3360 : | ProcSym | Type | | ProcSym | Type |
3361 : |----------------| |----------------|
3362 :
3363 : */
3364 :
3365 : static void CheckProcedureParameters (bool IsForC);
3366 :
3367 : /*
3368 : CheckProcTypeAndProcedure - checks the ProcType with the call.
3369 : */
3370 :
3371 : static void CheckProcTypeAndProcedure (unsigned int tokno, unsigned int ProcType, unsigned int call, unsigned int ParamCheckId);
3372 :
3373 : /*
3374 : IsReallyPointer - returns TRUE is sym is a pointer, address or a type declared
3375 : as a pointer or address.
3376 : */
3377 :
3378 : static bool IsReallyPointer (unsigned int Sym);
3379 :
3380 : /*
3381 : LegalUnboundedParam - returns TRUE if the parameter, Actual, can legitimately be
3382 : passed to ProcSym, i, the, Formal, parameter.
3383 : */
3384 :
3385 : static bool LegalUnboundedParam (unsigned int tokpos, unsigned int ProcSym, unsigned int i, unsigned int ActualType, unsigned int Actual, unsigned int Dimension, unsigned int Formal);
3386 :
3387 : /*
3388 : CheckParameter - checks that types ActualType and FormalType are compatible for parameter
3389 : passing. ProcSym is the procedure and i is the parameter number.
3390 :
3391 : We obey the following rules:
3392 :
3393 : (1) we allow WORD, BYTE, LOC to be compitable with any like sized
3394 : type.
3395 : (2) we allow ADDRESS to be compatible with any pointer type.
3396 : (3) we relax INTEGER and CARDINAL checking for Temporary variables.
3397 :
3398 : Note that type sizes are checked during the code generation pass.
3399 : */
3400 :
3401 : static void CheckParameter (unsigned int tokpos, unsigned int Actual, unsigned int Dimension, unsigned int Formal, unsigned int ProcSym, unsigned int i, Lists_List TypeList, unsigned int ParamCheckId);
3402 :
3403 : /*
3404 : DescribeType - returns a String describing a symbol, Sym, name and its type.
3405 : */
3406 :
3407 : static DynamicStrings_String DescribeType (unsigned int Sym);
3408 :
3409 : /*
3410 : FailParameter - generates an error message indicating that a parameter
3411 : declaration has failed.
3412 :
3413 : The parameters are:
3414 :
3415 : CurrentState - string describing the current failing state.
3416 : Actual - actual parameter.
3417 : ParameterNo - parameter number that has failed.
3418 : ProcedureSym - procedure symbol where parameter has failed.
3419 :
3420 : If any parameter is Nul then it is ignored.
3421 : */
3422 :
3423 : static void FailParameter (unsigned int tokpos, const char *CurrentState_, unsigned int _CurrentState_high, unsigned int Actual, unsigned int ProcedureSym, unsigned int ParameterNo);
3424 :
3425 : /*
3426 : WarnParameter - generates a warning message indicating that a parameter
3427 : use might cause problems on another target.
3428 :
3429 : CurrentState - string describing the current failing state.
3430 : Actual - actual parameter.
3431 : ParameterNo - parameter number that has failed.
3432 : ProcedureSym - procedure symbol where parameter has failed.
3433 :
3434 : If any parameter is Nul then it is ignored.
3435 : */
3436 :
3437 : static void WarnParameter (unsigned int tokpos, const char *CurrentState_, unsigned int _CurrentState_high, unsigned int Actual, unsigned int ProcedureSym, unsigned int ParameterNo);
3438 :
3439 : /*
3440 : doIndrX - perform des = *exp with a conversion if necessary.
3441 : */
3442 :
3443 : static void doIndrX (unsigned int tok, unsigned int des, unsigned int exp);
3444 :
3445 : /*
3446 : MakeRightValue - returns a temporary which will have the RightValue of symbol, Sym.
3447 : If Sym is a right value and has type, type, then no quadruples are
3448 : generated and Sym is returned. Otherwise a new temporary is created
3449 : and an IndrX quadruple is generated.
3450 : */
3451 :
3452 : static unsigned int MakeRightValue (unsigned int tok, unsigned int Sym, unsigned int type);
3453 :
3454 : /*
3455 : MakeLeftValue - returns a temporary coresponding to the LeftValue of
3456 : symbol, Sym. No quadruple is generated if Sym is already
3457 : a LeftValue and has the same type.
3458 : */
3459 :
3460 : static unsigned int MakeLeftValue (unsigned int tok, unsigned int Sym, SymbolTable_ModeOfAddr with, unsigned int type);
3461 :
3462 : /*
3463 : ManipulatePseudoCallParameters - manipulates the parameters to a pseudo function or
3464 : procedure. It dereferences all LeftValue parameters
3465 : and Boolean parameters.
3466 : The Stack:
3467 :
3468 :
3469 : Entry Exit
3470 :
3471 : Ptr -> exactly the same
3472 : +----------------+
3473 : | NoOfParameters |
3474 : |----------------|
3475 : | Param 1 |
3476 : |----------------|
3477 : | Param 2 |
3478 : |----------------|
3479 : . .
3480 : . .
3481 : . .
3482 : |----------------|
3483 : | Param # |
3484 : |----------------|
3485 : | ProcSym | Type |
3486 : |----------------|
3487 :
3488 : */
3489 :
3490 : static void ManipulatePseudoCallParameters (void);
3491 :
3492 : /*
3493 : ManipulateParameters - manipulates the procedure parameters in
3494 : preparation for a procedure call.
3495 : Prepares Boolean, Unbounded and VAR parameters.
3496 : The Stack:
3497 :
3498 :
3499 : Entry Exit
3500 :
3501 : Ptr -> exactly the same
3502 : +----------------+
3503 : | NoOfParameters |
3504 : |----------------|
3505 : | Param 1 |
3506 : |----------------|
3507 : | Param 2 |
3508 : |----------------|
3509 : . .
3510 : . .
3511 : . .
3512 : |----------------|
3513 : | Param # |
3514 : |----------------|
3515 : | ProcSym | Type |
3516 : |----------------|
3517 : */
3518 :
3519 : static void ManipulateParameters (bool IsForC);
3520 :
3521 : /*
3522 : CheckParameterOrdinals - check that ordinal values are within type range.
3523 : */
3524 :
3525 : static void CheckParameterOrdinals (void);
3526 :
3527 : /*
3528 : IsSameUnbounded - returns TRUE if unbounded types, t1, and, t2,
3529 : are compatible.
3530 : */
3531 :
3532 : static bool IsSameUnbounded (unsigned int t1, unsigned int t2);
3533 :
3534 : /*
3535 : AssignUnboundedVar - assigns an Unbounded symbol fields,
3536 : ArrayAddress and ArrayHigh, from an array symbol.
3537 : UnboundedSym is not a VAR parameter and therefore
3538 : this procedure can complete both of the fields.
3539 : Sym can be a Variable with type Unbounded.
3540 : Sym can be a Variable with type Array.
3541 : Sym can be a String Constant.
3542 :
3543 : ParamType is the TYPE of the parameter
3544 : */
3545 :
3546 : static void AssignUnboundedVar (unsigned int tok, unsigned int Sym, unsigned int ArraySym, unsigned int UnboundedSym, unsigned int ParamType, unsigned int dim);
3547 :
3548 : /*
3549 : AssignUnboundedNonVar - assigns an Unbounded symbol fields,
3550 : The difference between this procedure and
3551 : AssignUnboundedVar is that this procedure cannot
3552 : set the Unbounded.Address since the data from
3553 : Sym will be copied because parameter is NOT a VAR
3554 : parameter.
3555 : UnboundedSym is not a VAR parameter and therefore
3556 : this procedure can only complete the HIGH field
3557 : and not the ADDRESS field.
3558 : Sym can be a Variable with type Unbounded.
3559 : Sym can be a Variable with type Array.
3560 : Sym can be a String Constant.
3561 :
3562 : ParamType is the TYPE of the paramater
3563 : */
3564 :
3565 : static void AssignUnboundedNonVar (unsigned int tok, unsigned int Sym, unsigned int ArraySym, unsigned int UnboundedSym, unsigned int ParamType, unsigned int dim);
3566 :
3567 : /*
3568 : GenHigh - generates a HighOp but it checks if op3 is a
3569 : L value and if so it dereferences it. This
3570 : is inefficient, however it is clean and we let the gcc
3571 : backend detect these as common subexpressions.
3572 : It will also detect that a R value -> L value -> R value
3573 : via indirection and eleminate these.
3574 : */
3575 :
3576 : static void GenHigh (unsigned int tok, unsigned int op1, unsigned int op2, unsigned int op3);
3577 :
3578 : /*
3579 : AssignHighField -
3580 : */
3581 :
3582 : static void AssignHighField (unsigned int tok, unsigned int Sym, unsigned int ArraySym, unsigned int UnboundedSym, unsigned int ParamType, unsigned int actuali, unsigned int formali);
3583 :
3584 : /*
3585 : AssignHighFields -
3586 : */
3587 :
3588 : static void AssignHighFields (unsigned int tok, unsigned int Sym, unsigned int ArraySym, unsigned int UnboundedSym, unsigned int ParamType, unsigned int dim);
3589 :
3590 : /*
3591 : UnboundedNonVarLinkToArray - links an array, ArraySym, to an unbounded
3592 : array, UnboundedSym. The parameter is a
3593 : NON VAR variety.
3594 : */
3595 :
3596 : static void UnboundedNonVarLinkToArray (unsigned int tok, unsigned int Sym, unsigned int ArraySym, unsigned int UnboundedSym, unsigned int ParamType, unsigned int dim);
3597 :
3598 : /*
3599 : UnboundedVarLinkToArray - links an array, ArraySym, to an unbounded array,
3600 : UnboundedSym. The parameter is a VAR variety.
3601 : */
3602 :
3603 : static void UnboundedVarLinkToArray (unsigned int tok, unsigned int Sym, unsigned int ArraySym, unsigned int UnboundedSym, unsigned int ParamType, unsigned int dim);
3604 :
3605 : /*
3606 : BuildPseudoProcedureCall - builds a pseudo procedure call.
3607 : This procedure does not directly alter the
3608 : stack, but by calling routines the stack
3609 : will change in the following way when this
3610 : procedure returns.
3611 :
3612 : The Stack:
3613 :
3614 :
3615 : Entry Exit
3616 :
3617 : Ptr ->
3618 : +----------------+
3619 : | NoOfParam |
3620 : |----------------|
3621 : | Param 1 |
3622 : |----------------|
3623 : | Param 2 |
3624 : |----------------|
3625 : . .
3626 : . .
3627 : . .
3628 : |----------------|
3629 : | Param # |
3630 : |----------------|
3631 : | ProcSym | Type | Empty
3632 : |----------------|
3633 : */
3634 :
3635 : static void BuildPseudoProcedureCall (unsigned int tokno);
3636 :
3637 : /*
3638 : GetItemPointedTo - returns the symbol type that is being pointed to
3639 : by Sym.
3640 : */
3641 :
3642 : static unsigned int GetItemPointedTo (unsigned int Sym);
3643 :
3644 : /*
3645 : BuildThrowProcedure - builds the pseudo procedure call M2RTS.Throw.
3646 : The Stack:
3647 :
3648 :
3649 : Entry Exit
3650 :
3651 : Ptr ->
3652 : +----------------+
3653 : | NoOfParam |
3654 : |----------------|
3655 : | Param 1 |
3656 : |----------------|
3657 : | Param 2 |
3658 : |----------------|
3659 : . .
3660 : . .
3661 : . .
3662 : |----------------|
3663 : | Param # |
3664 : |----------------|
3665 : | ProcSym | Type | Empty
3666 : |----------------|
3667 : */
3668 :
3669 : static void BuildThrowProcedure (unsigned int functok);
3670 :
3671 : /*
3672 : BuildNewProcedure - builds the pseudo procedure call NEW.
3673 : This procedure is traditionally a "macro" for
3674 : NEW(x, ...) --> ALLOCATE(x, TSIZE(x^, ...))
3675 : One method of implementation is to emulate a "macro"
3676 : processor by pushing the relevant input tokens
3677 : back onto the input stack.
3678 : However this causes two problems:
3679 :
3680 : (i) Unnecessary code is produced for x^
3681 : (ii) SIZE must be imported from SYSTEM
3682 : Therefore we chose an alternative method of
3683 : implementation;
3684 : generate quadruples for ALLOCATE(x, TSIZE(x^, ...))
3685 : this, although slightly more efficient,
3686 : is more complex and circumvents problems (i) and (ii).
3687 :
3688 : The Stack:
3689 :
3690 :
3691 : Entry Exit
3692 :
3693 : Ptr ->
3694 : +----------------+
3695 : | NoOfParam |
3696 : |----------------|
3697 : | Param 1 |
3698 : |----------------|
3699 : | Param 2 |
3700 : |----------------|
3701 : . .
3702 : . .
3703 : . .
3704 : |----------------|
3705 : | Param # |
3706 : |----------------|
3707 : | ProcSym | Type | Empty
3708 : |----------------|
3709 : */
3710 :
3711 : static void BuildNewProcedure (unsigned int functok);
3712 :
3713 : /*
3714 : BuildDisposeProcedure - builds the pseudo procedure call DISPOSE.
3715 : This procedure is traditionally a "macro" for
3716 : DISPOSE(x) --> DEALLOCATE(x, TSIZE(x^))
3717 : One method of implementation is to emulate a "macro"
3718 : processor by pushing the relevant input tokens
3719 : back onto the input stack.
3720 : However this causes two problems:
3721 :
3722 : (i) Unnecessary code is produced for x^
3723 : (ii) TSIZE must be imported from SYSTEM
3724 : Therefore we chose an alternative method of
3725 : implementation;
3726 : generate quadruples for DEALLOCATE(x, TSIZE(x^))
3727 : this, although slightly more efficient,
3728 : is more complex and circumvents problems (i)
3729 : and (ii).
3730 :
3731 : The Stack:
3732 :
3733 :
3734 : Entry Exit
3735 :
3736 : Ptr ->
3737 : +----------------+
3738 : | NoOfParam |
3739 : |----------------|
3740 : | Param 1 |
3741 : |----------------|
3742 : | Param 2 |
3743 : |----------------|
3744 : . .
3745 : . .
3746 : . .
3747 : |----------------|
3748 : | Param # |
3749 : |----------------|
3750 : | ProcSym | Type | Empty
3751 : |----------------|
3752 : */
3753 :
3754 : static void BuildDisposeProcedure (unsigned int functok);
3755 :
3756 : /*
3757 : CheckRangeIncDec - performs des := des <tok> expr
3758 : with range checking (if enabled).
3759 :
3760 : Stack
3761 : Entry Exit
3762 :
3763 : +------------+
3764 : empty | des + expr |
3765 : |------------|
3766 : */
3767 :
3768 : static void CheckRangeIncDec (unsigned int tokenpos, unsigned int des, unsigned int expr, NameKey_Name tok);
3769 :
3770 : /*
3771 : BuildIncProcedure - builds the pseudo procedure call INC.
3772 : INC is a procedure which increments a variable.
3773 : It takes one or two parameters:
3774 : INC(a, b) or INC(a)
3775 : a := a+b or a := a+1
3776 :
3777 : The Stack:
3778 :
3779 :
3780 : Entry Exit
3781 :
3782 : Ptr ->
3783 : +----------------+
3784 : | NoOfParam |
3785 : |----------------|
3786 : | Param 1 |
3787 : |----------------|
3788 : | Param 2 |
3789 : |----------------|
3790 : . .
3791 : . .
3792 : . .
3793 : |----------------|
3794 : | Param # |
3795 : |----------------|
3796 : | ProcSym | Type | Empty
3797 : |----------------|
3798 : */
3799 :
3800 : static void BuildIncProcedure (unsigned int proctok);
3801 :
3802 : /*
3803 : BuildDecProcedure - builds the pseudo procedure call DEC.
3804 : DEC is a procedure which decrements a variable.
3805 : It takes one or two parameters:
3806 : DEC(a, b) or DEC(a)
3807 : a := a-b or a := a-1
3808 :
3809 : The Stack:
3810 :
3811 :
3812 : Entry Exit
3813 :
3814 : Ptr ->
3815 : +----------------+
3816 : | NoOfParam |
3817 : |----------------|
3818 : | Param 1 |
3819 : |----------------|
3820 : | Param 2 |
3821 : |----------------|
3822 : . .
3823 : . .
3824 : . .
3825 : |----------------|
3826 : | Param # |
3827 : |----------------|
3828 : | ProcSym | Type | Empty
3829 : |----------------|
3830 : */
3831 :
3832 : static void BuildDecProcedure (unsigned int proctok);
3833 :
3834 : /*
3835 : DereferenceLValue - checks to see whether, operand, is declare as an LValue
3836 : and if so it dereferences it.
3837 : */
3838 :
3839 : static unsigned int DereferenceLValue (unsigned int tok, unsigned int operand);
3840 :
3841 : /*
3842 : BuildInclProcedure - builds the pseudo procedure call INCL.
3843 : INCL is a procedure which adds bit b into a BITSET a.
3844 : It takes two parameters:
3845 : INCL(a, b)
3846 :
3847 : a := a + {b}
3848 :
3849 : The Stack:
3850 :
3851 :
3852 : Entry Exit
3853 :
3854 : Ptr ->
3855 : +----------------+
3856 : | NoOfParam |
3857 : |----------------|
3858 : | Param 1 |
3859 : |----------------|
3860 : | Param 2 |
3861 : |----------------|
3862 : | ProcSym | Type | Empty
3863 : |----------------|
3864 : */
3865 :
3866 : static void BuildInclProcedure (unsigned int proctok);
3867 :
3868 : /*
3869 : BuildExclProcedure - builds the pseudo procedure call EXCL.
3870 : INCL is a procedure which removes bit b from SET a.
3871 : It takes two parameters:
3872 : EXCL(a, b)
3873 :
3874 : a := a - {b}
3875 :
3876 : The Stack:
3877 :
3878 :
3879 : Entry Exit
3880 :
3881 : Ptr ->
3882 : +----------------+
3883 : | NoOfParam |
3884 : |----------------|
3885 : | Param 1 |
3886 : |----------------|
3887 : | Param 2 |
3888 : |----------------|
3889 : | ProcSym | Type | Empty
3890 : |----------------|
3891 : */
3892 :
3893 : static void BuildExclProcedure (unsigned int proctok);
3894 :
3895 : /*
3896 : BuildTypeCoercion - builds the type coersion.
3897 : Modula-2 allows types to be coersed with no runtime
3898 : penility.
3899 : It insists that the TSIZE(t1)=TSIZE(t2) where
3900 : t2 variable := t2(variable of type t1).
3901 : The ReturnVar on the stack is of type t2.
3902 :
3903 : The Stack:
3904 :
3905 :
3906 : Entry Exit
3907 :
3908 : Ptr ->
3909 : +----------------+
3910 : | NoOfParam |
3911 : |----------------|
3912 : | Param 1 |
3913 : |----------------|
3914 : | Param 2 |
3915 : |----------------|
3916 : . .
3917 : . .
3918 : . .
3919 : |----------------|
3920 : | Param # | <- Ptr
3921 : |----------------| +------------+
3922 : | ProcSym | Type | | ReturnVar |
3923 : |----------------| |------------|
3924 :
3925 : Quadruples:
3926 :
3927 : CoerceOp ReturnVar Type Param1
3928 :
3929 : A type coercion will only be legal if the different
3930 : types have exactly the same size.
3931 : Since we can only decide this after M2Eval has processed
3932 : the symbol table then we create a quadruple explaining
3933 : the coercion taking place, the code generator can test
3934 : this assertion and report an error if the type sizes
3935 : differ.
3936 : */
3937 :
3938 : static void BuildTypeCoercion (bool ConstExpr);
3939 :
3940 : /*
3941 : BuildRealFunctionCall - builds a function call.
3942 : The Stack:
3943 :
3944 :
3945 : Entry Exit
3946 :
3947 : Ptr ->
3948 : +----------------+
3949 : | NoOfParam |
3950 : |----------------|
3951 : | Param 1 |
3952 : |----------------|
3953 : | Param 2 |
3954 : |----------------|
3955 : . .
3956 : . .
3957 : . .
3958 : |----------------|
3959 : | Param # | <- Ptr
3960 : |----------------| +------------+
3961 : | ProcSym | Type | | ReturnVar |
3962 : |----------------| |------------|
3963 : */
3964 :
3965 : static void BuildRealFunctionCall (unsigned int tokno, bool ConstExpr);
3966 :
3967 : /*
3968 : BuildPseudoFunctionCall - builds the pseudo function
3969 : The Stack:
3970 :
3971 :
3972 : Entry Exit
3973 :
3974 : Ptr ->
3975 : +----------------+
3976 : | NoOfParam |
3977 : |----------------|
3978 : | Param 1 |
3979 : |----------------|
3980 : | Param 2 |
3981 : |----------------|
3982 : . .
3983 : . .
3984 : . .
3985 : |----------------|
3986 : | Param # | <- Ptr
3987 : |----------------| +------------+
3988 : | ProcSym | Type | | ReturnVar |
3989 : |----------------| |------------|
3990 :
3991 : */
3992 :
3993 : static void BuildPseudoFunctionCall (bool ConstExpr);
3994 :
3995 : /*
3996 : BuildAddAdrFunction - builds the pseudo procedure call ADDADR.
3997 :
3998 : PROCEDURE ADDADR (addr: ADDRESS; offset: CARDINAL): ADDRESS ;
3999 :
4000 : Which returns address given by (addr + offset),
4001 : [ the standard says that it _may_
4002 : "raise an exception if this address is not valid."
4003 : currently we do not generate any exception code ]
4004 :
4005 : The Stack:
4006 :
4007 : Entry Exit
4008 :
4009 : Ptr ->
4010 : +----------------+
4011 : | NoOfParam |
4012 : |----------------|
4013 : | Param 1 |
4014 : |----------------|
4015 : | Param 2 | <- Ptr
4016 : |----------------| +------------+
4017 : | ProcSym | Type | | ReturnVar |
4018 : |----------------| |------------|
4019 : */
4020 :
4021 : static void BuildAddAdrFunction (unsigned int ProcSym, bool ConstExpr);
4022 :
4023 : /*
4024 : BuildSubAdrFunction - builds the pseudo procedure call ADDADR.
4025 :
4026 : PROCEDURE SUBADR (addr: ADDRESS; offset: CARDINAL): ADDRESS ;
4027 :
4028 : Which returns address given by (addr - offset),
4029 : [ the standard says that it _may_
4030 : "raise an exception if this address is not valid."
4031 : currently we do not generate any exception code ]
4032 :
4033 : The Stack:
4034 :
4035 : Entry Exit
4036 :
4037 : Ptr ->
4038 : +----------------+
4039 : | NoOfParam |
4040 : |----------------|
4041 : | Param 1 |
4042 : |----------------|
4043 : | Param 2 | <- Ptr
4044 : |----------------| +------------+
4045 : | ProcSym | Type | | ReturnVar |
4046 : |----------------| |------------|
4047 : */
4048 :
4049 : static void BuildSubAdrFunction (unsigned int ProcSym, bool ConstExpr);
4050 :
4051 : /*
4052 : BuildDifAdrFunction - builds the pseudo procedure call DIFADR.
4053 :
4054 : PROCEDURE DIFADR (addr1, addr2: ADDRESS): INTEGER ;
4055 :
4056 : Which returns address given by (addr1 - addr2),
4057 : [ the standard says that it _may_
4058 : "raise an exception if this address is invalid or
4059 : address space is non-contiguous."
4060 : currently we do not generate any exception code ]
4061 :
4062 : The Stack:
4063 :
4064 : Entry Exit
4065 :
4066 : Ptr ->
4067 : +----------------+
4068 : | NoOfParam |
4069 : |----------------|
4070 : | Param 1 |
4071 : |----------------|
4072 : | Param 2 | <- Ptr
4073 : |----------------| +------------+
4074 : | ProcSym | Type | | ReturnVar |
4075 : |----------------| |------------|
4076 : */
4077 :
4078 : static void BuildDifAdrFunction (unsigned int ProcSym, bool ConstExpr);
4079 :
4080 : /*
4081 : BuildHighFunction - checks the stack in preparation for generating
4082 : quadruples which perform HIGH.
4083 : This procedure does not alter the stack but
4084 : determines whether, a, in HIGH(a) is an ArraySym
4085 : or UnboundedSym.
4086 : Both cases are different and appropriate quadruple
4087 : generating routines are called.
4088 :
4089 : The Stack:
4090 :
4091 :
4092 : Entry Exit
4093 :
4094 : Ptr ->
4095 : +----------------+
4096 : | NoOfParam |
4097 : |----------------|
4098 : | Param 1 |
4099 : |----------------|
4100 : | Param 2 |
4101 : |----------------|
4102 : . .
4103 : . .
4104 : . .
4105 : |----------------|
4106 : | Param # | <- Ptr
4107 : |----------------| +------------+
4108 : | ProcSym | Type | | ReturnVar |
4109 : |----------------| |------------|
4110 :
4111 : */
4112 :
4113 : static void BuildHighFunction (void);
4114 :
4115 : /*
4116 : BuildConstHighFromSym - builds the pseudo function HIGH from an Sym.
4117 : Sym is a constant or an array which has constant bounds
4118 : and therefore it can be calculated at compile time.
4119 :
4120 : The Stack:
4121 :
4122 :
4123 : Entry Exit
4124 :
4125 : Ptr ->
4126 : +----------------+
4127 : | NoOfParam |
4128 : |----------------|
4129 : | Param 1 |
4130 : |----------------|
4131 : | Param 2 |
4132 : |----------------|
4133 : . .
4134 : . .
4135 : . .
4136 : |----------------|
4137 : | Param # | <- Ptr
4138 : |----------------| +------------+
4139 : | ProcSym | Type | | ReturnVar |
4140 : |----------------| |------------|
4141 : */
4142 :
4143 : static void BuildConstHighFromSym (unsigned int tok);
4144 :
4145 : /*
4146 : BuildHighFromUnbounded - builds the pseudo function HIGH from an
4147 : UnboundedSym.
4148 :
4149 : The Stack:
4150 :
4151 :
4152 : Entry Exit
4153 :
4154 : Ptr ->
4155 : +----------------+
4156 : | NoOfParam |
4157 : |----------------|
4158 : | Param # | <- Ptr
4159 : |----------------| +------------+
4160 : | ProcSym | Type | | ReturnVar |
4161 : |----------------| |------------|
4162 :
4163 : */
4164 :
4165 : static void BuildHighFromUnbounded (unsigned int tok);
4166 :
4167 : /*
4168 : GetQualidentImport - returns the symbol as if it were qualified from, module.n.
4169 : This is used to reference runtime support procedures and an
4170 : error is generated if the symbol cannot be obtained.
4171 : */
4172 :
4173 : static unsigned int GetQualidentImport (unsigned int tokno, NameKey_Name n, NameKey_Name module);
4174 :
4175 : /*
4176 : ConstExprError - return TRUE if a constant expression is being built and Var is a variable.
4177 : */
4178 :
4179 : static bool ConstExprError (unsigned int Func, unsigned int Var, unsigned int optok, bool ConstExpr);
4180 :
4181 : /*
4182 : DeferMakeLengthConst - creates a constant which contains the length of string, sym.
4183 : */
4184 :
4185 : static unsigned int DeferMakeLengthConst (unsigned int tok, unsigned int sym);
4186 :
4187 : /*
4188 : BuildLengthFunction - builds the inline standard function LENGTH.
4189 :
4190 : The Stack:
4191 :
4192 :
4193 : Entry Exit
4194 :
4195 : Ptr ->
4196 : +----------------+
4197 : | NoOfParam |
4198 : |----------------|
4199 : | Param 1 | <- Ptr
4200 : |----------------| +------------+
4201 : | ProcSym | Type | | ReturnVar |
4202 : |----------------| |------------|
4203 :
4204 : */
4205 :
4206 : static void BuildLengthFunction (unsigned int Function, bool ConstExpr);
4207 :
4208 : /*
4209 : BuildOddFunction - builds the pseudo procedure call ODD.
4210 : This procedure is actually a "macro" for
4211 : ORD(x) --> VAL(BOOLEAN, x MOD 2)
4212 : However we cannot push tokens back onto the input stack
4213 : because the compiler is currently building a function
4214 : call and expecting a ReturnVar on the stack.
4215 : Hence we manipulate the stack and call
4216 : BuildConvertFunction.
4217 :
4218 : The Stack:
4219 :
4220 :
4221 : Entry Exit
4222 :
4223 : Ptr ->
4224 : +----------------+
4225 : | NoOfParam |
4226 : |----------------|
4227 : | Param 1 |
4228 : |----------------|
4229 : | Param 2 |
4230 : |----------------|
4231 : . .
4232 : . .
4233 : . .
4234 : |----------------|
4235 : | Param # |
4236 : |----------------|
4237 : | ProcSym | Type | Empty
4238 : |----------------|
4239 : */
4240 :
4241 : static void BuildOddFunction (unsigned int ProcSym, bool ConstExpr);
4242 :
4243 : /*
4244 : BuildAbsFunction - builds a call to the standard function ABS.
4245 :
4246 : We cannot implement it as a macro or inline an
4247 : IF THEN statement as the IF THEN ELSE requires
4248 : we write the value to the same variable (or constant)
4249 : twice. The macro implementation will fail as
4250 : the compiler maybe building a function
4251 : call and expecting a ReturnVar on the stack.
4252 : The only method to implement this is to pass it to the
4253 : gcc backend.
4254 :
4255 : The Stack:
4256 :
4257 :
4258 : Entry Exit
4259 :
4260 : Ptr ->
4261 : +----------------+
4262 : | NoOfParam |
4263 : |----------------|
4264 : | Param 1 |
4265 : |----------------|
4266 : | Param 2 |
4267 : |----------------|
4268 : . .
4269 : . .
4270 : . .
4271 : |----------------|
4272 : | Param # |
4273 : |----------------|
4274 : | ProcSym | Type | Empty
4275 : |----------------|
4276 : */
4277 :
4278 : static void BuildAbsFunction (unsigned int ProcSym, bool ConstExpr);
4279 :
4280 : /*
4281 : BuildCapFunction - builds the pseudo procedure call CAP.
4282 : We generate a the following quad:
4283 :
4284 :
4285 : StandardFunctionOp ReturnVal Cap Param1
4286 :
4287 : The Stack:
4288 :
4289 :
4290 : Entry Exit
4291 :
4292 : Ptr ->
4293 : +----------------+
4294 : | NoOfParam = 1 |
4295 : |----------------|
4296 : | Param 1 |
4297 : |----------------| +-------------+
4298 : | ProcSym | Type | | ReturnVal |
4299 : |----------------| |-------------|
4300 : */
4301 :
4302 : static void BuildCapFunction (unsigned int ProcSym, bool ConstExpr);
4303 :
4304 : /*
4305 : BuildChrFunction - builds the pseudo procedure call CHR.
4306 : This procedure is actually a "macro" for
4307 : CHR(x) --> CONVERT(CHAR, x)
4308 : However we cannot push tokens back onto the input stack
4309 : because the compiler is currently building a function
4310 : call and expecting a ReturnVar on the stack.
4311 : Hence we manipulate the stack and call
4312 : BuildConvertFunction.
4313 :
4314 : The Stack:
4315 :
4316 :
4317 : Entry Exit
4318 :
4319 : Ptr ->
4320 : +----------------+
4321 : | NoOfParam |
4322 : |----------------|
4323 : | Param 1 |
4324 : |----------------|
4325 : | Param 2 |
4326 : |----------------|
4327 : . .
4328 : . .
4329 : . .
4330 : |----------------|
4331 : | Param # |
4332 : |----------------|
4333 : | ProcSym | Type | Empty
4334 : |----------------|
4335 : */
4336 :
4337 : static void BuildChrFunction (unsigned int ProcSym, bool ConstExpr);
4338 :
4339 : /*
4340 : BuildOrdFunction - builds the pseudo procedure call ORD.
4341 : This procedure is actually a "macro" for
4342 : ORD(x) --> CONVERT(GetSType(sym), x)
4343 : However we cannot push tokens back onto the input stack
4344 : because the compiler is currently building a function
4345 : call and expecting a ReturnVar on the stack.
4346 : Hence we manipulate the stack and call
4347 : BuildConvertFunction.
4348 :
4349 : The Stack:
4350 :
4351 :
4352 : Entry Exit
4353 :
4354 : Ptr ->
4355 : +----------------+
4356 : | NoOfParam |
4357 : |----------------|
4358 : | Param 1 |
4359 : |----------------|
4360 : | Param 2 |
4361 : |----------------|
4362 : . .
4363 : . .
4364 : . .
4365 : |----------------|
4366 : | Param # |
4367 : |----------------|
4368 : | ProcSym | Type | Empty
4369 : |----------------|
4370 : */
4371 :
4372 : static void BuildOrdFunction (unsigned int Sym, bool ConstExpr);
4373 :
4374 : /*
4375 : BuildIntFunction - builds the pseudo procedure call INT.
4376 : This procedure is actually a "macro" for
4377 : INT(x) --> CONVERT(INTEGER, x)
4378 : However we cannot push tokens back onto the input stack
4379 : because the compiler is currently building a function
4380 : call and expecting a ReturnVar on the stack.
4381 : Hence we manipulate the stack and call
4382 : BuildConvertFunction.
4383 :
4384 : The Stack:
4385 :
4386 :
4387 : Entry Exit
4388 :
4389 : Ptr ->
4390 : +----------------+
4391 : | NoOfParam |
4392 : |----------------|
4393 : | Param 1 |
4394 : |----------------|
4395 : | Param 2 |
4396 : |----------------|
4397 : . .
4398 : . .
4399 : . .
4400 : |----------------|
4401 : | Param # |
4402 : |----------------|
4403 : | ProcSym | Type | Empty
4404 : |----------------|
4405 : */
4406 :
4407 : static void BuildIntFunction (unsigned int Sym, bool ConstExpr);
4408 :
4409 : /*
4410 : BuildMakeAdrFunction - builds the pseudo procedure call MAKEADR.
4411 :
4412 : The Stack:
4413 :
4414 :
4415 : Entry Exit
4416 :
4417 : Ptr ->
4418 : +----------------+
4419 : | NoOfParam |
4420 : |----------------|
4421 : | Param 1 |
4422 : |----------------|
4423 : | Param 2 |
4424 : |----------------|
4425 : . .
4426 : . .
4427 : . .
4428 : |----------------|
4429 : | Param # |
4430 : |----------------|
4431 : | ProcSym | Type | Empty
4432 : |----------------|
4433 : */
4434 :
4435 : static void BuildMakeAdrFunction (void);
4436 :
4437 : /*
4438 : BuildShiftFunction - builds the pseudo procedure call SHIFT.
4439 :
4440 : PROCEDURE SHIFT (val: <any type>;
4441 : num: INTEGER): <any type> ;
4442 :
4443 : "Returns a bit sequence obtained from val by
4444 : shifting up or down (left or right) by the
4445 : absolute value of num, introducing
4446 : zeros as necessary. The direction is down if
4447 : the sign of num is negative, otherwise the
4448 : direction is up."
4449 :
4450 : The Stack:
4451 :
4452 : Entry Exit
4453 :
4454 : Ptr ->
4455 : +----------------+
4456 : | NoOfParam |
4457 : |----------------|
4458 : | Param 1 |
4459 : |----------------|
4460 : | Param 2 | <- Ptr
4461 : |----------------| +------------+
4462 : | ProcSym | Type | | ReturnVar |
4463 : |----------------| |------------|
4464 : */
4465 :
4466 : static void BuildShiftFunction (void);
4467 :
4468 : /*
4469 : BuildRotateFunction - builds the pseudo procedure call ROTATE.
4470 :
4471 : PROCEDURE ROTATE (val: <any type>;
4472 : num: INTEGER): <any type> ;
4473 :
4474 : "Returns a bit sequence obtained from val
4475 : by rotating up or down (left or right) by
4476 : the absolute value of num. The direction is
4477 : down if the sign of num is negative, otherwise
4478 : the direction is up."
4479 :
4480 : The Stack:
4481 :
4482 : Entry Exit
4483 :
4484 : Ptr ->
4485 : +----------------+
4486 : | NoOfParam |
4487 : |----------------|
4488 : | Param 1 |
4489 : |----------------|
4490 : | Param 2 | <- Ptr
4491 : |----------------| +------------+
4492 : | ProcSym | Type | | ReturnVar |
4493 : |----------------| |------------|
4494 : */
4495 :
4496 : static void BuildRotateFunction (void);
4497 :
4498 : /*
4499 : BuildValFunction - builds the pseudo procedure call VAL.
4500 : This procedure is actually a "macro" for
4501 : VAL(Type, x) --> CONVERT(Type, x)
4502 : However we cannot push tokens back onto the input stack
4503 : because the compiler is currently building a function
4504 : call and expecting a ReturnVar on the stack.
4505 : Hence we manipulate the stack and call
4506 : BuildConvertFunction.
4507 :
4508 : The Stack:
4509 :
4510 :
4511 : Entry Exit
4512 :
4513 : Ptr ->
4514 : +----------------+
4515 : | NoOfParam |
4516 : |----------------|
4517 : | Param 1 |
4518 : |----------------|
4519 : | Param 2 |
4520 : |----------------|
4521 : . .
4522 : . .
4523 : . .
4524 : |----------------|
4525 : | Param # |
4526 : |----------------|
4527 : | ProcSym | Type | Empty
4528 : |----------------|
4529 : */
4530 :
4531 : static void BuildValFunction (unsigned int ProcSym, bool ConstExpr);
4532 :
4533 : /*
4534 : BuildCastFunction - builds the pseudo procedure call CAST.
4535 : This procedure is actually a "macro" for
4536 : CAST(Type, x) --> Type(x)
4537 : However we cannot push tokens back onto the input stack
4538 : because the compiler is currently building a function
4539 : call and expecting a ReturnVar on the stack.
4540 : Hence we manipulate the stack and call
4541 : BuildConvertFunction.
4542 :
4543 : The Stack:
4544 :
4545 :
4546 : Entry Exit
4547 :
4548 : Ptr ->
4549 : +----------------+
4550 : | NoOfParam |
4551 : |----------------|
4552 : | Param 1 |
4553 : |----------------|
4554 : | Param 2 |
4555 : |----------------|
4556 : . .
4557 : . .
4558 : . .
4559 : |----------------|
4560 : | Param # |
4561 : |----------------|
4562 : | ProcSym | Type | Empty
4563 : |----------------|
4564 : */
4565 :
4566 : static void BuildCastFunction (unsigned int ProcSym, bool ConstExpr);
4567 :
4568 : /*
4569 : BuildConvertFunction - builds the pseudo function CONVERT.
4570 : CONVERT( Type, Variable ) ;
4571 :
4572 : The Stack:
4573 :
4574 :
4575 : Entry Exit
4576 :
4577 : Ptr ->
4578 : +----------------+
4579 : | NoOfParam |
4580 : |----------------|
4581 : | Param 1 |
4582 : |----------------|
4583 : | Param 2 |
4584 : |----------------|
4585 : . .
4586 : . .
4587 : . .
4588 : |----------------|
4589 : | Param # | <- Ptr
4590 : |----------------| +---------------------+
4591 : | ProcSym | Type | | ReturnVar | Param1 |
4592 : |----------------| |---------------------|
4593 :
4594 : Quadruples:
4595 :
4596 : ConvertOp ReturnVar Param1 Param2
4597 :
4598 : Converts variable Param2 into a variable Param1
4599 : with a type Param1.
4600 : */
4601 :
4602 : static void BuildConvertFunction (unsigned int ProcSym, bool ConstExpr);
4603 :
4604 : /*
4605 : CheckBaseTypeValue - checks to see whether the value, min, really exists.
4606 : */
4607 :
4608 : static unsigned int CheckBaseTypeValue (unsigned int tok, unsigned int type, unsigned int min, unsigned int func);
4609 :
4610 : /*
4611 : GetTypeMin - returns the minimium value of type and generate an error
4612 : if this is unavailable.
4613 : */
4614 :
4615 : static unsigned int GetTypeMin (unsigned int tok, unsigned int func, unsigned int type);
4616 :
4617 : /*
4618 : GetTypeMinLower - obtain the maximum value for type.
4619 : */
4620 :
4621 : static unsigned int GetTypeMinLower (unsigned int tok, unsigned int func, unsigned int type);
4622 :
4623 : /*
4624 : GetTypeMax - returns the maximum value of type and generate an error
4625 : if this is unavailable.
4626 : */
4627 :
4628 : static unsigned int GetTypeMax (unsigned int tok, unsigned int func, unsigned int type);
4629 :
4630 : /*
4631 : GetTypeMaxLower - obtain the maximum value for type.
4632 : */
4633 :
4634 : static unsigned int GetTypeMaxLower (unsigned int tok, unsigned int func, unsigned int type);
4635 :
4636 : /*
4637 : BuildMinFunction - builds the pseudo function call Min.
4638 :
4639 : The Stack:
4640 :
4641 : Entry Exit
4642 :
4643 : Ptr ->
4644 : +----------------+
4645 : | NoOfParam=1 |
4646 : |----------------|
4647 : | Param 1 |
4648 : |----------------|
4649 : | ProcSym | Type | Empty
4650 : |----------------|
4651 : */
4652 :
4653 : static void BuildMinFunction (void);
4654 :
4655 : /*
4656 : BuildMaxFunction - builds the pseudo function call Max.
4657 :
4658 : The Stack:
4659 :
4660 : Entry Exit
4661 :
4662 : Ptr ->
4663 : +----------------+
4664 : | NoOfParam=1 |
4665 : |----------------|
4666 : | Param 1 |
4667 : |----------------|
4668 : | ProcSym | Type | Empty
4669 : |----------------|
4670 : */
4671 :
4672 : static void BuildMaxFunction (void);
4673 :
4674 : /*
4675 : BuildTruncFunction - builds the pseudo procedure call TRUNC.
4676 : This procedure is actually a "macro" for
4677 : TRUNC(x) --> CONVERT(INTEGER, x)
4678 : However we cannot push tokens back onto the input stack
4679 : because the compiler is currently building a function
4680 : call and expecting a ReturnVar on the stack.
4681 : Hence we manipulate the stack and call
4682 : BuildConvertFunction.
4683 :
4684 : The Stack:
4685 :
4686 :
4687 : Entry Exit
4688 :
4689 : Ptr ->
4690 : +----------------+
4691 : | NoOfParam |
4692 : |----------------|
4693 : | Param 1 |
4694 : |----------------|
4695 : | Param 2 |
4696 : |----------------|
4697 : . .
4698 : . .
4699 : . .
4700 : |----------------|
4701 : | Param # |
4702 : |----------------|
4703 : | ProcSym | Type | Empty
4704 : |----------------|
4705 : */
4706 :
4707 : static void BuildTruncFunction (unsigned int Sym, bool ConstExpr);
4708 :
4709 : /*
4710 : BuildFloatFunction - builds the pseudo procedure call FLOAT.
4711 : This procedure is actually a "macro" for
4712 : FLOAT(x) --> CONVERT(REAL, x)
4713 : However we cannot push tokens back onto the input stack
4714 : because the compiler is currently building a function
4715 : call and expecting a ReturnVar on the stack.
4716 : Hence we manipulate the stack and call
4717 : BuildConvertFunction.
4718 :
4719 : The Stack:
4720 :
4721 :
4722 : Entry Exit
4723 :
4724 : Ptr ->
4725 : +----------------+
4726 : | NoOfParam |
4727 : |----------------|
4728 : | Param 1 |
4729 : |----------------|
4730 : | Param 2 |
4731 : |----------------|
4732 : . .
4733 : . .
4734 : . .
4735 : |----------------|
4736 : | Param # |
4737 : |----------------|
4738 : | ProcSym | Type | Empty
4739 : |----------------|
4740 : */
4741 :
4742 : static void BuildFloatFunction (unsigned int Sym, bool ConstExpr);
4743 :
4744 : /*
4745 : BuildReFunction - builds the pseudo procedure call RE.
4746 :
4747 : The Stack:
4748 :
4749 :
4750 : Entry Exit
4751 :
4752 : Ptr ->
4753 : +----------------+
4754 : | NoOfParam |
4755 : |----------------|
4756 : | Param 1 |
4757 : |----------------|
4758 : | Param 2 |
4759 : |----------------|
4760 : . .
4761 : . .
4762 : . .
4763 : |----------------|
4764 : | Param # |
4765 : |----------------|
4766 : | ProcSym | Type | Empty
4767 : |----------------|
4768 : */
4769 :
4770 : static void BuildReFunction (unsigned int Sym, bool ConstExpr);
4771 :
4772 : /*
4773 : BuildImFunction - builds the pseudo procedure call IM.
4774 :
4775 : The Stack:
4776 :
4777 :
4778 : Entry Exit
4779 :
4780 : Ptr ->
4781 : +----------------+
4782 : | NoOfParam |
4783 : |----------------|
4784 : | Param 1 |
4785 : |----------------|
4786 : | Param 2 |
4787 : |----------------|
4788 : . .
4789 : . .
4790 : . .
4791 : |----------------|
4792 : | Param # |
4793 : |----------------|
4794 : | ProcSym | Type | Empty
4795 : |----------------|
4796 : */
4797 :
4798 : static void BuildImFunction (unsigned int Sym, bool ConstExpr);
4799 :
4800 : /*
4801 : BuildCmplxFunction - builds the pseudo procedure call CMPLX.
4802 :
4803 : The Stack:
4804 :
4805 :
4806 : Entry Exit
4807 :
4808 : Ptr ->
4809 : +----------------+
4810 : | NoOfParam |
4811 : |----------------|
4812 : | Param 1 |
4813 : |----------------|
4814 : | Param 2 |
4815 : |----------------|
4816 : . .
4817 : . .
4818 : . .
4819 : |----------------|
4820 : | Param # |
4821 : |----------------|
4822 : | ProcSym | Type | Empty
4823 : |----------------|
4824 : */
4825 :
4826 : static void BuildCmplxFunction (unsigned int func, bool ConstExpr);
4827 :
4828 : /*
4829 : BuildAdrFunction - builds the pseudo function ADR
4830 : The Stack:
4831 :
4832 :
4833 : Entry Exit
4834 :
4835 : Ptr ->
4836 : +----------------+
4837 : | NoOfParam |
4838 : |----------------|
4839 : | Param 1 |
4840 : |----------------|
4841 : | Param 2 |
4842 : |----------------|
4843 : . .
4844 : . .
4845 : . .
4846 : |----------------|
4847 : | Param # | <- Ptr
4848 : |----------------| +------------+
4849 : | ProcSym | Type | | ReturnVar |
4850 : |----------------| |------------|
4851 :
4852 : */
4853 :
4854 : static void BuildAdrFunction (void);
4855 :
4856 : /*
4857 : BuildSizeFunction - builds the pseudo function SIZE
4858 : The Stack:
4859 :
4860 :
4861 : Entry Exit
4862 :
4863 : Ptr ->
4864 : +----------------+
4865 : | NoOfParam |
4866 : |----------------|
4867 : | Param 1 |
4868 : |----------------|
4869 : | Param 2 |
4870 : |----------------|
4871 : . .
4872 : . .
4873 : . .
4874 : |----------------|
4875 : | Param # | <- Ptr
4876 : |----------------| +------------+
4877 : | ProcSym | Type | | ReturnVar |
4878 : |----------------| |------------|
4879 : */
4880 :
4881 : static void BuildSizeFunction (void);
4882 :
4883 : /*
4884 : BuildTSizeFunction - builds the pseudo function TSIZE
4885 : The Stack:
4886 :
4887 :
4888 : Entry Exit
4889 :
4890 : Ptr ->
4891 : +----------------+
4892 : | NoOfParam |
4893 : |----------------|
4894 : | Param 1 |
4895 : |----------------|
4896 : | Param 2 |
4897 : |----------------|
4898 : . .
4899 : . .
4900 : . .
4901 : |----------------|
4902 : | Param # | <- Ptr
4903 : |----------------| +------------+
4904 : | ProcSym | Type | | ReturnVar |
4905 : |----------------| |------------|
4906 :
4907 : */
4908 :
4909 : static void BuildTSizeFunction (void);
4910 :
4911 : /*
4912 : BuildTBitSizeFunction - builds the pseudo function TBITSIZE
4913 : The Stack:
4914 :
4915 :
4916 : Entry Exit
4917 :
4918 : Ptr ->
4919 : +----------------+
4920 : | NoOfParam |
4921 : |----------------|
4922 : | Param 1 |
4923 : |----------------|
4924 : | Param 2 |
4925 : |----------------|
4926 : . .
4927 : . .
4928 : . .
4929 : |----------------|
4930 : | Param # | <- Ptr
4931 : |----------------| +------------+
4932 : | ProcSym | Type | | ReturnVar |
4933 : |----------------| |------------|
4934 :
4935 : */
4936 :
4937 : static void BuildTBitSizeFunction (void);
4938 :
4939 : /*
4940 : ExpectingParameterType -
4941 : */
4942 :
4943 : static void ExpectingParameterType (unsigned int BlockSym, unsigned int Type);
4944 :
4945 : /*
4946 : ExpectingVariableType -
4947 : */
4948 :
4949 : static void ExpectingVariableType (unsigned int BlockSym, unsigned int Type);
4950 :
4951 : /*
4952 : CheckVariablesAndParameterTypesInBlock - checks to make sure that block, BlockSym, has
4953 : parameters types and variable types which are legal.
4954 : */
4955 :
4956 : static void CheckVariablesAndParameterTypesInBlock (unsigned int BlockSym);
4957 :
4958 : /*
4959 : IsNeverAltered - returns TRUE if variable, sym, is never altered
4960 : between quadruples: Start..End
4961 : */
4962 :
4963 : static bool IsNeverAltered (unsigned int sym, unsigned int Start, unsigned int End);
4964 :
4965 : /*
4966 : IsConditionVariable - returns TRUE if the condition at quadruple, q, is variable.
4967 : */
4968 :
4969 : static bool IsConditionVariable (unsigned int q, unsigned int Start, unsigned int End);
4970 :
4971 : /*
4972 : IsInfiniteLoop - returns TRUE if an infinite loop is found.
4973 : Given a backwards jump at, End, it returns a BOOLEAN which depends on
4974 : whether a jump is found to jump beyond, End. If a conditonal jump is found
4975 : to pass over, End, the condition is tested for global variables, procedure variables and
4976 : constants.
4977 :
4978 : constant - ignored
4979 : variables - tested to see whether they are altered inside the loop
4980 : global variable - the procedure tests to see whether it is altered as above
4981 : but will also test to see whether this loop calls a procedure
4982 : in which case it believes the loop NOT to be infinite
4983 : (as this procedure call might alter the global variable)
4984 :
4985 : Note that this procedure can easily be fooled by the user altering variables
4986 : with pointers.
4987 : */
4988 :
4989 : static bool IsInfiniteLoop (unsigned int End);
4990 :
4991 : /*
4992 : CheckVariablesInBlock - given a block, BlockSym, check whether all variables are used.
4993 : */
4994 :
4995 : static void CheckVariablesInBlock (unsigned int BlockSym);
4996 :
4997 : /*
4998 : CheckFunctionReturn - checks to see that a RETURN statement was present in a function.
4999 : */
5000 :
5001 : static void CheckFunctionReturn (unsigned int ProcSym);
5002 :
5003 : /*
5004 : CheckReturnType - checks to see that the return type from currentProc is
5005 : assignment compatible with actualType.
5006 : */
5007 :
5008 : static void CheckReturnType (unsigned int tokno, unsigned int currentProc, unsigned int actualVal, unsigned int actualType);
5009 :
5010 : /*
5011 : BuildReturnLower - check the return type and value to ensure type
5012 : compatibility and no range overflow will occur.
5013 : */
5014 :
5015 : static void BuildReturnLower (unsigned int tokcombined, unsigned int tokexpr, unsigned int e1, unsigned int t1);
5016 :
5017 : /*
5018 : IsReadOnly - a helper procedure function to detect constants.
5019 : */
5020 :
5021 : static bool IsReadOnly (unsigned int sym);
5022 :
5023 : /*
5024 : BuildDesignatorError - removes the designator from the stack and replaces
5025 : it with an error symbol.
5026 : */
5027 :
5028 : static void BuildDesignatorError (const char *message_, unsigned int _message_high);
5029 :
5030 : /*
5031 : BuildDesignatorPointerError - removes the designator from the stack and replaces
5032 : it with an error symbol.
5033 : */
5034 :
5035 : static void BuildDesignatorPointerError (unsigned int type, unsigned int rw, unsigned int tokpos, const char *message_, unsigned int _message_high);
5036 :
5037 : /*
5038 : BuildDesignatorArrayStaticDynamic - Builds the array referencing.
5039 : The purpose of this procedure is to work out
5040 : whether the DesignatorArray is a static or
5041 : dynamic array and to call the appropriate
5042 : BuildRoutine.
5043 :
5044 : The Stack is expected to contain:
5045 :
5046 :
5047 : Entry Exit
5048 : ===== ====
5049 :
5050 : Ptr ->
5051 : +--------------+
5052 : | e | <- Ptr
5053 : |--------------| +------------+
5054 : | Sym | Type | | S | T |
5055 : |--------------| |------------|
5056 : */
5057 :
5058 : static void BuildDesignatorArrayStaticDynamic (void);
5059 :
5060 : /*
5061 : BuildStaticArray - Builds the array referencing for static arrays.
5062 : The Stack is expected to contain:
5063 :
5064 :
5065 : Entry Exit
5066 : ===== ====
5067 :
5068 : Ptr ->
5069 : +--------------+
5070 : | e | <- Ptr
5071 : |--------------| +------------+
5072 : | Sym | Type | | S | T |
5073 : |--------------| |------------|
5074 : */
5075 :
5076 : static void BuildStaticArray (void);
5077 :
5078 : /*
5079 : calculateMultipicand - generates quadruples which calculate the
5080 : multiplicand for the array at dimension, dim.
5081 : */
5082 :
5083 : static unsigned int calculateMultipicand (unsigned int tok, unsigned int arraySym, unsigned int arrayType, unsigned int dim);
5084 :
5085 : /*
5086 : ConvertToAddress - convert sym to an address.
5087 : */
5088 :
5089 : static unsigned int ConvertToAddress (unsigned int tokpos, unsigned int sym);
5090 :
5091 : /*
5092 : BuildDynamicArray - Builds the array referencing for dynamic arrays.
5093 : The Stack is expected to contain:
5094 :
5095 :
5096 : Entry Exit
5097 : ===== ====
5098 :
5099 : Ptr ->
5100 : +-----------------------+
5101 : | Index | <- Ptr
5102 : |-----------------------| +---------------------------+
5103 : | ArraySym | Type | Dim | | S | T | ArraySym | Dim+1 |
5104 : |-----------------------| |---------------------------|
5105 :
5106 :
5107 : if Dim=1
5108 : then
5109 : S := base of ArraySym + TSIZE(Type)*Index
5110 : else
5111 : S := S + TSIZE(Type)*Index
5112 : fi
5113 : */
5114 :
5115 : static void BuildDynamicArray (void);
5116 :
5117 : /*
5118 : DebugLocation -
5119 : */
5120 :
5121 : static void DebugLocation (unsigned int tok, const char *message_, unsigned int _message_high);
5122 :
5123 : /*
5124 : PushWith - pushes sym and type onto the with stack. It checks for
5125 : previous declaration of this record type.
5126 : */
5127 :
5128 : static void PushWith (unsigned int Sym, unsigned int Type, unsigned int Ref, unsigned int Tok);
5129 : static void PopWith (void);
5130 :
5131 : /*
5132 : BuildAccessWithField - similar to BuildDesignatorRecord except it
5133 : does not perform the address operation.
5134 : The address will have been computed at the
5135 : beginning of the WITH statement.
5136 : It also stops the GenQuad procedure from examining the
5137 : with stack.
5138 :
5139 : The Stack
5140 :
5141 : Entry
5142 :
5143 : Ptr ->
5144 : +--------------+
5145 : | Field | Type1| <- Ptr
5146 : |-------|------| +-------------+
5147 : | Adr | Type2| | Sym | Type1|
5148 : |--------------| |-------------|
5149 : */
5150 :
5151 : static void BuildAccessWithField (void);
5152 :
5153 : /*
5154 : SafeCheckWithField - only call CheckWithReference if the top of stack
5155 : contains a record field.
5156 : */
5157 :
5158 : static void SafeCheckWithField (void);
5159 :
5160 : /*
5161 : PushConstructor -
5162 : */
5163 :
5164 : static void PushConstructor (unsigned int sym);
5165 :
5166 : /*
5167 : AddFieldTo - adds field to value.
5168 : */
5169 :
5170 : static unsigned int AddFieldTo (unsigned int value, unsigned int field, unsigned int valuetok, unsigned int fieldtok);
5171 :
5172 : /*
5173 : CheckLogicalOperator - returns a logical operator if the operands imply
5174 : a logical operation should be performed.
5175 : */
5176 :
5177 : static NameKey_Name CheckLogicalOperator (NameKey_Name Tok, unsigned int left, unsigned int lefttype);
5178 :
5179 : /*
5180 : CheckDivModRem - initiates calls to check the divisor for DIV, MOD, REM
5181 : expressions.
5182 : */
5183 :
5184 : static void CheckDivModRem (unsigned int TokPos, NameKey_Name tok, unsigned int d, unsigned int e);
5185 :
5186 : /*
5187 : doConvert - convert, sym, to a new symbol with, type.
5188 : Return the new symbol.
5189 : */
5190 :
5191 : static unsigned int doConvert (unsigned int type, unsigned int sym);
5192 :
5193 : /*
5194 : doBuildBinaryOp - build the binary op, with or without type
5195 : checking.
5196 : */
5197 :
5198 : static void doBuildBinaryOp (bool checkTypes, bool checkOverflow);
5199 :
5200 : /*
5201 : AreConstant - returns immediate addressing mode if b is true else
5202 : offset mode is returned. b determines whether the
5203 : operands are all constant - in which case we can use
5204 : a constant temporary variable.
5205 : */
5206 :
5207 : static SymbolTable_ModeOfAddr AreConstant (bool b);
5208 :
5209 : /*
5210 : ConvertBooleanToVariable - converts a BoolStack(i) from a Boolean True|False
5211 : exit pair into a variable containing the value TRUE or
5212 : FALSE. The parameter i is relative to the top
5213 : of the stack.
5214 : */
5215 :
5216 : static void ConvertBooleanToVariable (unsigned int tok, unsigned int i);
5217 :
5218 : /*
5219 : DumpQuadSummary -
5220 : */
5221 :
5222 : static void DumpQuadSummary (unsigned int quad);
5223 :
5224 : /*
5225 : BuildRelOpFromBoolean - builds a relational operator sequence of quadruples
5226 : instead of using a temporary boolean variable.
5227 : This function can only be used when we perform
5228 : the following translation:
5229 :
5230 : (a=b) # (c=d) alternatively (a=b) = (c=d)
5231 : ^ ^
5232 :
5233 : it only allows # = to be used as >= <= > < all
5234 : assume a particular value for TRUE and FALSE.
5235 : (In which case the user should specify ORD)
5236 :
5237 :
5238 : before
5239 :
5240 : q if r1 op1 op2 t2
5241 : q+1 Goto f2
5242 : ...
5243 : q+n if r2 op3 op4 t1
5244 : q+n+1 Goto f1
5245 :
5246 : after (in case of =)
5247 :
5248 : q if r1 op1 op2 q+2
5249 : q+1 Goto q+4
5250 : q+2 if r2 op3 op4 t
5251 : q+3 Goto f
5252 : q+4 if r2 op3 op4 f
5253 : q+5 Goto t
5254 :
5255 : after (in case of #)
5256 :
5257 : q if r1 op1 op2 q+2
5258 : q+1 Goto q+n+2
5259 : q+2 ...
5260 : ... ...
5261 : q+n if r2 op3 op4 f
5262 : q+n+1 Goto t
5263 : q+n+2 if r2 op3 op4 t
5264 : q+n+3 Goto f
5265 :
5266 : The Stack is expected to contain:
5267 :
5268 :
5269 : Entry Exit
5270 : ===== ====
5271 :
5272 : Ptr ->
5273 : +------------+
5274 : | t1 | f1 |
5275 : |------------|
5276 : | Operator | <- Ptr
5277 : |------------| +------------+
5278 : | t2 | f2 | | t | f |
5279 : |------------| |------------|
5280 :
5281 :
5282 : */
5283 :
5284 : static void BuildRelOpFromBoolean (unsigned int tokpos);
5285 :
5286 : /*
5287 : CheckVariableOrConstantOrProcedure - checks to make sure sym is a variable, constant or procedure.
5288 : */
5289 :
5290 : static void CheckVariableOrConstantOrProcedure (unsigned int tokpos, unsigned int sym);
5291 :
5292 : /*
5293 : MakeOp - returns the equalent quadruple operator to a token, t.
5294 : */
5295 :
5296 : static M2Quads_QuadOperator MakeOp (NameKey_Name t);
5297 :
5298 : /*
5299 : GenQuadO - generate a quadruple with Operation, Op1, Op2, Op3, overflow.
5300 : */
5301 :
5302 : static void GenQuadO (unsigned int TokPos, M2Quads_QuadOperator Operation, unsigned int Op1, unsigned int Op2, unsigned int Op3, bool overflow);
5303 :
5304 : /*
5305 : GenQuadOTrash - generate a quadruple with Operation, Op1, Op2, Op3, overflow.
5306 : */
5307 :
5308 : static void GenQuadOTrash (unsigned int TokPos, M2Quads_QuadOperator Operation, unsigned int Op1, unsigned int Op2, unsigned int Op3, bool overflow, unsigned int trash);
5309 :
5310 : /*
5311 : GenQuad - Generate a quadruple with Operation, Op1, Op2, Op3.
5312 : */
5313 :
5314 : static void GenQuad (M2Quads_QuadOperator Operation, unsigned int Op1, unsigned int Op2, unsigned int Op3);
5315 :
5316 : /*
5317 : GenQuadOtok - generate a quadruple with Operation, Op1, Op2, Op3, overflow.
5318 : */
5319 :
5320 : static void GenQuadOtok (unsigned int TokPos, M2Quads_QuadOperator Operation, unsigned int Op1, unsigned int Op2, unsigned int Op3, bool overflow, unsigned int Op1Pos, unsigned int Op2Pos, unsigned int Op3Pos);
5321 :
5322 : /*
5323 : GenQuadOTypetok - assigns the fields of the quadruple with
5324 : the parameters.
5325 : */
5326 :
5327 : static void GenQuadOTypetok (unsigned int TokPos, M2Quads_QuadOperator Operation, unsigned int Op1, unsigned int Op2, unsigned int Op3, bool overflow, bool typecheck, unsigned int Op1Pos, unsigned int Op2Pos, unsigned int Op3Pos);
5328 :
5329 : /*
5330 : DumpUntil - dump all quadruples until we seen the ending quadruple
5331 : with procsym in the third operand.
5332 : Return the quad number containing the match.
5333 : */
5334 :
5335 : static unsigned int DumpUntil (M2Quads_QuadOperator ending, unsigned int procsym, unsigned int quad);
5336 :
5337 : /*
5338 : GetCtorInit - return the init procedure for the module.
5339 : */
5340 :
5341 : static unsigned int GetCtorInit (unsigned int sym);
5342 :
5343 : /*
5344 : GetCtorFini - return the fini procedure for the module.
5345 : */
5346 :
5347 : static unsigned int GetCtorFini (unsigned int sym);
5348 :
5349 : /*
5350 : DumpQuadrupleFilter -
5351 : */
5352 :
5353 : static void DumpQuadrupleFilter (void);
5354 :
5355 : /*
5356 : DumpQuadrupleAll - dump all quadruples.
5357 : */
5358 :
5359 : static void DumpQuadrupleAll (void);
5360 :
5361 : /*
5362 : BackPatch - Makes each of the quadruples on the list pointed to by
5363 : QuadNo take quadruple Value as a target.
5364 : */
5365 :
5366 : static void BackPatch (unsigned int QuadNo, unsigned int Value);
5367 :
5368 : /*
5369 : Merge - joins two quad lists, QuadList2 to the end of QuadList1.
5370 : A QuadList of value zero is a nul list.
5371 : */
5372 :
5373 : static unsigned int Merge (unsigned int QuadList1, unsigned int QuadList2);
5374 :
5375 : /*
5376 : DisplayProcedureAttributes -
5377 : */
5378 :
5379 : static void DisplayProcedureAttributes (unsigned int proc);
5380 :
5381 : /*
5382 : WriteQuad - Writes out the Quad BufferQuad.
5383 : */
5384 :
5385 : static void WriteQuad (unsigned int BufferQuad);
5386 :
5387 : /*
5388 : WriteOperand - displays the operands name, symbol id and mode of addressing.
5389 : */
5390 :
5391 : static void WriteMode (SymbolTable_ModeOfAddr Mode);
5392 :
5393 : /*
5394 : PushExit - pushes the exit value onto the EXIT stack.
5395 : */
5396 :
5397 : static void PushExit (unsigned int Exit);
5398 :
5399 : /*
5400 : PopExit - pops the exit value from the EXIT stack.
5401 : */
5402 :
5403 : static unsigned int PopExit (void);
5404 :
5405 : /*
5406 : PushFor - pushes the exit value onto the FOR stack.
5407 : */
5408 :
5409 : static void PushFor (unsigned int Exit);
5410 :
5411 : /*
5412 : PopFor - pops the exit value from the FOR stack.
5413 : */
5414 :
5415 : static unsigned int PopFor (void);
5416 :
5417 : /*
5418 : OperandTno - returns the ident operand stored in the true position
5419 : on the boolean stack. This is exactly the same as
5420 : OperandT but it has no IsBoolean checking.
5421 : */
5422 :
5423 : static unsigned int OperandTno (unsigned int pos);
5424 :
5425 : /*
5426 : OperandFno - returns the ident operand stored in the false position
5427 : on the boolean stack. This is exactly the same as
5428 : OperandF but it has no IsBoolean checking.
5429 : */
5430 :
5431 : static unsigned int OperandFno (unsigned int pos);
5432 :
5433 : /*
5434 : OperandTtok - returns the token associated with the position, pos
5435 : on the boolean stack.
5436 : */
5437 :
5438 : static unsigned int OperandTtok (unsigned int pos);
5439 :
5440 : /*
5441 : PopBooltok - Pops a True and a False exit quad number from the True/False
5442 : stack.
5443 : */
5444 :
5445 : static void PopBooltok (unsigned int *True, unsigned int *False, unsigned int *tokno);
5446 :
5447 : /*
5448 : PushBooltok - Push a True and a False exit quad numbers onto the
5449 : True/False stack.
5450 : */
5451 :
5452 : static void PushBooltok (unsigned int True, unsigned int False, unsigned int tokno);
5453 :
5454 : /*
5455 : PopBool - Pops a True and a False exit quad number from the True/False
5456 : stack.
5457 : */
5458 :
5459 : static void PopBool (unsigned int *True, unsigned int *False);
5460 :
5461 : /*
5462 : PushBool - Push a True and a False exit quad numbers onto the
5463 : True/False stack.
5464 : */
5465 :
5466 : static void PushBool (unsigned int True, unsigned int False);
5467 :
5468 : /*
5469 : IsBoolean - returns true is the Stack position pos contains a Boolean
5470 : Exit. False is returned if an Ident is stored.
5471 : */
5472 :
5473 : static bool IsBoolean (unsigned int pos);
5474 :
5475 : /*
5476 : OperandD - returns possible array dimension associated with the ident
5477 : operand stored on the boolean stack.
5478 : */
5479 :
5480 : static unsigned int OperandD (unsigned int pos);
5481 :
5482 : /*
5483 : OperandRW - returns the rw operand stored on the boolean stack.
5484 : */
5485 :
5486 : static unsigned int OperandRW (unsigned int pos);
5487 :
5488 : /*
5489 : OperandMergeRW - returns the rw operand if not NulSym else it
5490 : returns True.
5491 : */
5492 :
5493 : static unsigned int OperandMergeRW (unsigned int pos);
5494 :
5495 : /*
5496 : OperandRangeDep - return the range dependant associated with the quad stack.
5497 : */
5498 :
5499 : static unsigned int OperandRangeDep (unsigned int pos);
5500 :
5501 : /*
5502 : PutRangeDep - assigns the quad stack pos RangeDep to dep.
5503 : */
5504 :
5505 : static void PutRangeDep (unsigned int pos, unsigned int dep);
5506 :
5507 : /*
5508 : UseLineNote - uses the line note and returns it to the free list.
5509 : */
5510 :
5511 : static void UseLineNote (M2Quads_LineNote l);
5512 :
5513 : /*
5514 : PopLineNo - pops a line note from the line stack.
5515 : */
5516 :
5517 : static M2Quads_LineNote PopLineNo (void);
5518 :
5519 : /*
5520 : InitLineNote - creates a line note and initializes it to
5521 : contain, file, line.
5522 : */
5523 :
5524 : static M2Quads_LineNote InitLineNote (NameKey_Name file, unsigned int line);
5525 :
5526 : /*
5527 : PushLineNote -
5528 : */
5529 :
5530 : static void PushLineNote (M2Quads_LineNote l);
5531 :
5532 : /*
5533 : BuildStmtNoteTok - adds a nop (with an assigned tokenno location) to the code.
5534 : */
5535 :
5536 : static void BuildStmtNoteTok (unsigned int tokenno);
5537 :
5538 : /*
5539 : GetRecordOrField -
5540 : */
5541 :
5542 : static unsigned int GetRecordOrField (void);
5543 :
5544 : /*
5545 : PushTFAD - Push True, False, Array, Dim, numbers onto the
5546 : True/False stack. True and False are assumed to
5547 : contain Symbols or Ident etc.
5548 : */
5549 :
5550 : static void PushTFAD (unsigned int True, unsigned int False, unsigned int Array, unsigned int Dim);
5551 :
5552 : /*
5553 : PushTFADtok - Push True, False, Array, Dim, numbers onto the
5554 : True/False stack. True and False are assumed to
5555 : contain Symbols or Ident etc.
5556 : */
5557 :
5558 : static void PushTFADtok (unsigned int True, unsigned int False, unsigned int Array, unsigned int Dim, unsigned int tokno);
5559 :
5560 : /*
5561 : PushTFADrwtok - Push True, False, Array, Dim, rw, numbers onto the
5562 : True/False stack. True and False are assumed to
5563 : contain Symbols or Ident etc.
5564 : */
5565 :
5566 : static void PushTFADrwtok (unsigned int True, unsigned int False, unsigned int Array, unsigned int Dim, unsigned int rw, unsigned int Tok);
5567 :
5568 : /*
5569 : PopTFrwtok - Pop a True and False number from the True/False stack.
5570 : True and False are assumed to contain Symbols or Ident etc.
5571 : */
5572 :
5573 : static void PopTFrwtok (unsigned int *True, unsigned int *False, unsigned int *rw, unsigned int *tokno);
5574 :
5575 : /*
5576 : PushTFrwtok - Push an item onto the stack in the T (true) position,
5577 : it is assummed to be a token and its token location is recorded.
5578 : */
5579 :
5580 : static void PushTFrwtok (unsigned int True, unsigned int False, unsigned int rw, unsigned int tokno);
5581 :
5582 : /*
5583 : PushTFDtok - Push True, False, Dim, numbers onto the
5584 : True/False stack. True and False are assumed to
5585 : contain Symbols or Ident etc.
5586 : */
5587 :
5588 : static void PushTFDtok (unsigned int True, unsigned int False, unsigned int Dim, unsigned int Tok);
5589 :
5590 : /*
5591 : PopTFDtok - Pop a True, False, Dim number from the True/False stack.
5592 : True and False are assumed to contain Symbols or Ident etc.
5593 : */
5594 :
5595 : static void PopTFDtok (unsigned int *True, unsigned int *False, unsigned int *Dim, unsigned int *Tok);
5596 :
5597 : /*
5598 : PushTFDrwtok - Push True, False, Dim, numbers onto the
5599 : True/False stack. True and False are assumed to
5600 : contain Symbols or Ident etc.
5601 : */
5602 :
5603 : static void PushTFDrwtok (unsigned int True, unsigned int False, unsigned int Dim, unsigned int rw, unsigned int Tok);
5604 :
5605 : /*
5606 : PushTFrw - Push a True and False numbers onto the True/False stack.
5607 : True and False are assumed to contain Symbols or Ident etc.
5608 : It also pushes the higher level symbol which is associated
5609 : with the True symbol. Eg record variable or array variable.
5610 : */
5611 :
5612 : static void PushTFrw (unsigned int True, unsigned int False, unsigned int rw);
5613 :
5614 : /*
5615 : PopTFrw - Pop a True and False number from the True/False stack.
5616 : True and False are assumed to contain Symbols or Ident etc.
5617 : */
5618 :
5619 : static void PopTFrw (unsigned int *True, unsigned int *False, unsigned int *rw);
5620 :
5621 : /*
5622 : newBoolFrame - creates a new BoolFrame with all fields initialised to their defaults.
5623 : */
5624 :
5625 : static M2Quads_BoolFrame newBoolFrame (void);
5626 :
5627 : /*
5628 : PushTrwtok - Push an item onto the True/False stack. The False value will be zero.
5629 : */
5630 :
5631 : static void PushTrwtok (unsigned int True, unsigned int rw, unsigned int tok);
5632 :
5633 : /*
5634 : PopTrw - Pop a True field and rw symbol from the stack.
5635 : */
5636 :
5637 : static void PopTrw (unsigned int *True, unsigned int *rw);
5638 :
5639 : /*
5640 : PopTrwtok - Pop a True field and rw symbol from the stack.
5641 : */
5642 :
5643 : static void PopTrwtok (unsigned int *True, unsigned int *rw, unsigned int *tok);
5644 :
5645 : /*
5646 : gdbhook - a debugger convenience hook.
5647 : */
5648 :
5649 : static void gdbhook (void);
5650 :
5651 : /*
5652 : BreakWhenQuadCreated - to be called interactively by gdb.
5653 : */
5654 :
5655 : static void BreakWhenQuadCreated (unsigned int quad);
5656 :
5657 : /*
5658 : CheckBreak - if quad = BreakQuad then call gdbhook.
5659 : */
5660 :
5661 : static void CheckBreak (unsigned int quad);
5662 :
5663 : /*
5664 : Init - initialize the M2Quads module, all the stacks, all the lists
5665 : and the quads list.
5666 : */
5667 :
5668 : static void Init (void);
5669 :
5670 :
5671 : /*
5672 : DSdbEnter -
5673 : */
5674 :
5675 0 : static void DSdbEnter (void)
5676 : {
5677 0 : }
5678 :
5679 :
5680 : /*
5681 : DSdbExit -
5682 : */
5683 :
5684 0 : static void DSdbExit (void)
5685 : {
5686 0 : }
5687 :
5688 :
5689 : /*
5690 : GetQF - returns the QuadFrame associated with, q.
5691 : */
5692 :
5693 14295715828 : static M2Quads_QuadFrame GetQF (unsigned int q)
5694 : {
5695 0 : return (M2Quads_QuadFrame) (Indexing_GetIndice (QuadArray, q));
5696 : /* static analysis guarentees a RETURN statement will be used before here. */
5697 : __builtin_unreachable ();
5698 : }
5699 :
5700 :
5701 : /*
5702 : IsQuadA - returns true if QuadNo is a op.
5703 : */
5704 :
5705 1057897666 : static bool IsQuadA (unsigned int QuadNo, M2Quads_QuadOperator op)
5706 : {
5707 1057897666 : M2Quads_QuadFrame f;
5708 :
5709 0 : f = GetQF (QuadNo);
5710 1057897666 : return f->Operator == op;
5711 : /* static analysis guarentees a RETURN statement will be used before here. */
5712 : __builtin_unreachable ();
5713 : }
5714 :
5715 :
5716 : /*
5717 : OpUsesOp1 - return TRUE if op allows op1.
5718 : */
5719 :
5720 425884 : static bool OpUsesOp1 (M2Quads_QuadOperator op)
5721 : {
5722 425884 : switch (op)
5723 : {
5724 : case M2Quads_StringConvertCnulOp:
5725 : case M2Quads_StringConvertM2nulOp:
5726 : case M2Quads_StringLengthOp:
5727 : case M2Quads_InclOp:
5728 : case M2Quads_ExclOp:
5729 : case M2Quads_UnboundedOp:
5730 : case M2Quads_FunctValueOp:
5731 : case M2Quads_NegateOp:
5732 : case M2Quads_BecomesOp:
5733 : case M2Quads_HighOp:
5734 : case M2Quads_SizeOp:
5735 : case M2Quads_AddrOp:
5736 : case M2Quads_RecordFieldOp:
5737 : case M2Quads_ArrayOp:
5738 : case M2Quads_LogicalShiftOp:
5739 : case M2Quads_LogicalRotateOp:
5740 : case M2Quads_LogicalOrOp:
5741 : case M2Quads_LogicalAndOp:
5742 : case M2Quads_LogicalXorOp:
5743 : case M2Quads_CoerceOp:
5744 : case M2Quads_ConvertOp:
5745 : case M2Quads_CastOp:
5746 : case M2Quads_AddOp:
5747 : case M2Quads_SubOp:
5748 : case M2Quads_MultOp:
5749 : case M2Quads_ModFloorOp:
5750 : case M2Quads_DivCeilOp:
5751 : case M2Quads_ModCeilOp:
5752 : case M2Quads_DivFloorOp:
5753 : case M2Quads_ModTruncOp:
5754 : case M2Quads_DivTruncOp:
5755 : case M2Quads_DivM2Op:
5756 : case M2Quads_ModM2Op:
5757 : case M2Quads_XIndrOp:
5758 : case M2Quads_IndrXOp:
5759 : case M2Quads_SaveExceptionOp:
5760 : case M2Quads_RestoreExceptionOp:
5761 : return true;
5762 100788 : break;
5763 :
5764 :
5765 100788 : default:
5766 100788 : return false;
5767 : break;
5768 : }
5769 : /* static analysis guarentees a RETURN statement will be used before here. */
5770 : __builtin_unreachable ();
5771 : }
5772 :
5773 :
5774 : /*
5775 : AddQuadInformation - adds variable analysis and jump analysis to the new quadruple.
5776 : */
5777 :
5778 6411484 : static void AddQuadInformation (unsigned int QuadNo, M2Quads_QuadOperator Op, unsigned int Oper1, unsigned int Oper2, unsigned int Oper3)
5779 : {
5780 6411484 : switch (Op)
5781 : {
5782 177961 : case M2Quads_IfInOp:
5783 177961 : case M2Quads_IfNotInOp:
5784 177961 : case M2Quads_IfEquOp:
5785 177961 : case M2Quads_IfNotEquOp:
5786 177961 : case M2Quads_IfLessOp:
5787 177961 : case M2Quads_IfLessEquOp:
5788 177961 : case M2Quads_IfGreOp:
5789 177961 : case M2Quads_IfGreEquOp:
5790 177961 : ManipulateReference (QuadNo, Oper3);
5791 177961 : CheckAddVariableRead (Oper1, false, QuadNo);
5792 177961 : CheckAddVariableRead (Oper2, false, QuadNo);
5793 177961 : break;
5794 :
5795 2586 : case M2Quads_LastForIteratorOp:
5796 2586 : CheckAddVariableWrite (Oper1, false, QuadNo);
5797 2586 : CheckAddTuple2Read (Oper2, false, QuadNo);
5798 2586 : CheckAddVariableRead (Oper3, false, QuadNo);
5799 2586 : break;
5800 :
5801 187188 : case M2Quads_TryOp:
5802 187188 : case M2Quads_RetryOp:
5803 187188 : case M2Quads_GotoOp:
5804 187188 : ManipulateReference (QuadNo, Oper3);
5805 187188 : break;
5806 :
5807 2020 : case M2Quads_InclOp:
5808 2020 : case M2Quads_ExclOp:
5809 : /* variable references */
5810 2020 : CheckConst (Oper1);
5811 2020 : CheckAddVariableRead (Oper3, false, QuadNo);
5812 2020 : CheckAddVariableWrite (Oper1, true, QuadNo);
5813 2020 : break;
5814 :
5815 679458 : case M2Quads_UnboundedOp:
5816 679458 : case M2Quads_FunctValueOp:
5817 679458 : case M2Quads_NegateOp:
5818 679458 : case M2Quads_BecomesOp:
5819 679458 : case M2Quads_HighOp:
5820 679458 : case M2Quads_SizeOp:
5821 679458 : CheckConst (Oper1);
5822 679458 : CheckAddVariableWrite (Oper1, false, QuadNo);
5823 679458 : CheckAddVariableRead (Oper3, false, QuadNo);
5824 679458 : break;
5825 :
5826 198458 : case M2Quads_AddrOp:
5827 198458 : CheckConst (Oper1);
5828 198458 : CheckAddVariableWrite (Oper1, false, QuadNo);
5829 : /* the next line is a kludge and assumes we _will_
5830 : write to the variable as we have taken its address */
5831 198458 : CheckRemoveVariableWrite (Oper1, true, QuadNo);
5832 198458 : break;
5833 :
5834 28111 : case M2Quads_ReturnValueOp:
5835 28111 : CheckAddVariableRead (Oper1, false, QuadNo);
5836 28111 : break;
5837 :
5838 : case M2Quads_ReturnOp:
5839 : case M2Quads_NewLocalVarOp:
5840 : case M2Quads_KillLocalVarOp:
5841 : break;
5842 :
5843 220622 : case M2Quads_CallOp:
5844 220622 : CheckAddVariableRead (Oper3, true, QuadNo);
5845 220622 : break;
5846 :
5847 618640 : case M2Quads_ParamOp:
5848 618640 : CheckAddVariableRead (Oper2, false, QuadNo);
5849 618640 : CheckAddVariableRead (Oper3, false, QuadNo);
5850 618640 : if (((Oper1 > 0) && (Oper1 <= (SymbolTable_NoOfParamAny (Oper2)))) && (SymbolTable_IsVarParamAny (Oper2, Oper1)))
5851 : {
5852 : /* _may_ also write to a var parameter, although we dont know */
5853 20486 : CheckAddVariableWrite (Oper3, true, QuadNo);
5854 : }
5855 : break;
5856 :
5857 361043 : case M2Quads_RecordFieldOp:
5858 361043 : case M2Quads_ArrayOp:
5859 361043 : case M2Quads_LogicalShiftOp:
5860 361043 : case M2Quads_LogicalRotateOp:
5861 361043 : case M2Quads_LogicalOrOp:
5862 361043 : case M2Quads_LogicalAndOp:
5863 361043 : case M2Quads_LogicalXorOp:
5864 361043 : case M2Quads_CoerceOp:
5865 361043 : case M2Quads_ConvertOp:
5866 361043 : case M2Quads_CastOp:
5867 361043 : case M2Quads_AddOp:
5868 361043 : case M2Quads_SubOp:
5869 361043 : case M2Quads_MultOp:
5870 361043 : case M2Quads_DivM2Op:
5871 361043 : case M2Quads_ModM2Op:
5872 361043 : case M2Quads_ModFloorOp:
5873 361043 : case M2Quads_DivCeilOp:
5874 361043 : case M2Quads_ModCeilOp:
5875 361043 : case M2Quads_DivFloorOp:
5876 361043 : case M2Quads_ModTruncOp:
5877 361043 : case M2Quads_DivTruncOp:
5878 361043 : CheckConst (Oper1);
5879 361043 : CheckAddVariableWrite (Oper1, false, QuadNo);
5880 361043 : CheckAddVariableRead (Oper2, false, QuadNo);
5881 361043 : CheckAddVariableRead (Oper3, false, QuadNo);
5882 361043 : break;
5883 :
5884 43640 : case M2Quads_XIndrOp:
5885 43640 : CheckConst (Oper1);
5886 43640 : CheckAddVariableWrite (Oper1, true, QuadNo);
5887 43640 : CheckAddVariableRead (Oper3, false, QuadNo);
5888 43640 : break;
5889 :
5890 17449 : case M2Quads_IndrXOp:
5891 17449 : CheckConst (Oper1);
5892 17449 : CheckAddVariableWrite (Oper1, false, QuadNo);
5893 17449 : CheckAddVariableRead (Oper3, true, QuadNo);
5894 17449 : break;
5895 :
5896 2969 : case M2Quads_SaveExceptionOp:
5897 : /* RangeCheckOp : CheckRangeAddVariableRead(Oper3, QuadNo) | */
5898 2969 : CheckConst (Oper1);
5899 2969 : CheckAddVariableWrite (Oper1, false, QuadNo);
5900 2969 : break;
5901 :
5902 3131 : case M2Quads_RestoreExceptionOp:
5903 3131 : CheckAddVariableRead (Oper1, false, QuadNo);
5904 3131 : break;
5905 :
5906 :
5907 : default:
5908 : break;
5909 : }
5910 6411484 : }
5911 :
5912 :
5913 : /*
5914 : PutQuadO - alters a quadruple QuadNo with Op, Oper1, Oper2, Oper3, and
5915 : sets a boolean to determinine whether overflow should be checked.
5916 : */
5917 :
5918 5447607 : static void PutQuadO (unsigned int QuadNo, M2Quads_QuadOperator Op, unsigned int Oper1, unsigned int Oper2, unsigned int Oper3, bool overflow)
5919 : {
5920 0 : PutQuadOType (QuadNo, Op, Oper1, Oper2, Oper3, overflow, true);
5921 0 : }
5922 :
5923 :
5924 : /*
5925 : PutQuadOType -
5926 : */
5927 :
5928 6329303 : static void PutQuadOType (unsigned int QuadNo, M2Quads_QuadOperator Op, unsigned int Oper1, unsigned int Oper2, unsigned int Oper3, bool overflow, bool checktype)
5929 : {
5930 6329303 : M2Quads_QuadFrame f;
5931 :
5932 6329303 : if (QuadrupleGeneration)
5933 : {
5934 6329303 : M2Quads_EraseQuad (QuadNo);
5935 6329303 : AddQuadInformation (QuadNo, Op, Oper1, Oper2, Oper3);
5936 6329303 : f = GetQF (QuadNo);
5937 6329303 : f->Operator = Op;
5938 6329303 : f->Operand1 = Oper1;
5939 6329303 : f->Operand2 = Oper2;
5940 6329303 : f->Operand3 = Oper3;
5941 6329303 : f->CheckOverflow = overflow;
5942 6329303 : f->CheckType = checktype;
5943 6329303 : f->ConstExpr = false; /* IsInConstExpression () */
5944 : }
5945 : /* IsInConstExpression () */
5946 6329303 : }
5947 :
5948 :
5949 : /*
5950 : UndoReadWriteInfo -
5951 : */
5952 :
5953 8340045 : static void UndoReadWriteInfo (unsigned int QuadNo, M2Quads_QuadOperator Op, unsigned int Oper1, unsigned int Oper2, unsigned int Oper3)
5954 : {
5955 8340045 : switch (Op)
5956 : {
5957 98046 : case M2Quads_IfInOp:
5958 98046 : case M2Quads_IfNotInOp:
5959 98046 : case M2Quads_IfEquOp:
5960 98046 : case M2Quads_IfNotEquOp:
5961 98046 : case M2Quads_IfLessOp:
5962 98046 : case M2Quads_IfLessEquOp:
5963 98046 : case M2Quads_IfGreOp:
5964 98046 : case M2Quads_IfGreEquOp:
5965 : /* jumps, calls and branches */
5966 98046 : RemoveReference (QuadNo);
5967 98046 : CheckRemoveVariableRead (Oper1, false, QuadNo);
5968 98046 : CheckRemoveVariableRead (Oper2, false, QuadNo);
5969 98046 : break;
5970 :
5971 137259 : case M2Quads_TryOp:
5972 137259 : case M2Quads_RetryOp:
5973 137259 : case M2Quads_GotoOp:
5974 137259 : RemoveReference (QuadNo);
5975 137259 : break;
5976 :
5977 0 : case M2Quads_InclOp:
5978 0 : case M2Quads_ExclOp:
5979 : /* variable references */
5980 0 : CheckRemoveVariableRead (Oper1, false, QuadNo);
5981 0 : CheckRemoveVariableWrite (Oper1, true, QuadNo);
5982 0 : break;
5983 :
5984 336945 : case M2Quads_UnboundedOp:
5985 336945 : case M2Quads_FunctValueOp:
5986 336945 : case M2Quads_NegateOp:
5987 336945 : case M2Quads_BecomesOp:
5988 336945 : case M2Quads_HighOp:
5989 336945 : case M2Quads_SizeOp:
5990 336945 : CheckRemoveVariableWrite (Oper1, false, QuadNo);
5991 336945 : CheckRemoveVariableRead (Oper3, false, QuadNo);
5992 336945 : break;
5993 :
5994 1630 : case M2Quads_AddrOp:
5995 1630 : CheckRemoveVariableWrite (Oper1, false, QuadNo);
5996 : /* the next line is a kludge and assumes we _will_
5997 : write to the variable as we have taken its address */
5998 1630 : CheckRemoveVariableWrite (Oper1, true, QuadNo);
5999 1630 : break;
6000 :
6001 184 : case M2Quads_ReturnValueOp:
6002 184 : CheckRemoveVariableRead (Oper1, false, QuadNo);
6003 184 : break;
6004 :
6005 : case M2Quads_ReturnOp:
6006 : case M2Quads_CallOp:
6007 : case M2Quads_NewLocalVarOp:
6008 : case M2Quads_KillLocalVarOp:
6009 : break;
6010 :
6011 11254 : case M2Quads_ParamOp:
6012 11254 : CheckRemoveVariableRead (Oper2, false, QuadNo);
6013 11254 : CheckRemoveVariableRead (Oper3, false, QuadNo);
6014 11254 : if (((Oper1 > 0) && (Oper1 <= (SymbolTable_NoOfParamAny (Oper2)))) && (SymbolTable_IsVarParamAny (Oper2, Oper1)))
6015 : {
6016 : /* _may_ also write to a var parameter, although we dont know */
6017 112 : CheckRemoveVariableWrite (Oper3, true, QuadNo);
6018 : }
6019 : break;
6020 :
6021 50688 : case M2Quads_RecordFieldOp:
6022 50688 : case M2Quads_ArrayOp:
6023 50688 : case M2Quads_LogicalShiftOp:
6024 50688 : case M2Quads_LogicalRotateOp:
6025 50688 : case M2Quads_LogicalOrOp:
6026 50688 : case M2Quads_LogicalAndOp:
6027 50688 : case M2Quads_LogicalXorOp:
6028 50688 : case M2Quads_CoerceOp:
6029 50688 : case M2Quads_ConvertOp:
6030 50688 : case M2Quads_CastOp:
6031 50688 : case M2Quads_AddOp:
6032 50688 : case M2Quads_SubOp:
6033 50688 : case M2Quads_MultOp:
6034 50688 : case M2Quads_DivM2Op:
6035 50688 : case M2Quads_ModM2Op:
6036 50688 : case M2Quads_ModFloorOp:
6037 50688 : case M2Quads_DivCeilOp:
6038 50688 : case M2Quads_ModCeilOp:
6039 50688 : case M2Quads_DivFloorOp:
6040 50688 : case M2Quads_ModTruncOp:
6041 50688 : case M2Quads_DivTruncOp:
6042 50688 : CheckRemoveVariableWrite (Oper1, false, QuadNo);
6043 50688 : CheckRemoveVariableRead (Oper2, false, QuadNo);
6044 50688 : CheckRemoveVariableRead (Oper3, false, QuadNo);
6045 50688 : break;
6046 :
6047 4 : case M2Quads_XIndrOp:
6048 4 : CheckRemoveVariableWrite (Oper1, true, QuadNo);
6049 4 : CheckRemoveVariableRead (Oper3, false, QuadNo);
6050 4 : break;
6051 :
6052 450 : case M2Quads_IndrXOp:
6053 450 : CheckRemoveVariableWrite (Oper1, false, QuadNo);
6054 450 : CheckRemoveVariableRead (Oper3, true, QuadNo);
6055 450 : break;
6056 :
6057 0 : case M2Quads_SaveExceptionOp:
6058 : /* RangeCheckOp : CheckRangeRemoveVariableRead(Oper3, QuadNo) | */
6059 0 : CheckRemoveVariableWrite (Oper1, false, QuadNo);
6060 0 : break;
6061 :
6062 216 : case M2Quads_RestoreExceptionOp:
6063 216 : CheckRemoveVariableRead (Oper1, false, QuadNo);
6064 216 : break;
6065 :
6066 :
6067 : default:
6068 : break;
6069 : }
6070 8340045 : }
6071 :
6072 :
6073 : /*
6074 : CheckAddTuple2Read - checks to see whether symbol tuple contains variables or
6075 : parameters and if so it then adds them to the quadruple
6076 : variable list.
6077 : */
6078 :
6079 2586 : static void CheckAddTuple2Read (unsigned int tuple, bool canDereference, unsigned int Quad)
6080 : {
6081 2586 : if (SymbolTable_IsTuple (tuple))
6082 : {
6083 2586 : CheckAddVariableRead (SymbolTable_GetNth (tuple, 1), canDereference, Quad);
6084 2586 : CheckAddVariableRead (SymbolTable_GetNth (tuple, 2), canDereference, Quad);
6085 : }
6086 2586 : }
6087 :
6088 :
6089 : /*
6090 : CheckAddVariableRead - checks to see whether symbol, Sym, is a variable or
6091 : a parameter and if so it then adds this quadruple
6092 : to the variable list.
6093 : */
6094 :
6095 3317477 : static void CheckAddVariableRead (unsigned int Sym, bool canDereference, unsigned int Quad)
6096 : {
6097 3317477 : if (SymbolTable_IsVar (Sym))
6098 : {
6099 1181619 : SymbolTable_PutReadQuad (Sym, SymbolTable_GetMode (Sym), Quad);
6100 1181619 : if (((SymbolTable_GetMode (Sym)) == SymbolTable_LeftValue) && canDereference)
6101 : {
6102 17517 : SymbolTable_PutReadQuad (Sym, SymbolTable_RightValue, Quad);
6103 : }
6104 : }
6105 3317477 : }
6106 :
6107 :
6108 : /*
6109 : CheckRemoveVariableRead - checks to see whether, Sym, is a variable or
6110 : a parameter and if so then it removes the
6111 : quadruple from the variable list.
6112 : */
6113 :
6114 657775 : static void CheckRemoveVariableRead (unsigned int Sym, bool canDereference, unsigned int Quad)
6115 : {
6116 657775 : if (SymbolTable_IsVar (Sym))
6117 : {
6118 124100 : SymbolTable_RemoveReadQuad (Sym, SymbolTable_GetMode (Sym), Quad);
6119 124100 : if (((SymbolTable_GetMode (Sym)) == SymbolTable_LeftValue) && canDereference)
6120 : {
6121 450 : SymbolTable_RemoveReadQuad (Sym, SymbolTable_RightValue, Quad);
6122 : }
6123 : }
6124 657775 : }
6125 :
6126 :
6127 : /*
6128 : CheckAddVariableWrite - checks to see whether symbol, Sym, is a variable and
6129 : if so it then adds this quadruple to the variable list.
6130 : */
6131 :
6132 1328109 : static void CheckAddVariableWrite (unsigned int Sym, bool canDereference, unsigned int Quad)
6133 : {
6134 1328109 : if (SymbolTable_IsVar (Sym))
6135 : {
6136 : /* avoid gcc warning by using compound statement even if not strictly necessary. */
6137 953879 : if (((SymbolTable_GetMode (Sym)) == SymbolTable_LeftValue) && canDereference)
6138 : {
6139 60022 : SymbolTable_PutReadQuad (Sym, SymbolTable_LeftValue, Quad);
6140 60022 : SymbolTable_PutWriteQuad (Sym, SymbolTable_RightValue, Quad);
6141 : }
6142 : else
6143 : {
6144 893857 : SymbolTable_PutWriteQuad (Sym, SymbolTable_GetMode (Sym), Quad);
6145 : }
6146 : }
6147 1328109 : }
6148 :
6149 :
6150 : /*
6151 : CheckRemoveVariableWrite - checks to see whether, Sym, is a variable and
6152 : if so then it removes the quadruple from the
6153 : variable list.
6154 : */
6155 :
6156 589917 : static void CheckRemoveVariableWrite (unsigned int Sym, bool canDereference, unsigned int Quad)
6157 : {
6158 589917 : if (SymbolTable_IsVar (Sym))
6159 : {
6160 : /* avoid gcc warning by using compound statement even if not strictly necessary. */
6161 219836 : if (((SymbolTable_GetMode (Sym)) == SymbolTable_LeftValue) && canDereference)
6162 : {
6163 11374 : SymbolTable_RemoveReadQuad (Sym, SymbolTable_LeftValue, Quad);
6164 11374 : SymbolTable_RemoveWriteQuad (Sym, SymbolTable_RightValue, Quad);
6165 : }
6166 : else
6167 : {
6168 208462 : SymbolTable_RemoveWriteQuad (Sym, SymbolTable_GetMode (Sym), Quad);
6169 : }
6170 : }
6171 589917 : }
6172 :
6173 :
6174 : /*
6175 : CheckConst -
6176 : */
6177 :
6178 1305037 : static void CheckConst (unsigned int sym)
6179 : {
6180 1305037 : if (SymbolTable_IsConst (sym))
6181 : {
6182 372448 : M2GCCDeclare_PutToBeSolvedByQuads (sym);
6183 : }
6184 1305037 : }
6185 :
6186 :
6187 : /*
6188 : AlterReference - alters all references from OldQuad, to NewQuad in a
6189 : quadruple list Head.
6190 : */
6191 :
6192 1928561 : static void AlterReference (unsigned int Head, unsigned int OldQuad, unsigned int NewQuad)
6193 : {
6194 1928561 : M2Quads_QuadFrame f;
6195 1928561 : M2Quads_QuadFrame g;
6196 1928561 : unsigned int i;
6197 :
6198 1928561 : f = GetQF (OldQuad);
6199 12895292 : while ((f->NoOfTimesReferenced > 0) && (Head != 0))
6200 : {
6201 9038170 : g = GetQF (Head);
6202 9038170 : switch (g->Operator)
6203 : {
6204 399714 : case M2Quads_IfInOp:
6205 399714 : case M2Quads_IfNotInOp:
6206 399714 : case M2Quads_IfEquOp:
6207 399714 : case M2Quads_IfNotEquOp:
6208 399714 : case M2Quads_IfLessOp:
6209 399714 : case M2Quads_IfLessEquOp:
6210 399714 : case M2Quads_IfGreOp:
6211 399714 : case M2Quads_IfGreEquOp:
6212 399714 : case M2Quads_TryOp:
6213 399714 : case M2Quads_RetryOp:
6214 399714 : case M2Quads_GotoOp:
6215 399714 : if (g->Operand3 == OldQuad)
6216 : {
6217 8982 : ManipulateReference (Head, NewQuad);
6218 : }
6219 : break;
6220 :
6221 :
6222 : default:
6223 : break;
6224 : }
6225 9038170 : i = g->Next;
6226 9038170 : Head = i;
6227 : }
6228 1928561 : }
6229 :
6230 :
6231 : /*
6232 : GrowQuads - grows the list of quadruples to the quadruple, to.
6233 : */
6234 :
6235 645034 : static void GrowQuads (unsigned int to)
6236 : {
6237 645034 : unsigned int i;
6238 645034 : M2Quads_QuadFrame f;
6239 :
6240 645034 : if ((to != 0) && (to > GrowInitialization))
6241 : {
6242 10044 : i = GrowInitialization+1;
6243 20088 : while (i <= to)
6244 : {
6245 10044 : if (Indexing_InBounds (QuadArray, i))
6246 : {
6247 0 : M2Debug_Assert ((Indexing_GetIndice (QuadArray, i)) != NULL);
6248 : }
6249 : else
6250 : {
6251 10044 : Storage_ALLOCATE ((void **) &f, sizeof (M2Quads__T3));
6252 10044 : if (f == NULL)
6253 : {
6254 0 : M2Error_InternalError ((const char *) "out of memory error when trying to allocate a quadruple", 55);
6255 : }
6256 10044 : Indexing_PutIndice (QuadArray, i, reinterpret_cast <void *> (f));
6257 10044 : f->NoOfTimesReferenced = 0;
6258 : }
6259 10044 : i += 1;
6260 : }
6261 10044 : GrowInitialization = to;
6262 : }
6263 645034 : }
6264 :
6265 :
6266 : /*
6267 : ManipulateReference - manipulates the quadruple, q, so that it now points to quad, to.
6268 : */
6269 :
6270 645034 : static void ManipulateReference (unsigned int q, unsigned int to)
6271 : {
6272 645034 : M2Quads_QuadFrame f;
6273 :
6274 1290068 : M2Debug_Assert ((GrowInitialization >= q) || (to == 0));
6275 645034 : GrowQuads (to);
6276 645034 : RemoveReference (q);
6277 645034 : f = GetQF (q);
6278 645034 : f->Operand3 = to;
6279 645034 : if (to != 0)
6280 : {
6281 409823 : f = GetQF (to);
6282 409823 : f->NoOfTimesReferenced += 1;
6283 : }
6284 645034 : }
6285 :
6286 :
6287 : /*
6288 : RemoveReference - remove the reference by quadruple q to wherever
6289 : it was pointing.
6290 : */
6291 :
6292 880339 : static void RemoveReference (unsigned int q)
6293 : {
6294 880339 : M2Quads_QuadFrame f;
6295 880339 : M2Quads_QuadFrame g;
6296 :
6297 880339 : f = GetQF (q);
6298 880339 : if ((f->Operand3 != 0) && (f->Operand3 < NextQuad))
6299 : {
6300 279979 : CheckBreak (f->Operand3);
6301 279979 : g = GetQF (f->Operand3);
6302 279979 : M2Debug_Assert (g->NoOfTimesReferenced != 0);
6303 279979 : g->NoOfTimesReferenced -= 1;
6304 : }
6305 880339 : }
6306 :
6307 :
6308 : /*
6309 : NewQuad - sets QuadNo to a new quadruple.
6310 : */
6311 :
6312 6330256 : static void NewQuad (unsigned int *QuadNo)
6313 : {
6314 6330256 : M2Quads_QuadFrame f;
6315 :
6316 6330256 : (*QuadNo) = FreeList;
6317 6330256 : if ((Indexing_InBounds (QuadArray, (*QuadNo))) && ((Indexing_GetIndice (QuadArray, (*QuadNo))) != NULL))
6318 : {
6319 10044 : f = static_cast<M2Quads_QuadFrame> (Indexing_GetIndice (QuadArray, (*QuadNo)));
6320 : }
6321 : else
6322 : {
6323 6320212 : Storage_ALLOCATE ((void **) &f, sizeof (M2Quads__T3));
6324 6320212 : if (f == NULL)
6325 : {
6326 0 : M2Error_InternalError ((const char *) "out of memory error trying to allocate a quadruple", 50);
6327 : }
6328 : else
6329 : {
6330 6320212 : NoOfQuads += 1;
6331 6320212 : Indexing_PutIndice (QuadArray, (*QuadNo), reinterpret_cast <void *> (f));
6332 6320212 : f->NoOfTimesReferenced = 0;
6333 6320212 : M2Diagnostic_MemSet (QuadMemDiag, 1, NoOfQuads);
6334 6320212 : M2Diagnostic_MemIncr (QuadMemDiag, 2, sizeof ((*f)));
6335 : }
6336 : }
6337 6330256 : f->Operator = M2Quads_DummyOp;
6338 6330256 : f->Operand3 = 0;
6339 6330256 : f->Next = 0;
6340 6330256 : FreeList += 1;
6341 6330256 : if (GrowInitialization < FreeList)
6342 : {
6343 6320212 : GrowInitialization = FreeList;
6344 : }
6345 6330256 : }
6346 :
6347 :
6348 : /*
6349 : CheckVariableAt - checks to see whether, sym, was declared at a particular address.
6350 : */
6351 :
6352 4141015 : static void CheckVariableAt (unsigned int sym)
6353 : {
6354 4141015 : if ((SymbolTable_IsVar (sym)) && (SymbolTable_IsVariableAtAddress (sym)))
6355 : {
6356 : /* avoid gcc warning by using compound statement even if not strictly necessary. */
6357 54 : if ((SymbolTable_GetMode (sym)) == SymbolTable_LeftValue)
6358 : {
6359 54 : GenQuad (M2Quads_InitAddressOp, sym, SymbolTable_NulSym, SymbolTable_GetVariableAtAddress (sym));
6360 : }
6361 : else
6362 : {
6363 0 : M2Error_InternalError ((const char *) "expecting lvalue for this variable which is declared at an explicit address", 75);
6364 : }
6365 : }
6366 4141015 : }
6367 :
6368 :
6369 : /*
6370 : CheckVariablesAt - checks to see whether we need to initialize any pointers
6371 : which point to variable declared at addresses.
6372 : */
6373 :
6374 166631 : static void CheckVariablesAt (unsigned int scope)
6375 : {
6376 0 : SymbolTable_ForeachLocalSymDo (scope, (SymbolKey_PerformOperation) {(SymbolKey_PerformOperation_t) CheckVariableAt});
6377 0 : }
6378 :
6379 :
6380 : /*
6381 : GetTurnInterrupts - returns the TurnInterrupts procedure function.
6382 : */
6383 :
6384 840 : static unsigned int GetTurnInterrupts (unsigned int tok)
6385 : {
6386 840 : if (M2Options_Iso)
6387 : {
6388 0 : return GetQualidentImport (tok, NameKey_MakeKey ((const char *) "TurnInterrupts", 14), NameKey_MakeKey ((const char *) "COROUTINES", 10));
6389 : }
6390 : else
6391 : {
6392 840 : return GetQualidentImport (tok, NameKey_MakeKey ((const char *) "TurnInterrupts", 14), NameKey_MakeKey ((const char *) "SYSTEM", 6));
6393 : }
6394 : /* static analysis guarentees a RETURN statement will be used before here. */
6395 : __builtin_unreachable ();
6396 : }
6397 :
6398 :
6399 : /*
6400 : GetProtection - returns the PROTECTION data type.
6401 : */
6402 :
6403 420 : static unsigned int GetProtection (unsigned int tok)
6404 : {
6405 420 : if (M2Options_Iso)
6406 : {
6407 0 : return GetQualidentImport (tok, NameKey_MakeKey ((const char *) "PROTECTION", 10), NameKey_MakeKey ((const char *) "COROUTINES", 10));
6408 : }
6409 : else
6410 : {
6411 420 : return GetQualidentImport (tok, NameKey_MakeKey ((const char *) "PROTECTION", 10), NameKey_MakeKey ((const char *) "SYSTEM", 6));
6412 : }
6413 : /* static analysis guarentees a RETURN statement will be used before here. */
6414 : __builtin_unreachable ();
6415 : }
6416 :
6417 :
6418 : /*
6419 : CheckNeedPriorityBegin - checks to see whether we need to save the old
6420 : module priority and change to another module
6421 : priority.
6422 : The current module initialization or procedure
6423 : being built is defined by, scope. The module whose
6424 : priority will be used is defined by, module.
6425 : */
6426 :
6427 182664 : static void CheckNeedPriorityBegin (unsigned int tok, unsigned int scope, unsigned int module)
6428 : {
6429 182664 : unsigned int ProcSym;
6430 182664 : unsigned int old;
6431 :
6432 182664 : if ((SymbolTable_GetPriority (module)) != SymbolTable_NulSym)
6433 : {
6434 : /* module has been given a priority */
6435 420 : ProcSym = GetTurnInterrupts (tok);
6436 420 : if (ProcSym != SymbolTable_NulSym)
6437 : {
6438 420 : old = SymbolTable_MakeTemporary (tok, SymbolTable_RightValue);
6439 420 : SymbolTable_PutVar (old, GetProtection (tok));
6440 840 : GenQuadO (tok, M2Quads_SavePriorityOp, old, scope, ProcSym, false);
6441 420 : M2StackWord_PushWord (PriorityStack, old);
6442 : }
6443 : }
6444 182664 : }
6445 :
6446 :
6447 : /*
6448 : CheckNeedPriorityEnd - checks to see whether we need to restore the old
6449 : module priority.
6450 : The current module initialization or procedure
6451 : being built is defined by, scope.
6452 : */
6453 :
6454 182486 : static void CheckNeedPriorityEnd (unsigned int tok, unsigned int scope, unsigned int module)
6455 : {
6456 182486 : unsigned int ProcSym;
6457 182486 : unsigned int old;
6458 :
6459 182486 : if ((SymbolTable_GetPriority (module)) != SymbolTable_NulSym)
6460 : {
6461 : /* module has been given a priority */
6462 420 : ProcSym = GetTurnInterrupts (tok);
6463 420 : if (ProcSym != SymbolTable_NulSym)
6464 : {
6465 420 : old = static_cast<unsigned int> (M2StackWord_PopWord (PriorityStack));
6466 420 : GenQuad (M2Quads_RestorePriorityOp, old, scope, ProcSym);
6467 : }
6468 : }
6469 182486 : }
6470 :
6471 :
6472 : /*
6473 : BuildRTExceptEnter - informs RTExceptions that we are about to enter the except state.
6474 : */
6475 :
6476 2969 : static void BuildRTExceptEnter (unsigned int tok)
6477 : {
6478 2969 : unsigned int old;
6479 2969 : unsigned int ProcSym;
6480 :
6481 2969 : if (M2Options_Exceptions)
6482 : {
6483 : /* now inform the Modula-2 runtime we are in the exception state */
6484 2969 : ProcSym = GetQualidentImport (tok, NameKey_MakeKey ((const char *) "SetExceptionState", 17), NameKey_MakeKey ((const char *) "RTExceptions", 12));
6485 2969 : if (ProcSym == SymbolTable_NulSym)
6486 : {
6487 0 : M2MetaError_MetaErrorT0 (tok, (const char *) "{%W}no procedure SetExceptionState found in RTExceptions which is needed to implement exception handling", 104);
6488 : }
6489 : else
6490 : {
6491 2969 : old = SymbolTable_MakeTemporary (tok, SymbolTable_RightValue);
6492 2969 : SymbolTable_PutVar (old, M2Base_Boolean);
6493 5938 : GenQuadO (tok, M2Quads_SaveExceptionOp, old, SymbolTable_NulSym, ProcSym, false);
6494 2969 : M2StackWord_PushWord (ExceptStack, old);
6495 : }
6496 : }
6497 : else
6498 : {
6499 0 : M2MetaError_MetaErrorT0 (tok, (const char *) "{%E}cannot use {%kEXCEPT} blocks with the -fno-exceptions flag", 62);
6500 : }
6501 2969 : }
6502 :
6503 :
6504 : /*
6505 : BuildRTExceptLeave - informs RTExceptions that we are about to leave the except state.
6506 : If, destroy, is TRUE then pop the ExceptStack.
6507 : */
6508 :
6509 3131 : static void BuildRTExceptLeave (unsigned int tok, bool destroy)
6510 : {
6511 3131 : unsigned int old;
6512 3131 : unsigned int ProcSym;
6513 :
6514 3131 : if (M2Options_Exceptions)
6515 : {
6516 : /* avoid dangling else. */
6517 : /* now inform the Modula-2 runtime we are in the exception state */
6518 3131 : ProcSym = GetQualidentImport (tok, NameKey_MakeKey ((const char *) "SetExceptionState", 17), NameKey_MakeKey ((const char *) "RTExceptions", 12));
6519 3131 : if (ProcSym != SymbolTable_NulSym)
6520 : {
6521 3131 : if (destroy)
6522 : {
6523 2969 : old = static_cast<unsigned int> (M2StackWord_PopWord (ExceptStack));
6524 : }
6525 : else
6526 : {
6527 162 : old = static_cast<unsigned int> (M2StackWord_PeepWord (ExceptStack, 1));
6528 : }
6529 3131 : GenQuadO (tok, M2Quads_RestoreExceptionOp, old, SymbolTable_NulSym, ProcSym, false);
6530 : }
6531 : }
6532 : /* no need for an error message here as it will be generated in the Enter procedure above */
6533 3131 : }
6534 :
6535 :
6536 : /*
6537 : SafeRequestSym - only used during scaffold to get argc, argv, envp.
6538 : It attempts to get symbol name from the current scope(s) and if
6539 : it fails then it falls back onto default constants.
6540 : */
6541 :
6542 16482 : static unsigned int SafeRequestSym (unsigned int tok, NameKey_Name name)
6543 : {
6544 16482 : unsigned int sym;
6545 :
6546 16482 : sym = SymbolTable_GetSym (name);
6547 16482 : if (sym == SymbolTable_NulSym)
6548 : {
6549 : /* avoid gcc warning by using compound statement even if not strictly necessary. */
6550 0 : if (name == (NameKey_MakeKey ((const char *) "argc", 4)))
6551 : {
6552 0 : return SymbolTable_MakeConstLit (tok, NameKey_MakeKey ((const char *) "0", 1), M2Base_ZType);
6553 : }
6554 0 : else if ((name == (NameKey_MakeKey ((const char *) "argv", 4))) || (name == (NameKey_MakeKey ((const char *) "envp", 4))))
6555 : {
6556 : /* avoid dangling else. */
6557 0 : return M2Base_Nil;
6558 : }
6559 : else
6560 : {
6561 : /* avoid dangling else. */
6562 0 : M2Error_InternalError ((const char *) "not expecting this parameter name", 33);
6563 : return M2Base_Nil;
6564 : }
6565 : }
6566 : return sym;
6567 : /* static analysis guarentees a RETURN statement will be used before here. */
6568 : __builtin_unreachable ();
6569 : }
6570 :
6571 :
6572 : /*
6573 : callRequestDependant - create a call:
6574 : RequestDependant (GetSymName (modulesym), GetLibName (modulesym),
6575 : GetSymName (depModuleSym), GetLibName (depModuleSym));
6576 : */
6577 :
6578 39080 : static void callRequestDependant (unsigned int tokno, unsigned int moduleSym, unsigned int depModuleSym, unsigned int requestDep)
6579 : {
6580 39080 : M2Debug_Assert (requestDep != SymbolTable_NulSym);
6581 39080 : M2Quads_PushTtok (requestDep, tokno);
6582 39080 : M2Quads_PushTFtok (M2System_Adr, M2System_Address, tokno);
6583 39080 : M2Quads_PushTtok (SymbolTable_MakeConstString (tokno, SymbolTable_GetSymName (moduleSym)), tokno);
6584 39080 : M2Quads_PushT (static_cast<unsigned int> (1));
6585 39080 : BuildAdrFunction ();
6586 39080 : M2Quads_PushTFtok (M2System_Adr, M2System_Address, tokno);
6587 39080 : M2Quads_PushTtok (SymbolTable_MakeConstString (tokno, SymbolTable_GetLibName (moduleSym)), tokno);
6588 39080 : M2Quads_PushT (static_cast<unsigned int> (1));
6589 39080 : BuildAdrFunction ();
6590 39080 : if (depModuleSym == SymbolTable_NulSym)
6591 : {
6592 15783 : M2Quads_PushTF (M2Base_Nil, M2System_Address);
6593 15783 : M2Quads_PushTF (M2Base_Nil, M2System_Address);
6594 : }
6595 : else
6596 : {
6597 23297 : M2Quads_PushTFtok (M2System_Adr, M2System_Address, tokno);
6598 23297 : M2Quads_PushTtok (SymbolTable_MakeConstString (tokno, SymbolTable_GetSymName (depModuleSym)), tokno);
6599 23297 : M2Quads_PushT (static_cast<unsigned int> (1));
6600 23297 : BuildAdrFunction ();
6601 23297 : M2Quads_PushTFtok (M2System_Adr, M2System_Address, tokno);
6602 23297 : M2Quads_PushTtok (SymbolTable_MakeConstString (tokno, SymbolTable_GetLibName (depModuleSym)), tokno);
6603 23297 : M2Quads_PushT (static_cast<unsigned int> (1));
6604 23297 : BuildAdrFunction ();
6605 : }
6606 39080 : M2Quads_PushT (static_cast<unsigned int> (4));
6607 39080 : M2Quads_BuildProcedureCall (tokno);
6608 39080 : }
6609 :
6610 :
6611 : /*
6612 : ForeachImportInDepDo -
6613 : */
6614 :
6615 31566 : static void ForeachImportInDepDo (Lists_List importStatements, unsigned int moduleSym, unsigned int requestDep)
6616 : {
6617 31566 : unsigned int i;
6618 31566 : unsigned int j;
6619 31566 : unsigned int m;
6620 31566 : unsigned int n;
6621 31566 : unsigned int imported;
6622 31566 : unsigned int stmt;
6623 31566 : Lists_List l;
6624 :
6625 31566 : if (importStatements != NULL)
6626 : {
6627 19868 : i = 1;
6628 19868 : n = Lists_NoOfItemsInList (importStatements);
6629 62283 : while (i <= n)
6630 : {
6631 22547 : stmt = static_cast<unsigned int> (Lists_GetItemFromList (importStatements, i));
6632 22547 : M2Debug_Assert (SymbolTable_IsImportStatement (stmt));
6633 22547 : l = SymbolTable_GetImportStatementList (stmt);
6634 22547 : j = 1;
6635 22547 : m = Lists_NoOfItemsInList (l);
6636 68391 : while (j <= m)
6637 : {
6638 23297 : imported = static_cast<unsigned int> (Lists_GetItemFromList (l, j));
6639 23297 : M2Debug_Assert (SymbolTable_IsImport (imported));
6640 23297 : callRequestDependant (SymbolTable_GetImportDeclared (imported), moduleSym, SymbolTable_GetImportModule (imported), requestDep);
6641 23297 : j += 1;
6642 : }
6643 22547 : i += 1;
6644 : }
6645 : }
6646 31566 : }
6647 :
6648 :
6649 : /*
6650 : ForeachImportedModuleDo -
6651 : */
6652 :
6653 15783 : static void ForeachImportedModuleDo (unsigned int moduleSym, unsigned int requestDep)
6654 : {
6655 15783 : Lists_List importStatements;
6656 :
6657 15783 : importStatements = SymbolTable_GetModuleModImportStatementList (moduleSym);
6658 15783 : ForeachImportInDepDo (importStatements, moduleSym, requestDep);
6659 15783 : importStatements = SymbolTable_GetModuleDefImportStatementList (moduleSym);
6660 15783 : ForeachImportInDepDo (importStatements, moduleSym, requestDep);
6661 15783 : }
6662 :
6663 :
6664 : /*
6665 : BuildM2DepFunction - creates the dependency graph procedure using IR:
6666 : static void
6667 : dependencies (void)
6668 : {
6669 : M2RTS_RequestDependant (module_name, libname, "b", "b libname");
6670 : M2RTS_RequestDependant (module_name, libname, NULL, NULL);
6671 : }
6672 : */
6673 :
6674 15827 : static void BuildM2DepFunction (unsigned int tokno, unsigned int moduleSym)
6675 : {
6676 15827 : unsigned int requestDep;
6677 15827 : unsigned int ctor;
6678 15827 : unsigned int init;
6679 15827 : unsigned int fini;
6680 15827 : unsigned int dep;
6681 :
6682 15827 : if (M2Options_ScaffoldDynamic)
6683 : {
6684 : /* Scaffold required and dynamic dependency graph should be produced. */
6685 15783 : SymbolTable_GetModuleCtors (moduleSym, &ctor, &init, &fini, &dep);
6686 15783 : M2Quads_PushT (dep);
6687 15783 : M2Quads_BuildProcedureStart ();
6688 15783 : M2Quads_BuildProcedureBegin ();
6689 15783 : SymbolTable_StartScope (dep);
6690 15783 : requestDep = GetQualidentImport (tokno, NameKey_MakeKey ((const char *) "RequestDependant", 16), NameKey_MakeKey ((const char *) "M2RTS", 5));
6691 15783 : if (requestDep != SymbolTable_NulSym)
6692 : {
6693 15783 : ForeachImportedModuleDo (moduleSym, requestDep);
6694 15783 : callRequestDependant (tokno, moduleSym, SymbolTable_NulSym, requestDep);
6695 : }
6696 15783 : SymbolTable_EndScope ();
6697 15783 : M2Quads_BuildProcedureEnd ();
6698 15783 : M2Quads_PopN (1);
6699 : }
6700 15827 : }
6701 :
6702 :
6703 : /*
6704 : BuildM2LinkFunction - creates the _M2_link procedure which will
6705 : cause the linker to pull in all the module ctors.
6706 : */
6707 :
6708 2783 : static void BuildM2LinkFunction (unsigned int tokno)
6709 : {
6710 2783 : if (M2Options_ScaffoldDynamic)
6711 : {
6712 2747 : if (M2Scaffold_linkFunction != SymbolTable_NulSym)
6713 : {
6714 : /* void
6715 : _M2_link (void)
6716 : {
6717 : for each module in uselist do
6718 : PROC foo_%d = _M2_module_ctor
6719 : done
6720 : }. */
6721 2732 : M2Quads_PushT (M2Scaffold_linkFunction);
6722 2732 : M2Quads_BuildProcedureStart ();
6723 2732 : M2Quads_BuildProcedureBegin ();
6724 2732 : SymbolTable_StartScope (M2Scaffold_linkFunction);
6725 2732 : M2Scaffold_PopulateCtorArray (tokno);
6726 2732 : SymbolTable_EndScope ();
6727 2732 : M2Quads_BuildProcedureEnd ();
6728 2732 : M2Quads_PopN (1);
6729 : }
6730 : }
6731 2783 : }
6732 :
6733 :
6734 : /*
6735 : BuildTry - build the try statement for main.
6736 : */
6737 :
6738 2747 : static void BuildTry (unsigned int tokno)
6739 : {
6740 2747 : if (M2Options_Exceptions)
6741 : {
6742 2747 : M2StackWord_PushWord (TryStack, NextQuad);
6743 2747 : M2StackWord_PushWord (CatchStack, static_cast<unsigned int> (0));
6744 2747 : GenQuadO (tokno, M2Quads_TryOp, SymbolTable_NulSym, SymbolTable_NulSym, 0, false);
6745 : }
6746 2747 : }
6747 :
6748 :
6749 : /*
6750 : BuildExcept - build the except block for main.
6751 : */
6752 :
6753 2747 : static void BuildExcept (unsigned int tokno)
6754 : {
6755 2747 : unsigned int catchProcedure;
6756 :
6757 2747 : if (M2Options_Exceptions)
6758 : {
6759 2747 : M2Quads_BuildExceptInitial (tokno);
6760 2747 : catchProcedure = GetQualidentImport (tokno, NameKey_MakeKey ((const char *) "DefaultErrorCatch", 17), NameKey_MakeKey ((const char *) "RTExceptions", 12));
6761 2747 : if (catchProcedure != SymbolTable_NulSym)
6762 : {
6763 2747 : M2Quads_PushTtok (catchProcedure, tokno);
6764 2747 : M2Quads_PushT (static_cast<unsigned int> (0));
6765 2747 : M2Quads_BuildProcedureCall (tokno);
6766 : }
6767 2747 : BuildRTExceptLeave (tokno, true);
6768 2747 : GenQuadO (tokno, M2Quads_CatchEndOp, SymbolTable_NulSym, SymbolTable_NulSym, SymbolTable_NulSym, false);
6769 : }
6770 2747 : }
6771 :
6772 :
6773 : /*
6774 : BuildM2MainFunction - creates the main function with appropriate calls to the scaffold.
6775 : */
6776 :
6777 2783 : static void BuildM2MainFunction (unsigned int tokno)
6778 : {
6779 2783 : if ((M2Options_ScaffoldDynamic || M2Options_ScaffoldStatic) && ! M2Options_SharedFlag)
6780 : {
6781 : /*
6782 : int
6783 : main (int argc, char *argv[], char *envp[])
6784 : {
6785 : try {
6786 : _M2_init (argc, argv, envp);
6787 : _M2_fini (argc, argv, envp);
6788 : return 0;
6789 : }
6790 : catch (...) {
6791 : RTExceptions_DefaultErrorCatch ();
6792 : return 0;
6793 : }
6794 : }
6795 : */
6796 2747 : M2Quads_PushT (M2Scaffold_mainFunction);
6797 2747 : M2Quads_BuildProcedureStart ();
6798 2747 : M2Quads_BuildProcedureBegin ();
6799 2747 : SymbolTable_StartScope (M2Scaffold_mainFunction);
6800 2747 : BuildTry (tokno);
6801 : /* _M2_init (argc, argv, envp); */
6802 2747 : M2Quads_PushTtok (M2Scaffold_initFunction, tokno);
6803 2747 : M2Quads_PushTtok (SymbolTable_RequestSym (tokno, NameKey_MakeKey ((const char *) "argc", 4)), tokno);
6804 2747 : M2Quads_PushTtok (SymbolTable_RequestSym (tokno, NameKey_MakeKey ((const char *) "argv", 4)), tokno);
6805 2747 : M2Quads_PushTtok (SymbolTable_RequestSym (tokno, NameKey_MakeKey ((const char *) "envp", 4)), tokno);
6806 2747 : M2Quads_PushT (static_cast<unsigned int> (3));
6807 2747 : M2Quads_BuildProcedureCall (tokno);
6808 : /* _M2_fini (argc, argv, envp); */
6809 2747 : M2Quads_PushTtok (M2Scaffold_finiFunction, tokno);
6810 2747 : M2Quads_PushTtok (SymbolTable_RequestSym (tokno, NameKey_MakeKey ((const char *) "argc", 4)), tokno);
6811 2747 : M2Quads_PushTtok (SymbolTable_RequestSym (tokno, NameKey_MakeKey ((const char *) "argv", 4)), tokno);
6812 2747 : M2Quads_PushTtok (SymbolTable_RequestSym (tokno, NameKey_MakeKey ((const char *) "envp", 4)), tokno);
6813 2747 : M2Quads_PushT (static_cast<unsigned int> (3));
6814 2747 : M2Quads_BuildProcedureCall (tokno);
6815 2747 : PushZero (tokno, M2Base_Integer);
6816 2747 : M2Quads_BuildReturn (tokno);
6817 2747 : BuildExcept (tokno);
6818 2747 : PushZero (tokno, M2Base_Integer);
6819 2747 : M2Quads_BuildReturn (tokno);
6820 2747 : SymbolTable_EndScope ();
6821 2747 : M2Quads_BuildProcedureEnd ();
6822 2747 : M2Quads_PopN (1);
6823 : }
6824 2783 : }
6825 :
6826 :
6827 : /*
6828 : DeferMakeConstStringCnul - return a C const string which will be nul terminated.
6829 : */
6830 :
6831 9733 : static unsigned int DeferMakeConstStringCnul (unsigned int tok, unsigned int sym)
6832 : {
6833 9733 : unsigned int const_;
6834 :
6835 9733 : const_ = SymbolTable_MakeConstStringCnul (tok, NameKey_NulName, false);
6836 19466 : GenQuadO (tok, M2Quads_StringConvertCnulOp, const_, 0, sym, false);
6837 9733 : return const_;
6838 : /* static analysis guarentees a RETURN statement will be used before here. */
6839 : __builtin_unreachable ();
6840 : }
6841 :
6842 :
6843 : /*
6844 : DeferMakeConstStringM2nul - return a const string which will be nul terminated.
6845 : */
6846 :
6847 34964 : static unsigned int DeferMakeConstStringM2nul (unsigned int tok, unsigned int sym)
6848 : {
6849 34964 : unsigned int const_;
6850 :
6851 34964 : const_ = SymbolTable_MakeConstStringM2nul (tok, NameKey_NulName, false);
6852 69928 : GenQuadO (tok, M2Quads_StringConvertM2nulOp, const_, 0, sym, false);
6853 34964 : return const_;
6854 : /* static analysis guarentees a RETURN statement will be used before here. */
6855 : __builtin_unreachable ();
6856 : }
6857 :
6858 :
6859 : /*
6860 : BuildStringAdrParam - push the address of a nul terminated string onto the quad stack.
6861 : */
6862 :
6863 8241 : static void BuildStringAdrParam (unsigned int tok, NameKey_Name name)
6864 : {
6865 8241 : unsigned int str;
6866 8241 : unsigned int m2strnul;
6867 :
6868 8241 : M2Quads_PushTFtok (M2System_Adr, M2System_Address, tok);
6869 8241 : str = SymbolTable_MakeConstString (tok, name);
6870 8241 : SymbolTable_PutConstStringKnown (tok, str, name, false, true);
6871 8241 : m2strnul = DeferMakeConstStringM2nul (tok, str);
6872 8241 : M2Quads_PushTtok (m2strnul, tok);
6873 8241 : M2Quads_PushT (static_cast<unsigned int> (1));
6874 8241 : BuildAdrFunction ();
6875 8241 : }
6876 :
6877 :
6878 : /*
6879 : BuildM2InitFunction -
6880 : */
6881 :
6882 2783 : static void BuildM2InitFunction (unsigned int tok, unsigned int moduleSym)
6883 : {
6884 2783 : unsigned int constructModules;
6885 :
6886 2783 : if (M2Options_ScaffoldDynamic || M2Options_ScaffoldStatic)
6887 : {
6888 : /* int
6889 : _M2_init (int argc, char *argv[], char *envp[])
6890 : {
6891 : M2RTS_ConstructModules (module_name, libname,
6892 : overrideliborder, argc, argv, envp);
6893 : } */
6894 2747 : M2Quads_PushT (M2Scaffold_initFunction);
6895 2747 : M2Quads_BuildProcedureStart ();
6896 2747 : M2Quads_BuildProcedureBegin ();
6897 2747 : SymbolTable_StartScope (M2Scaffold_initFunction);
6898 2747 : if (M2Options_ScaffoldDynamic)
6899 : {
6900 : /* avoid dangling else. */
6901 2747 : if (M2Scaffold_linkFunction != SymbolTable_NulSym)
6902 : {
6903 : /* _M2_link (); */
6904 2732 : M2Quads_PushTtok (M2Scaffold_linkFunction, tok);
6905 2732 : M2Quads_PushT (static_cast<unsigned int> (0));
6906 2732 : M2Quads_BuildProcedureCall (tok);
6907 : }
6908 : /* Lookup ConstructModules and call it. */
6909 2747 : constructModules = GetQualidentImport (tok, NameKey_MakeKey ((const char *) "ConstructModules", 16), NameKey_MakeKey ((const char *) "M2RTS", 5));
6910 2747 : if (constructModules != SymbolTable_NulSym)
6911 : {
6912 : /* ConstructModules (module_name, argc, argv, envp); */
6913 2747 : M2Quads_PushTtok (constructModules, tok);
6914 2747 : BuildStringAdrParam (tok, SymbolTable_GetSymName (moduleSym));
6915 2747 : BuildStringAdrParam (tok, SymbolTable_GetLibName (moduleSym));
6916 2747 : BuildStringAdrParam (tok, NameKey_makekey (M2Options_GetRuntimeModuleOverride ()));
6917 2747 : M2Quads_PushTtok (SafeRequestSym (tok, NameKey_MakeKey ((const char *) "argc", 4)), tok);
6918 2747 : M2Quads_PushTtok (SafeRequestSym (tok, NameKey_MakeKey ((const char *) "argv", 4)), tok);
6919 2747 : M2Quads_PushTtok (SafeRequestSym (tok, NameKey_MakeKey ((const char *) "envp", 4)), tok);
6920 2747 : M2Quads_PushT (static_cast<unsigned int> (6));
6921 2747 : M2Quads_BuildProcedureCall (tok);
6922 : }
6923 : }
6924 0 : else if (M2Options_ScaffoldStatic)
6925 : {
6926 : /* avoid dangling else. */
6927 0 : M2Scaffold_ForeachModuleCallInit (tok, SafeRequestSym (tok, NameKey_MakeKey ((const char *) "argc", 4)), SafeRequestSym (tok, NameKey_MakeKey ((const char *) "argv", 4)), SafeRequestSym (tok, NameKey_MakeKey ((const char *) "envp", 4)));
6928 : }
6929 2747 : SymbolTable_EndScope ();
6930 2747 : M2Quads_BuildProcedureEnd ();
6931 2747 : M2Quads_PopN (1);
6932 : }
6933 2783 : }
6934 :
6935 :
6936 : /*
6937 : BuildM2FiniFunction -
6938 : */
6939 :
6940 2783 : static void BuildM2FiniFunction (unsigned int tok, unsigned int moduleSym)
6941 : {
6942 2783 : unsigned int deconstructModules;
6943 :
6944 2783 : if (M2Options_ScaffoldDynamic || M2Options_ScaffoldStatic)
6945 : {
6946 : /* Scaffold required and main should be produced. */
6947 2747 : M2Quads_PushT (M2Scaffold_finiFunction);
6948 2747 : M2Quads_BuildProcedureStart ();
6949 2747 : M2Quads_BuildProcedureBegin ();
6950 2747 : SymbolTable_StartScope (M2Scaffold_finiFunction);
6951 2747 : if (M2Options_ScaffoldDynamic)
6952 : {
6953 : /* avoid dangling else. */
6954 : /* static void
6955 : _M2_finish (int argc, char *argv[], char *envp[])
6956 : {
6957 : M2RTS_DeconstructModules (module_name, argc, argv, envp);
6958 : } */
6959 2747 : deconstructModules = GetQualidentImport (tok, NameKey_MakeKey ((const char *) "DeconstructModules", 18), NameKey_MakeKey ((const char *) "M2RTS", 5));
6960 2747 : if (deconstructModules != SymbolTable_NulSym)
6961 : {
6962 : /* DeconstructModules (module_name, argc, argv, envp); */
6963 2747 : M2Quads_PushTtok (deconstructModules, tok);
6964 2747 : M2Quads_PushTFtok (M2System_Adr, M2System_Address, tok);
6965 2747 : M2Quads_PushTtok (SymbolTable_MakeConstString (tok, SymbolTable_GetSymName (moduleSym)), tok);
6966 2747 : M2Quads_PushT (static_cast<unsigned int> (1));
6967 2747 : BuildAdrFunction ();
6968 2747 : M2Quads_PushTFtok (M2System_Adr, M2System_Address, tok);
6969 2747 : M2Quads_PushTtok (SymbolTable_MakeConstString (tok, SymbolTable_GetLibName (moduleSym)), tok);
6970 2747 : M2Quads_PushT (static_cast<unsigned int> (1));
6971 2747 : BuildAdrFunction ();
6972 2747 : M2Quads_PushTtok (SafeRequestSym (tok, NameKey_MakeKey ((const char *) "argc", 4)), tok);
6973 2747 : M2Quads_PushTtok (SafeRequestSym (tok, NameKey_MakeKey ((const char *) "argv", 4)), tok);
6974 2747 : M2Quads_PushTtok (SafeRequestSym (tok, NameKey_MakeKey ((const char *) "envp", 4)), tok);
6975 2747 : M2Quads_PushT (static_cast<unsigned int> (5));
6976 2747 : M2Quads_BuildProcedureCall (tok);
6977 : }
6978 : }
6979 0 : else if (M2Options_ScaffoldStatic)
6980 : {
6981 : /* avoid dangling else. */
6982 0 : M2Scaffold_ForeachModuleCallFinish (tok, SafeRequestSym (tok, NameKey_MakeKey ((const char *) "argc", 4)), SafeRequestSym (tok, NameKey_MakeKey ((const char *) "argv", 4)), SafeRequestSym (tok, NameKey_MakeKey ((const char *) "envp", 4)));
6983 : }
6984 2747 : SymbolTable_EndScope ();
6985 2747 : M2Quads_BuildProcedureEnd ();
6986 2747 : M2Quads_PopN (1);
6987 : }
6988 2783 : }
6989 :
6990 :
6991 : /*
6992 : BuildM2CtorFunction - create a constructor function associated with moduleSym.
6993 :
6994 : void
6995 : ctorFunction ()
6996 : {
6997 : M2RTS_RegisterModule (GetSymName (moduleSym), GetLibName (moduleSym),
6998 : init, fini, dependencies);
6999 : }
7000 : */
7001 :
7002 15827 : static void BuildM2CtorFunction (unsigned int tok, unsigned int moduleSym)
7003 : {
7004 15827 : unsigned int RegisterModule;
7005 15827 : unsigned int ctor;
7006 15827 : unsigned int init;
7007 15827 : unsigned int fini;
7008 15827 : unsigned int dep;
7009 :
7010 15827 : if (M2Options_ScaffoldDynamic)
7011 : {
7012 15783 : SymbolTable_GetModuleCtors (moduleSym, &ctor, &init, &fini, &dep);
7013 15783 : if (ctor != SymbolTable_NulSym)
7014 : {
7015 15783 : M2Debug_Assert (SymbolTable_IsProcedure (ctor));
7016 15783 : M2Quads_PushT (ctor);
7017 15783 : M2Quads_BuildProcedureStart ();
7018 15783 : M2Quads_BuildProcedureBegin ();
7019 15783 : SymbolTable_StartScope (ctor);
7020 15783 : RegisterModule = GetQualidentImport (tok, NameKey_MakeKey ((const char *) "RegisterModule", 14), NameKey_MakeKey ((const char *) "M2RTS", 5));
7021 15783 : if (RegisterModule != SymbolTable_NulSym)
7022 : {
7023 : /* RegisterModule (module_name, init, fini, dependencies); */
7024 15783 : M2Quads_PushTtok (RegisterModule, tok);
7025 15783 : M2Quads_PushTFtok (M2System_Adr, M2System_Address, tok);
7026 15783 : M2Quads_PushTtok (SymbolTable_MakeConstString (tok, SymbolTable_GetSymName (moduleSym)), tok);
7027 15783 : M2Quads_PushT (static_cast<unsigned int> (1));
7028 15783 : BuildAdrFunction ();
7029 15783 : M2Quads_PushTFtok (M2System_Adr, M2System_Address, tok);
7030 15783 : M2Quads_PushTtok (SymbolTable_MakeConstString (tok, SymbolTable_GetLibName (moduleSym)), tok);
7031 15783 : M2Quads_PushT (static_cast<unsigned int> (1));
7032 15783 : BuildAdrFunction ();
7033 15783 : M2Quads_PushTtok (init, tok);
7034 15783 : M2Quads_PushTtok (fini, tok);
7035 15783 : M2Quads_PushTtok (dep, tok);
7036 15783 : M2Quads_PushT (static_cast<unsigned int> (5));
7037 15783 : M2Quads_BuildProcedureCall (tok);
7038 : }
7039 15783 : SymbolTable_EndScope ();
7040 15783 : M2Quads_BuildProcedureEnd ();
7041 15783 : M2Quads_PopN (1);
7042 : }
7043 : }
7044 15827 : }
7045 :
7046 :
7047 : /*
7048 : AddForInfo - adds the description of the FOR loop into the record list.
7049 : This is used if -pedantic is turned on to check index variable
7050 : usage.
7051 : */
7052 :
7053 2604 : static void AddForInfo (unsigned int Start, unsigned int End, unsigned int IncQuad, unsigned int Sym, unsigned int idtok)
7054 : {
7055 2604 : M2Quads_ForLoopInfo forDesc;
7056 :
7057 2604 : if (M2Options_Pedantic)
7058 : {
7059 0 : Storage_ALLOCATE ((void **) &forDesc, sizeof (M2Quads__T5));
7060 0 : forDesc->IncrementQuad = IncQuad;
7061 0 : forDesc->StartOfForLoop = Start;
7062 0 : forDesc->EndOfForLoop = End;
7063 0 : forDesc->ForLoopIndex = Sym;
7064 0 : forDesc->IndexTok = idtok;
7065 0 : Indexing_IncludeIndiceIntoIndex (ForInfo, reinterpret_cast <void *> (forDesc));
7066 : }
7067 2604 : }
7068 :
7069 :
7070 : /*
7071 : CheckForIndex - checks the quadruples: Start..End to see whether a
7072 : for loop index is manipulated by the programmer.
7073 : It generates a warning if this is the case.
7074 : It also checks to see whether the IndexSym is read
7075 : immediately outside the loop in which case a warning
7076 : is issued.
7077 : */
7078 :
7079 0 : static void CheckForIndex (M2Quads_ForLoopInfo forDesc)
7080 : {
7081 0 : unsigned int ReadStart;
7082 0 : unsigned int ReadEnd;
7083 0 : unsigned int WriteStart;
7084 0 : unsigned int WriteEnd;
7085 :
7086 0 : SymbolTable_GetWriteLimitQuads (forDesc->ForLoopIndex, SymbolTable_RightValue, forDesc->StartOfForLoop, forDesc->EndOfForLoop, &WriteStart, &WriteEnd);
7087 0 : if ((WriteStart < forDesc->IncrementQuad) && (WriteStart > forDesc->StartOfForLoop))
7088 : {
7089 0 : M2MetaError_MetaErrorT1 (forDesc->IndexTok, (const char *) "{%kFOR} loop index variable {%1Wad} is being manipulated inside the loop", 72, forDesc->ForLoopIndex);
7090 0 : M2MetaError_MetaErrorT1 (M2Quads_QuadToTokenNo (WriteStart), (const char *) "{%kFOR} loop index variable {%1Wad} is being manipulated, this is considered bad practice and may cause unknown program behaviour", 129, forDesc->ForLoopIndex);
7091 : }
7092 0 : SymbolTable_GetWriteLimitQuads (forDesc->ForLoopIndex, SymbolTable_RightValue, forDesc->EndOfForLoop, 0, &WriteStart, &WriteEnd);
7093 0 : SymbolTable_GetReadLimitQuads (forDesc->ForLoopIndex, SymbolTable_RightValue, forDesc->EndOfForLoop, 0, &ReadStart, &ReadEnd);
7094 0 : if ((ReadStart != 0) && ((ReadStart < WriteStart) || (WriteStart == 0)))
7095 : {
7096 0 : M2MetaError_MetaErrorT1 (forDesc->IndexTok, (const char *) "{%kFOR} loop index variable {%1Wad} is being read outside the FOR loop (without being reset)", 92, forDesc->ForLoopIndex);
7097 0 : M2MetaError_MetaErrorT1 (M2Quads_QuadToTokenNo (ReadStart), (const char *) "{%kFOR} loop index variable {%1Wad} is being read outside the FOR loop (without being reset), this is considered extremely bad practice and may cause unknown program behaviour", 175, forDesc->ForLoopIndex);
7098 : }
7099 0 : }
7100 :
7101 :
7102 : /*
7103 : BuildRange - generates a RangeCheckOp quad with, r, as its operand.
7104 : */
7105 :
7106 2086369 : static void BuildRange (unsigned int r)
7107 : {
7108 2086369 : GenQuad (M2Quads_RangeCheckOp, (unsigned int ) (M2LexBuf_GetLineNo ()), SymbolTable_NulSym, r);
7109 2086369 : }
7110 :
7111 :
7112 : /*
7113 : BuildError - generates a ErrorOp quad, indicating that if this
7114 : quadruple is reachable, then a runtime error would
7115 : occur.
7116 : */
7117 :
7118 19660 : static void BuildError (unsigned int r)
7119 : {
7120 19660 : GenQuad (M2Quads_ErrorOp, (unsigned int ) (M2LexBuf_GetLineNo ()), SymbolTable_NulSym, r);
7121 19660 : }
7122 :
7123 :
7124 : /*
7125 : CheckPointerThroughNil - builds a range quadruple, providing, sym, is
7126 : a candidate for checking against NIL.
7127 : This range quadruple is only expanded into
7128 : code during the code generation phase
7129 : thus allowing limited compile time checking.
7130 : */
7131 :
7132 80695 : static void CheckPointerThroughNil (unsigned int tokpos, unsigned int sym)
7133 : {
7134 80695 : if ((SymbolTable_IsVar (sym)) && (SymbolTable_GetVarPointerCheck (sym)))
7135 : {
7136 : /* PutVarPointerCheck(sym, FALSE) ; so we do not detect this again */
7137 23714 : BuildRange (M2Range_InitPointerRangeCheck (tokpos, sym, (SymbolTable_GetMode (sym)) == SymbolTable_LeftValue));
7138 : }
7139 80695 : }
7140 :
7141 :
7142 : /*
7143 : CollectLow - returns the low of the subrange value.
7144 : */
7145 :
7146 306 : static unsigned int CollectLow (unsigned int sym)
7147 : {
7148 306 : unsigned int low;
7149 306 : unsigned int high;
7150 :
7151 306 : if (SymbolTable_IsSubrange (sym))
7152 : {
7153 306 : SymbolTable_GetSubrange (sym, &high, &low);
7154 306 : return low;
7155 : }
7156 : else
7157 : {
7158 0 : M2Error_InternalError ((const char *) "expecting Subrange symbol", 25);
7159 : }
7160 : ReturnException ("/home/worker/buildworker/tiber-lcov/build/gcc/m2/gm2-compiler/M2Quads.def", 20, 1);
7161 : __builtin_unreachable ();
7162 : }
7163 :
7164 :
7165 : /*
7166 : CollectHigh - returns the high of the subrange value, sym.
7167 : */
7168 :
7169 562 : static unsigned int CollectHigh (unsigned int sym)
7170 : {
7171 562 : unsigned int low;
7172 562 : unsigned int high;
7173 :
7174 562 : if (SymbolTable_IsSubrange (sym))
7175 : {
7176 562 : SymbolTable_GetSubrange (sym, &high, &low);
7177 562 : return high;
7178 : }
7179 : else
7180 : {
7181 0 : M2Error_InternalError ((const char *) "expecting Subrange symbol", 25);
7182 : }
7183 : ReturnException ("/home/worker/buildworker/tiber-lcov/build/gcc/m2/gm2-compiler/M2Quads.def", 20, 1);
7184 : __builtin_unreachable ();
7185 : }
7186 :
7187 :
7188 : /*
7189 : CheckCompatibleWithBecomes - checks to see that symbol, sym, is
7190 : compatible with the := operator.
7191 : */
7192 :
7193 502381 : static void CheckCompatibleWithBecomes (unsigned int des, unsigned int expr, unsigned int destok, unsigned int exprtok)
7194 : {
7195 502381 : if (SymbolTable_IsType (des))
7196 : {
7197 0 : M2MetaError_MetaErrorT1 (destok, (const char *) "an assignment cannot assign a value to a type {%1a}", 51, des);
7198 : }
7199 502381 : else if (SymbolTable_IsProcedure (des))
7200 : {
7201 : /* avoid dangling else. */
7202 6 : M2MetaError_MetaErrorT1 (destok, (const char *) "an assignment cannot assign a value to a procedure {%1a}", 56, des);
7203 : }
7204 502375 : else if (SymbolTable_IsFieldEnumeration (des))
7205 : {
7206 : /* avoid dangling else. */
7207 0 : M2MetaError_MetaErrorT1 (destok, (const char *) "an assignment cannot assign a value to an enumeration field {%1a}", 65, des);
7208 : }
7209 502381 : if ((M2Base_IsPseudoBaseProcedure (expr)) || (M2Base_IsPseudoBaseFunction (expr)))
7210 : {
7211 6 : M2MetaError_MetaErrorT1 (exprtok, (const char *) "an assignment cannot assign a {%1dv} {%1a}", 42, expr);
7212 : }
7213 502381 : }
7214 :
7215 :
7216 : /*
7217 : BuildAssignmentWithoutBounds - calls BuildAssignment but makes sure we do not
7218 : check bounds.
7219 : */
7220 :
7221 83855 : static void BuildAssignmentWithoutBounds (unsigned int tok, bool checkTypes, bool checkOverflow)
7222 : {
7223 83855 : bool old;
7224 :
7225 83855 : old = MustNotCheckBounds;
7226 83855 : MustNotCheckBounds = true;
7227 0 : doBuildAssignment (tok, checkTypes, checkOverflow);
7228 83855 : MustNotCheckBounds = old;
7229 19748 : }
7230 :
7231 :
7232 : /*
7233 : MarkArrayWritten - marks, Array, as being written.
7234 : */
7235 :
7236 101950 : static void MarkArrayWritten (unsigned int Array)
7237 : {
7238 101950 : if ((Array != SymbolTable_NulSym) && (SymbolTable_IsVarAParam (Array)))
7239 : {
7240 12630 : SymbolTable_PutVarWritten (Array, true);
7241 : }
7242 101950 : }
7243 :
7244 :
7245 : /*
7246 : MarkAsReadWrite - marks the variable or parameter as being
7247 : read/write.
7248 : */
7249 :
7250 31247 : static void MarkAsReadWrite (unsigned int sym)
7251 : {
7252 31247 : if ((sym != SymbolTable_NulSym) && (SymbolTable_IsVar (sym)))
7253 : {
7254 21514 : SymbolTable_PutReadQuad (sym, SymbolTable_RightValue, NextQuad);
7255 21514 : SymbolTable_PutWriteQuad (sym, SymbolTable_RightValue, NextQuad);
7256 : }
7257 31247 : }
7258 :
7259 :
7260 : /*
7261 : MarkAsRead - marks the variable or parameter as being read.
7262 : */
7263 :
7264 1275988 : static void MarkAsRead (unsigned int sym)
7265 : {
7266 1275988 : if ((sym != SymbolTable_NulSym) && (SymbolTable_IsVar (sym)))
7267 : {
7268 361363 : SymbolTable_PutReadQuad (sym, SymbolTable_RightValue, NextQuad);
7269 : }
7270 1275988 : }
7271 :
7272 :
7273 : /*
7274 : MarkAsWrite - marks the variable or parameter as being written.
7275 : */
7276 :
7277 502381 : static void MarkAsWrite (unsigned int sym)
7278 : {
7279 502381 : if ((sym != SymbolTable_NulSym) && (SymbolTable_IsVar (sym)))
7280 : {
7281 86131 : SymbolTable_PutWriteQuad (sym, SymbolTable_RightValue, NextQuad);
7282 : }
7283 502381 : }
7284 :
7285 :
7286 : /*
7287 : doVal - return an expression which is VAL(type, expr). If
7288 : expr is a constant then return expr.
7289 : */
7290 :
7291 44030 : static unsigned int doVal (unsigned int type, unsigned int expr)
7292 : {
7293 44030 : if ((! (SymbolTable_IsConst (expr))) && ((SymbolTable_SkipType (type)) != (SymbolTable_GetDType (expr))))
7294 : {
7295 33286 : M2Quads_PushTF (M2Base_Convert, static_cast<unsigned int> (SymbolTable_NulSym));
7296 33286 : M2Quads_PushT (SymbolTable_SkipType (type));
7297 33286 : M2Quads_PushT (expr);
7298 33286 : M2Quads_PushT (static_cast<unsigned int> (2)); /* Two parameters */
7299 33286 : BuildConvertFunction (M2Base_Convert, false); /* Two parameters */
7300 33286 : M2Quads_PopT (&expr);
7301 : }
7302 44030 : return expr;
7303 : /* static analysis guarentees a RETURN statement will be used before here. */
7304 : __builtin_unreachable ();
7305 : }
7306 :
7307 :
7308 : /*
7309 : MoveWithMode -
7310 : */
7311 :
7312 502375 : static void MoveWithMode (unsigned int tokno, unsigned int Des, unsigned int Exp, unsigned int Array, unsigned int destok, unsigned int exptok, bool checkOverflow)
7313 : {
7314 502375 : unsigned int t;
7315 :
7316 502375 : if ((SymbolTable_IsConstString (Exp)) && (SymbolTable_IsConst (Des)))
7317 : {
7318 1426 : GenQuadOtok (tokno, M2Quads_BecomesOp, Des, SymbolTable_NulSym, Exp, true, destok, M2LexBuf_UnknownTokenNo, exptok);
7319 : }
7320 : else
7321 : {
7322 500949 : if ((SymbolTable_GetMode (Des)) == SymbolTable_RightValue)
7323 : {
7324 158152 : if ((SymbolTable_GetMode (Exp)) == SymbolTable_LeftValue)
7325 : {
7326 2688 : CheckPointerThroughNil (tokno, Exp); /* Des = *Exp */
7327 2688 : doIndrX (tokno, Des, Exp); /* Des = *Exp */
7328 : }
7329 : else
7330 : {
7331 155464 : GenQuadOtok (tokno, M2Quads_BecomesOp, Des, SymbolTable_NulSym, Exp, true, destok, M2LexBuf_UnknownTokenNo, exptok);
7332 : }
7333 : }
7334 342797 : else if ((SymbolTable_GetMode (Des)) == SymbolTable_LeftValue)
7335 : {
7336 : /* avoid dangling else. */
7337 43512 : MarkArrayWritten (Array);
7338 43512 : if ((SymbolTable_GetMode (Exp)) == SymbolTable_LeftValue)
7339 : {
7340 1106 : t = SymbolTable_MakeTemporary (tokno, SymbolTable_RightValue);
7341 1106 : SymbolTable_PutVar (t, SymbolTable_GetSType (Exp));
7342 1106 : CheckPointerThroughNil (tokno, Exp);
7343 1106 : doIndrX (tokno, t, Exp);
7344 1106 : CheckPointerThroughNil (tokno, Des); /* *Des = Exp */
7345 1106 : GenQuadO (tokno, M2Quads_XIndrOp, Des, SymbolTable_GetSType (Des), doVal (SymbolTable_GetSType (Des), t), checkOverflow); /* *Des = Exp */
7346 : }
7347 : else
7348 : {
7349 42406 : CheckPointerThroughNil (tokno, Des); /* *Des = Exp */
7350 42406 : GenQuadO (tokno, M2Quads_XIndrOp, Des, SymbolTable_GetSType (Des), doVal (SymbolTable_GetSType (Des), Exp), checkOverflow); /* *Des = Exp */
7351 : }
7352 : }
7353 : else
7354 : {
7355 : /* avoid dangling else. */
7356 : /* This might be inside a const expression. */
7357 299285 : GenQuadOTypetok (tokno, M2Quads_BecomesOp, Des, SymbolTable_NulSym, Exp, true, true, destok, M2LexBuf_UnknownTokenNo, exptok);
7358 : }
7359 : }
7360 502375 : }
7361 :
7362 :
7363 : /*
7364 : CheckBecomesMeta - checks to make sure that we are not
7365 : assigning a variable to a constant.
7366 : Also check we are not assigning to an
7367 : unbounded array.
7368 : */
7369 :
7370 430324 : static void CheckBecomesMeta (unsigned int Des, unsigned int Exp, unsigned int combinedtok, unsigned int destok, unsigned int exprtok)
7371 : {
7372 430324 : if ((SymbolTable_IsConst (Des)) && (SymbolTable_IsVar (Exp)))
7373 : {
7374 84 : M2MetaError_MetaErrorsT2 (combinedtok, (const char *) "in assignment, cannot assign a variable {%2a} to a constant {%1a}", 65, (const char *) "designator {%1Da} is declared as a {%kCONST}", 44, Des, Exp);
7375 : }
7376 430324 : if ((((SymbolTable_GetDType (Des)) != SymbolTable_NulSym) && (SymbolTable_IsVar (Des))) && (SymbolTable_IsUnbounded (SymbolTable_GetDType (Des))))
7377 : {
7378 0 : M2MetaError_MetaErrorT1 (destok, (const char *) "in assignment, cannot assign to an unbounded array {%1ad}", 57, Des);
7379 : }
7380 430324 : if ((((SymbolTable_GetDType (Exp)) != SymbolTable_NulSym) && (SymbolTable_IsVar (Exp))) && (SymbolTable_IsUnbounded (SymbolTable_GetDType (Exp))))
7381 : {
7382 0 : M2MetaError_MetaErrorT1 (exprtok, (const char *) "in assignment, cannot assign from an unbounded array {%1ad}", 59, Exp);
7383 : }
7384 430324 : }
7385 :
7386 :
7387 : /*
7388 : BuildAssignmentBoolean - build the quadruples for a boolean variable or constant
7389 : which will be assigned to the result of a boolean expression.
7390 : For example:
7391 :
7392 : foo := a = b ;
7393 : foo := a IN b ;
7394 :
7395 : The boolean result is contained in the control flow
7396 : the true value will emerge from the quad path t.
7397 : The false value will emerge from the quad path f.
7398 : This procedure terminates both paths by backpatching
7399 : and assigns TRUE or FALSE to the variable/constant.
7400 : A variable maybe an L value so it will require dereferencing.
7401 : */
7402 :
7403 10044 : static void BuildAssignmentBoolean (unsigned int becomesTokNo, bool checkOverflow, unsigned int t, unsigned int f, unsigned int Des, unsigned int destok)
7404 : {
7405 10044 : SymbolTable_PutVarConditional (Des, true); /* Des will contain the result of a boolean relop. */
7406 : /* Conditional Boolean Assignment. */
7407 10044 : BackPatch (t, NextQuad);
7408 10044 : if ((SymbolTable_GetMode (Des)) == SymbolTable_LeftValue)
7409 : {
7410 64 : CheckPointerThroughNil (destok, Des);
7411 128 : GenQuadO (destok, M2Quads_XIndrOp, Des, M2Base_Boolean, M2Base_True, checkOverflow);
7412 64 : GenQuadO (destok, M2Quads_GotoOp, SymbolTable_NulSym, SymbolTable_NulSym, NextQuad+2, false);
7413 : }
7414 : else
7415 : {
7416 : /* This might be inside a const expression. */
7417 19960 : GenQuadO (becomesTokNo, M2Quads_BecomesOp, Des, SymbolTable_NulSym, M2Base_True, checkOverflow);
7418 9980 : GenQuadO (destok, M2Quads_GotoOp, SymbolTable_NulSym, SymbolTable_NulSym, NextQuad+2, false);
7419 : }
7420 10044 : BackPatch (f, NextQuad);
7421 10044 : if ((SymbolTable_GetMode (Des)) == SymbolTable_LeftValue)
7422 : {
7423 64 : CheckPointerThroughNil (destok, Des);
7424 64 : GenQuadO (destok, M2Quads_XIndrOp, Des, M2Base_Boolean, M2Base_False, checkOverflow);
7425 : }
7426 : else
7427 : {
7428 9980 : GenQuadO (becomesTokNo, M2Quads_BecomesOp, Des, SymbolTable_NulSym, M2Base_False, checkOverflow);
7429 : }
7430 10044 : }
7431 :
7432 :
7433 : /*
7434 : doBuildAssignment - subsiduary procedure of BuildAssignment.
7435 : It builds the assignment and optionally
7436 : checks the types are compatible.
7437 : */
7438 :
7439 512425 : static void doBuildAssignment (unsigned int becomesTokNo, bool checkTypes, bool checkOverflow)
7440 : {
7441 512425 : unsigned int r;
7442 512425 : unsigned int w;
7443 512425 : unsigned int t;
7444 512425 : unsigned int f;
7445 512425 : unsigned int Array;
7446 512425 : unsigned int Des;
7447 512425 : unsigned int Exp;
7448 512425 : unsigned int combinedtok;
7449 512425 : unsigned int destok;
7450 512425 : unsigned int exptok;
7451 :
7452 512425 : M2Quads_DisplayStack ();
7453 512425 : if (IsBoolean (1))
7454 : {
7455 20088 : PopBool (&t, &f);
7456 10044 : M2Quads_PopTtok (&Des, &destok);
7457 10044 : if ((SymbolTable_IsVar (Des)) || (SymbolTable_IsConstVar (Des)))
7458 : {
7459 10044 : BuildAssignmentBoolean (becomesTokNo, checkOverflow, t, f, Des, destok);
7460 : }
7461 : else
7462 : {
7463 0 : M2MetaError_MetaErrorT1 (destok, (const char *) "expecting the designator {%1Ead} to be a constant or a variable and not a {%1dv}", 80, Des);
7464 : }
7465 : }
7466 : else
7467 : {
7468 502381 : PopTrwtok (&Exp, &r, &exptok);
7469 502381 : MarkAsRead (r);
7470 502381 : if (Exp == SymbolTable_NulSym)
7471 : {
7472 0 : M2MetaError_MetaError0 ((const char *) "{%E}unknown expression found during assignment", 46);
7473 0 : M2Error_FlushErrors ();
7474 : }
7475 502381 : Array = static_cast<unsigned int> (M2Quads_OperandA (1));
7476 502381 : PopTrwtok (&Des, &w, &destok);
7477 502381 : MarkAsWrite (w);
7478 502381 : CheckCompatibleWithBecomes (Des, Exp, destok, exptok);
7479 502381 : if (DebugTokPos)
7480 : {
7481 : M2MetaError_MetaErrorT1 (becomesTokNo, (const char *) "becomestok {%1Oad}", 18, Des);
7482 : M2MetaError_MetaErrorT1 (destok, (const char *) "destok {%1Oad}", 14, Des);
7483 : M2MetaError_MetaErrorT1 (exptok, (const char *) "exptok {%1Oad}", 14, Exp);
7484 : }
7485 502381 : combinedtok = M2LexBuf_MakeVirtualTok (becomesTokNo, destok, exptok);
7486 502381 : if (DebugTokPos)
7487 : {
7488 : M2MetaError_MetaErrorT1 (combinedtok, (const char *) "combined {%1Oad}", 16, Des);
7489 : }
7490 502381 : if (M2Options_StrictTypeAssignment)
7491 : {
7492 502381 : BuildRange (M2Range_InitTypesAssignmentCheck (combinedtok, Des, Exp));
7493 : }
7494 502381 : if (((SymbolTable_GetSType (Des)) != SymbolTable_NulSym) && (! (SymbolTable_IsSet (SymbolTable_GetDType (Des)))))
7495 : {
7496 : /* Tell code generator to test runtime values of assignment so ensure we
7497 : catch overflow and underflow. */
7498 492723 : BuildRange (M2Range_InitAssignmentRangeCheck (combinedtok, Des, Exp, destok, exptok));
7499 : }
7500 502375 : if (checkTypes)
7501 : {
7502 430324 : CheckBecomesMeta (Des, Exp, combinedtok, destok, exptok);
7503 : }
7504 : /* Simple assignment. */
7505 502375 : MoveWithMode (combinedtok, Des, Exp, Array, destok, exptok, checkOverflow);
7506 502375 : if (checkTypes)
7507 : {
7508 430324 : CheckAssignCompatible (Des, Exp, combinedtok, destok, exptok);
7509 : }
7510 : }
7511 512419 : M2Quads_DisplayStack ();
7512 512419 : }
7513 :
7514 :
7515 : /*
7516 : CheckAssignCompatible - checks to see that an assignment is compatible.
7517 : It performs limited checking - thorough checking
7518 : is done in pass 3. But we do what we can here
7519 : given knowledge so far.
7520 : */
7521 :
7522 430324 : static void CheckAssignCompatible (unsigned int Des, unsigned int Exp, unsigned int combinedtok, unsigned int destok, unsigned int exprtok)
7523 : {
7524 430324 : unsigned int DesT;
7525 430324 : unsigned int ExpT;
7526 430324 : unsigned int DesL;
7527 :
7528 430324 : DesT = SymbolTable_GetSType (Des);
7529 430324 : ExpT = SymbolTable_GetSType (Exp);
7530 430324 : DesL = SymbolTable_GetLType (Des);
7531 430324 : if (((SymbolTable_IsProcedure (Exp)) && ((DesT != SymbolTable_NulSym) && (! (SymbolTable_IsProcType (DesT))))) && ((DesL != SymbolTable_NulSym) && (! (SymbolTable_IsProcType (DesL)))))
7532 : {
7533 0 : M2MetaError_MetaErrorT1 (destok, (const char *) "incorrectly assigning a procedure to a designator {%1Ead} (designator is not a procedure type, {%1ast})", 103, Des);
7534 : }
7535 : /* We ignore checking of these types in pass 3 - but we do check them thoroughly post pass 3 */
7536 430324 : else if ((SymbolTable_IsProcedure (Exp)) && (SymbolTable_IsProcedureNested (Exp)))
7537 : {
7538 : /* avoid dangling else. */
7539 6 : M2MetaError_MetaErrorT1 (exprtok, (const char *) "cannot call nested procedure {%1Ead} indirectly as the outer scope will not be known", 84, Exp);
7540 : }
7541 430318 : else if (SymbolTable_IsConstString (Exp))
7542 : {
7543 : /* avoid dangling else. */
7544 : }
7545 427226 : else if ((DesT != SymbolTable_NulSym) && (SymbolTable_IsUnbounded (DesT)))
7546 : {
7547 : /* avoid dangling else. */
7548 : }
7549 427226 : else if ((ExpT != SymbolTable_NulSym) && (SymbolTable_IsUnbounded (ExpT)))
7550 : {
7551 : /* avoid dangling else. */
7552 : }
7553 427226 : else if ((DesL != SymbolTable_NulSym) && (SymbolTable_IsArray (DesL)))
7554 : {
7555 : /* avoid dangling else. */
7556 : }
7557 426378 : else if (SymbolTable_IsConstructor (Exp))
7558 : {
7559 : /* avoid dangling else. */
7560 6426 : if (ExpT == SymbolTable_NulSym)
7561 : {} /* empty. */
7562 6386 : else if (((DesT == SymbolTable_NulSym) && (SymbolTable_IsConst (Des))) && ((SymbolTable_IsConstructor (Des)) || (SymbolTable_IsConstSet (Des))))
7563 : {
7564 : /* avoid dangling else. */
7565 0 : SymbolTable_PutConst (Des, ExpT);
7566 : }
7567 6386 : else if (! (M2Base_IsAssignmentCompatible (DesT, ExpT)))
7568 : {
7569 : /* avoid dangling else. */
7570 0 : M2MetaError_MetaErrorT1 (combinedtok, (const char *) "constructor expression is not compatible during assignment to {%1Ead}", 69, Des);
7571 : }
7572 : }
7573 419952 : else if (((DesT != SymbolTable_NulSym) && (SymbolTable_IsSet (DesT))) && (SymbolTable_IsConst (Exp)))
7574 : {
7575 : /* avoid dangling else. */
7576 : }
7577 419822 : else if ((((((SymbolTable_IsConst (Exp)) && (ExpT != M2System_Address)) && (! (SymbolTable_IsConst (Des)))) && (DesL != SymbolTable_NulSym)) && ((DesL == M2Base_Cardinal) || (! (SymbolTable_IsSubrange (DesL))))) && (! (SymbolTable_IsEnumeration (DesL))))
7578 : {
7579 : /* avoid dangling else. */
7580 25001 : if ((M2Base_IsBaseType (DesL)) || (M2System_IsSystemType (DesL)))
7581 : {
7582 25001 : M2Base_CheckAssignmentCompatible (combinedtok, ExpT, DesT);
7583 : }
7584 : else
7585 : {
7586 0 : M2MetaError_MetaErrorT2 (combinedtok, (const char *) "assignment of a constant {%1Ead} can only be made to a variable whose type is equivalent to a Modula-2 base type {%2tsa}", 120, Exp, Des);
7587 : }
7588 : }
7589 : else
7590 : {
7591 : /* avoid dangling else. */
7592 394821 : if (((DesT != SymbolTable_NulSym) && (SymbolTable_IsProcType (DesT))) && (SymbolTable_IsProcedure (Exp)))
7593 : {
7594 32562 : DesT = SymbolTable_GetSType (DesT); /* we can at least check RETURN values of procedure variables */
7595 : /* remember that thorough assignment checking is done post pass 3 */
7596 32562 : M2Base_CheckAssignmentCompatible (combinedtok, ExpT, DesT);
7597 : }
7598 : }
7599 430324 : }
7600 :
7601 :
7602 : /*
7603 : CheckBooleanId - Checks to see if the top operand is a boolean.
7604 : If the operand is not a boolean then it is tested
7605 : with true and a boolean is generated.
7606 : The Stack:
7607 :
7608 :
7609 : Entry Exit
7610 : Ptr -> <- Ptr
7611 : +------------+ +------------+
7612 : | Sym | | t | f |
7613 : |------------| |------------|
7614 :
7615 : Quadruples
7616 :
7617 : q If= Sym True _
7618 : q+1 GotoOp _ _ _
7619 : */
7620 :
7621 86312 : static void CheckBooleanId (void)
7622 : {
7623 86312 : unsigned int tok;
7624 :
7625 86312 : if (! (IsBoolean (1)))
7626 : {
7627 18063 : tok = static_cast<unsigned int> (M2Quads_OperandTok (1));
7628 18063 : if (SymbolTable_IsVar (M2Quads_OperandT (1)))
7629 : {
7630 14439 : if ((SymbolTable_GetSType (M2Quads_OperandT (1))) != M2Base_Boolean)
7631 : {
7632 0 : M2MetaError_MetaError1 ((const char *) "{%1Ua:is not a boolean expression}{!%1Ua:boolean expression expected}", 69, M2Quads_OperandT (1));
7633 : }
7634 : }
7635 18063 : M2Quads_PushT (M2Reserved_EqualTok);
7636 18063 : M2Quads_PushT (M2Base_True);
7637 18063 : M2Quads_BuildRelOp (tok);
7638 : }
7639 86312 : }
7640 :
7641 :
7642 : /*
7643 : PushOne - pushes the value one to the stack.
7644 : The Stack is changed:
7645 :
7646 :
7647 : Entry Exit
7648 : ===== ====
7649 :
7650 : <- Ptr
7651 : +------------+
7652 : Ptr -> | 1 | type |
7653 : |------------|
7654 : */
7655 :
7656 16432 : static void PushOne (unsigned int tok, unsigned int type, const char *message_, unsigned int _message_high)
7657 : {
7658 16432 : unsigned int const_;
7659 16432 : char message[_message_high+1];
7660 :
7661 : /* make a local copy of each unbounded array. */
7662 16432 : memcpy (message, message_, _message_high+1);
7663 :
7664 16432 : if (type == SymbolTable_NulSym)
7665 : {
7666 220 : const_ = SymbolTable_MakeConstLit (tok, NameKey_MakeKey ((const char *) "1", 1), SymbolTable_NulSym);
7667 220 : SymbolTable_PutConstLitInternal (const_, true);
7668 220 : M2Quads_PushTFtok (const_, static_cast<unsigned int> (SymbolTable_NulSym), tok);
7669 : }
7670 16212 : else if (SymbolTable_IsEnumeration (type))
7671 : {
7672 : /* avoid dangling else. */
7673 238 : if ((SymbolTable_NoOfElements (type)) == 0)
7674 : {
7675 0 : M2MetaError_MetaErrorString1 (DynamicStrings_ConCat (DynamicStrings_InitString ((const char *) "enumeration type only has one element {%1Dad} and therefore ", 60), DynamicStrings_Mark (DynamicStrings_InitString ((const char *) message, _message_high))), type);
7676 0 : PushZero (tok, type);
7677 : }
7678 : else
7679 : {
7680 238 : M2Quads_PushTFtok (M2Base_Convert, static_cast<unsigned int> (SymbolTable_NulSym), tok);
7681 238 : M2Quads_PushT (type);
7682 238 : M2Quads_PushTFtok (SymbolTable_MakeConstLit (tok, NameKey_MakeKey ((const char *) "1", 1), M2Base_ZType), M2Base_ZType, tok);
7683 238 : M2Quads_PushT (static_cast<unsigned int> (2)); /* Two parameters */
7684 238 : BuildConvertFunction (M2Base_Convert, true); /* Two parameters */
7685 : }
7686 : }
7687 : else
7688 : {
7689 : /* avoid dangling else. */
7690 15974 : const_ = SymbolTable_MakeConstLit (tok, NameKey_MakeKey ((const char *) "1", 1), type);
7691 15974 : SymbolTable_PutConstLitInternal (const_, true);
7692 15974 : M2Quads_PushTFtok (const_, type, tok);
7693 : }
7694 16432 : }
7695 :
7696 :
7697 : /*
7698 : PushZero - pushes the value zero to the stack.
7699 : The Stack is changed:
7700 :
7701 :
7702 : Entry Exit
7703 : ===== ====
7704 :
7705 : <- Ptr
7706 : +------------+
7707 : Ptr -> | 0 | type |
7708 : |------------|
7709 : */
7710 :
7711 8098 : static void PushZero (unsigned int tok, unsigned int type)
7712 : {
7713 8098 : if (type == SymbolTable_NulSym)
7714 : {
7715 424 : M2Quads_PushTFtok (SymbolTable_MakeConstLit (tok, NameKey_MakeKey ((const char *) "0", 1), SymbolTable_NulSym), static_cast<unsigned int> (SymbolTable_NulSym), tok);
7716 : }
7717 7674 : else if (SymbolTable_IsEnumeration (type))
7718 : {
7719 : /* avoid dangling else. */
7720 196 : M2Quads_PushTFtok (M2Base_Convert, static_cast<unsigned int> (SymbolTable_NulSym), tok);
7721 196 : M2Quads_PushTtok (type, tok);
7722 196 : M2Quads_PushTtok (SymbolTable_MakeConstLit (tok, NameKey_MakeKey ((const char *) "0", 1), M2Base_ZType), tok);
7723 196 : M2Quads_PushT (static_cast<unsigned int> (2)); /* Two parameters */
7724 196 : BuildConvertFunction (M2Base_Convert, true); /* Two parameters */
7725 : }
7726 : else
7727 : {
7728 : /* avoid dangling else. */
7729 7478 : M2Quads_PushTFtok (SymbolTable_MakeConstLit (tok, NameKey_MakeKey ((const char *) "0", 1), type), type, tok);
7730 : }
7731 8098 : }
7732 :
7733 :
7734 : /*
7735 : ForLoopLastIterator - calculate the last iterator value but avoid setting
7736 : LastIterator twice if it is a constant (in the quads).
7737 : In the ForLoopLastIteratorVariable case only one
7738 : path will be chosen but at the time of quadruple
7739 : generation we do not know the value of BySym.
7740 : */
7741 :
7742 2604 : static void ForLoopLastIterator (unsigned int LastIterator, unsigned int e1, unsigned int e2, unsigned int BySym, unsigned int e1tok, unsigned int e2tok, unsigned int bytok)
7743 : {
7744 2604 : if (! (SymbolTable_IsConst (BySym)))
7745 : {
7746 18 : M2MetaError_MetaErrorT1 (bytok, (const char *) "{%E}the {%kFOR} loop {%kBY} expression must be constant, the expression {%1a} is variable", 89, BySym);
7747 18 : M2MetaError_MetaErrorDecl (BySym, true);
7748 : }
7749 : else
7750 : {
7751 2586 : e1 = DereferenceLValue (e1tok, e1);
7752 2586 : e2 = DereferenceLValue (e2tok, e2);
7753 2586 : GenQuadOTypetok (bytok, M2Quads_LastForIteratorOp, LastIterator, SymbolTable_Make2Tuple (e1, e2), BySym, false, false, bytok, M2LexBuf_MakeVirtual2Tok (e1tok, e2tok), bytok);
7754 : }
7755 2604 : }
7756 :
7757 :
7758 : /*
7759 : BuildSizeCheckEnd - checks to see whether the function "called" was in fact SIZE.
7760 : If so then we restore quadruple generation.
7761 : */
7762 :
7763 16340 : static void BuildSizeCheckEnd (unsigned int ProcSym)
7764 : {
7765 16340 : if (((ProcSym == M2Size_Size) || (ProcSym == M2System_TSize)) || (ProcSym == M2System_TBitSize))
7766 : {
7767 13362 : QuadrupleGeneration = true;
7768 13362 : BuildingSize = false;
7769 : }
7770 2978 : else if (ProcSym == M2Base_High)
7771 : {
7772 : /* avoid dangling else. */
7773 2978 : QuadrupleGeneration = true;
7774 2978 : BuildingHigh = false;
7775 : }
7776 16340 : }
7777 :
7778 :
7779 : /*
7780 : BuildRealProcedureCall - builds a real procedure call.
7781 : The Stack:
7782 :
7783 :
7784 : Entry Exit
7785 :
7786 : Ptr ->
7787 : +----------------+
7788 : | NoOfParam |
7789 : |----------------|
7790 : | Param 1 |
7791 : |----------------|
7792 : | Param 2 |
7793 : |----------------|
7794 : . .
7795 : . .
7796 : . .
7797 : |----------------|
7798 : | Param # |
7799 : |----------------|
7800 : | ProcSym | Type | Empty
7801 : |----------------|
7802 : */
7803 :
7804 158692 : static void BuildRealProcedureCall (unsigned int tokno)
7805 : {
7806 158692 : unsigned int NoOfParam;
7807 158692 : unsigned int ProcSym;
7808 :
7809 158692 : M2Quads_PopT (&NoOfParam);
7810 158692 : M2Quads_PushT (NoOfParam);
7811 158692 : ProcSym = static_cast<unsigned int> (M2Quads_OperandT (NoOfParam+2));
7812 158692 : ProcSym = PCSymBuild_SkipConst (ProcSym);
7813 : /* --checkme-- */
7814 158692 : if (SymbolTable_IsVar (ProcSym))
7815 : {
7816 : /* Procedure Variable ? */
7817 684 : ProcSym = SymbolTable_SkipType (M2Quads_OperandF (NoOfParam+2));
7818 : }
7819 158692 : if ((SymbolTable_IsDefImp (SymbolTable_GetScope (ProcSym))) && (SymbolTable_IsDefinitionForC (SymbolTable_GetScope (ProcSym))))
7820 : {
7821 14726 : BuildRealFuncProcCall (tokno, false, true, false);
7822 : }
7823 : else
7824 : {
7825 143966 : BuildRealFuncProcCall (tokno, false, false, false);
7826 : }
7827 158686 : }
7828 :
7829 :
7830 : /*
7831 : BuildRealFuncProcCall - builds a real procedure or function call.
7832 : The Stack:
7833 :
7834 :
7835 : Entry Exit
7836 :
7837 : Ptr ->
7838 : +----------------+
7839 : | NoOfParam |
7840 : |----------------|
7841 : | Param 1 |
7842 : |----------------|
7843 : | Param 2 |
7844 : |----------------|
7845 : . .
7846 : . .
7847 : . .
7848 : |----------------|
7849 : | Param # |
7850 : |----------------|
7851 : | ProcSym | Type | Empty
7852 : |----------------|
7853 : */
7854 :
7855 220640 : static void BuildRealFuncProcCall (unsigned int tokno, bool IsFunc, bool IsForC, bool ConstExpr)
7856 : {
7857 220640 : bool AllocateProc;
7858 220640 : bool DeallocateProc;
7859 220640 : bool ForcedFunc;
7860 220640 : bool ParamConstant;
7861 220640 : unsigned int trash;
7862 220640 : unsigned int resulttok;
7863 220640 : unsigned int paramtok;
7864 220640 : unsigned int proctok;
7865 220640 : unsigned int NoOfParameters;
7866 220640 : unsigned int i;
7867 220640 : unsigned int pi;
7868 220640 : unsigned int ParamType;
7869 220640 : unsigned int Param1;
7870 220640 : unsigned int ReturnVar;
7871 220640 : unsigned int ProcSym;
7872 220640 : unsigned int Proc;
7873 :
7874 220640 : Param1 = SymbolTable_NulSym; /* Used to remember first param for allocate/deallocate. */
7875 220640 : ParamType = SymbolTable_NulSym;
7876 220640 : CheckProcedureParameters (IsForC);
7877 220622 : M2Quads_PopT (&NoOfParameters);
7878 220622 : M2Quads_PushT (NoOfParameters); /* Restore stack to original state. */
7879 220622 : ProcSym = static_cast<unsigned int> (M2Quads_OperandT (NoOfParameters+2)); /* Restore stack to original state. */
7880 220622 : proctok = tokno; /* OperandTtok (NoOfParameters+2) ; */
7881 220622 : if (proctok == M2LexBuf_UnknownTokenNo) /* OperandTtok (NoOfParameters+2) ; */
7882 : {
7883 0 : proctok = M2LexBuf_GetTokenNo ();
7884 : }
7885 220622 : paramtok = proctok;
7886 220622 : ProcSym = PCSymBuild_SkipConst (ProcSym);
7887 220622 : ForcedFunc = false;
7888 220622 : AllocateProc = false;
7889 220622 : DeallocateProc = false;
7890 220622 : if (SymbolTable_IsVar (ProcSym))
7891 : {
7892 : /* Procedure Variable ? */
7893 772 : Proc = SymbolTable_SkipType (M2Quads_OperandF (NoOfParameters+2));
7894 772 : ParamConstant = false;
7895 : }
7896 : else
7897 : {
7898 219850 : Proc = ProcSym;
7899 219850 : ParamConstant = true;
7900 219850 : AllocateProc = (SymbolTable_GetSymName (Proc)) == (NameKey_MakeKey ((const char *) "ALLOCATE", 8));
7901 219850 : DeallocateProc = (SymbolTable_GetSymName (Proc)) == (NameKey_MakeKey ((const char *) "DEALLOCATE", 10));
7902 : }
7903 220622 : if (IsFunc)
7904 : {
7905 : /* avoid dangling else. */
7906 61936 : if ((SymbolTable_GetSType (Proc)) == SymbolTable_NulSym)
7907 : {
7908 0 : M2MetaError_MetaErrors1 ((const char *) "procedure {%1a} cannot be used as a function", 44, (const char *) "procedure {%1Da} does not have a return type", 44, Proc);
7909 : }
7910 : }
7911 : else
7912 : {
7913 : /* is being called as a procedure */
7914 158686 : if ((SymbolTable_GetSType (Proc)) != SymbolTable_NulSym)
7915 : {
7916 : /* however it was declared as a procedure function */
7917 9069 : if (! (SymbolTable_IsReturnOptionalAny (Proc)))
7918 : {
7919 6 : M2MetaError_MetaErrors1 ((const char *) "function {%1a} is being called but its return value is ignored", 62, (const char *) "function {%1Da} return a type {%1ta:of {%1ta}}", 46, Proc);
7920 : }
7921 : IsFunc = true;
7922 : ForcedFunc = true;
7923 : }
7924 : }
7925 220622 : if (AllocateProc || DeallocateProc)
7926 : {
7927 1830 : Param1 = static_cast<unsigned int> (M2Quads_OperandT (NoOfParameters+1)); /* Remember this before manipulating. */
7928 : }
7929 220622 : ManipulateParameters (IsForC);
7930 220622 : CheckParameterOrdinals ();
7931 220622 : M2Quads_PopT (&NoOfParameters);
7932 220622 : if (IsFunc)
7933 : {
7934 71005 : GenQuad (M2Quads_ParamOp, 0, Proc, ProcSym); /* Space for return value */
7935 : }
7936 220622 : if (((NoOfParameters+1) == (SymbolTable_NoOfParamAny (Proc))) && (SymbolTable_UsesOptArgAny (Proc)))
7937 : {
7938 3626 : GenQuad (M2Quads_OptParamOp, SymbolTable_NoOfParamAny (Proc), Proc, Proc);
7939 : }
7940 220622 : i = NoOfParameters;
7941 220622 : pi = 1; /* stack index referencing stacked parameter, i */
7942 768233 : while (i > 0) /* stack index referencing stacked parameter, i */
7943 : {
7944 547611 : paramtok = OperandTtok (pi);
7945 547611 : if (((AllocateProc || DeallocateProc) && (i == 1)) && (Param1 != SymbolTable_NulSym))
7946 : {
7947 1830 : ParamType = GetItemPointedTo (Param1);
7948 1830 : if (ParamType == SymbolTable_NulSym)
7949 : {
7950 0 : GenQuadO (paramtok, M2Quads_ParamOp, i, Proc, M2Quads_OperandT (pi), true);
7951 : }
7952 : else
7953 : {
7954 1830 : if (AllocateProc)
7955 : {
7956 1282 : trash = SymbolTable_MakeTemporary (paramtok, SymbolTable_RightValue);
7957 1282 : SymbolTable_PutVar (trash, ParamType);
7958 1282 : SymbolTable_PutVarHeap (trash, true);
7959 : }
7960 : else
7961 : {
7962 548 : M2Debug_Assert (DeallocateProc);
7963 548 : trash = M2Base_Nil;
7964 : }
7965 1830 : GenQuadOTrash (paramtok, M2Quads_ParamOp, i, Proc, M2Quads_OperandT (pi), true, trash);
7966 : }
7967 : }
7968 : else
7969 : {
7970 545781 : GenQuadO (paramtok, M2Quads_ParamOp, i, Proc, M2Quads_OperandT (pi), true);
7971 : }
7972 547611 : if (! (SymbolTable_IsConst (M2Quads_OperandT (pi))))
7973 : {
7974 462280 : ParamConstant = false;
7975 : }
7976 547611 : i -= 1;
7977 547611 : pi += 1;
7978 : }
7979 441244 : GenQuadO (proctok, M2Quads_CallOp, SymbolTable_NulSym, SymbolTable_NulSym, ProcSym, true);
7980 220622 : M2Quads_PopN (NoOfParameters+1); /* Destroy arguments and procedure call */
7981 220622 : if (IsFunc)
7982 : {
7983 : /* ReturnVar has the type of the procedure. */
7984 71005 : resulttok = M2LexBuf_MakeVirtualTok (proctok, proctok, paramtok);
7985 71005 : if (ConstExpr && (! (SymbolTable_IsProcedureBuiltinAvailable (Proc))))
7986 : {
7987 0 : M2MetaError_MetaError1 ((const char *) "{%1d} {%1ad} cannot be used in a constant expression", 52, Proc);
7988 0 : ParamConstant = false;
7989 : }
7990 71005 : ReturnVar = SymbolTable_MakeTemporary (resulttok, AreConstant (ParamConstant && ConstExpr));
7991 71005 : SymbolTable_PutVar (ReturnVar, SymbolTable_GetSType (Proc));
7992 142010 : GenQuadO (resulttok, M2Quads_FunctValueOp, ReturnVar, SymbolTable_NulSym, Proc, true);
7993 71005 : if (! ForcedFunc)
7994 : {
7995 61936 : M2Quads_PushTFtok (ReturnVar, SymbolTable_GetSType (Proc), resulttok);
7996 : }
7997 : }
7998 220622 : }
7999 :
8000 :
8001 : /*
8002 : CheckProcedureParameters - Checks the parameters which are being passed to
8003 : procedure ProcSym.
8004 :
8005 : The Stack:
8006 :
8007 :
8008 : Entry Exit
8009 :
8010 : Ptr -> <- Ptr
8011 : +----------------+ +----------------+
8012 : | NoOfParam | | NoOfParam |
8013 : |----------------| |----------------|
8014 : | Param 1 | | Param 1 |
8015 : |----------------| |----------------|
8016 : | Param 2 | | Param 2 |
8017 : |----------------| |----------------|
8018 : . . . .
8019 : . . . .
8020 : . . . .
8021 : |----------------| |----------------|
8022 : | Param # | | Param # |
8023 : |----------------| |----------------|
8024 : | ProcSym | Type | | ProcSym | Type |
8025 : |----------------| |----------------|
8026 :
8027 : */
8028 :
8029 220640 : static void CheckProcedureParameters (bool IsForC)
8030 : {
8031 220640 : unsigned int proctok;
8032 220640 : unsigned int paramtok;
8033 220640 : NameKey_Name n1;
8034 220640 : NameKey_Name n2;
8035 220640 : unsigned int ParamCheckId;
8036 220640 : unsigned int Dim;
8037 220640 : unsigned int Actual;
8038 220640 : unsigned int FormalI;
8039 220640 : unsigned int ParamTotal;
8040 220640 : unsigned int pi;
8041 220640 : unsigned int Proc;
8042 220640 : unsigned int ProcSym;
8043 220640 : unsigned int i;
8044 220640 : DynamicStrings_String s;
8045 :
8046 220640 : M2Quads_PopT (&ParamTotal);
8047 220640 : M2Quads_PushT (ParamTotal); /* Restore stack to origional state */
8048 220640 : ProcSym = static_cast<unsigned int> (M2Quads_OperandT ((ParamTotal+1)+1)); /* Restore stack to origional state */
8049 220640 : proctok = OperandTtok ((ParamTotal+1)+1);
8050 220640 : if ((SymbolTable_IsVar (ProcSym)) && (SymbolTable_IsProcType (SymbolTable_GetDType (ProcSym))))
8051 : {
8052 : /* Procedure Variable ? */
8053 772 : Proc = SymbolTable_SkipType (M2Quads_OperandF ((ParamTotal+1)+1));
8054 : }
8055 : else
8056 : {
8057 219868 : Proc = PCSymBuild_SkipConst (ProcSym);
8058 : }
8059 220640 : if (! ((SymbolTable_IsProcedure (Proc)) || (SymbolTable_IsProcType (Proc))))
8060 : {
8061 : /* avoid gcc warning by using compound statement even if not strictly necessary. */
8062 12 : if (SymbolTable_IsUnknown (Proc))
8063 : {
8064 : /* Spellcheck. */
8065 0 : M2MetaError_MetaError1 ((const char *) "{%1Ua} is not recognised as a procedure, check declaration or import {%1&s}", 75, Proc);
8066 0 : SymbolTable_UnknownReported (Proc);
8067 : }
8068 : else
8069 : {
8070 : /* --fixme-- filter on Var, Const, Procedure. */
8071 12 : M2MetaError_MetaErrors1 ((const char *) "{%1a} is not recognised as a procedure, check declaration or import {%1&s}", 74, (const char *) "{%1Ua} is not recognised as a procedure, check declaration or import", 68, Proc);
8072 : }
8073 : }
8074 220640 : if (M2Options_CompilerDebugging)
8075 : {
8076 0 : n1 = SymbolTable_GetSymName (Proc);
8077 0 : M2Printf_printf1 ((const char *) " %a ( ", 7, (const unsigned char *) &n1, (sizeof (n1)-1));
8078 : }
8079 220640 : if (DebugTokPos)
8080 : {
8081 : s = DynamicStrings_InitString ((const char *) "procedure", 9);
8082 : M2Error_WarnStringAt (s, proctok);
8083 : }
8084 220640 : i = 1;
8085 220640 : pi = ParamTotal+1; /* stack index referencing stacked parameter, i */
8086 765117 : while (i <= ParamTotal) /* stack index referencing stacked parameter, i */
8087 : {
8088 544495 : if (i <= (SymbolTable_NoOfParamAny (Proc)))
8089 : {
8090 : /* FormalI := GetParam(Proc, i) ; */
8091 539229 : FormalI = SymbolTable_GetNthParamAnyClosest (Proc, i, SymbolTable_GetCurrentModule ());
8092 539229 : if (M2Options_CompilerDebugging)
8093 : {
8094 0 : n1 = SymbolTable_GetSymName (FormalI);
8095 0 : n2 = SymbolTable_GetSymName (SymbolTable_GetSType (FormalI));
8096 0 : M2Printf_printf2 ((const char *) "%a: %a", 6, (const unsigned char *) &n1, (sizeof (n1)-1), (const unsigned char *) &n2, (sizeof (n2)-1));
8097 : }
8098 539229 : Actual = static_cast<unsigned int> (M2Quads_OperandT (pi));
8099 539229 : Dim = static_cast<unsigned int> (OperandD (pi));
8100 539229 : paramtok = OperandTtok (pi);
8101 539229 : if (DebugTokPos)
8102 : {
8103 : s = DynamicStrings_InitString ((const char *) "actual", 6);
8104 : M2Error_WarnStringAt (s, paramtok);
8105 : }
8106 539229 : ParamCheckId = M2Range_InitTypesParameterCheck (paramtok, Proc, i, FormalI, Actual, 0);
8107 539229 : BuildRange (ParamCheckId);
8108 : /* Store the ParamCheckId on the quad stack so that any dependant checks
8109 : can be cancelled if the type check above detects an error. */
8110 539229 : PutRangeDep (pi, ParamCheckId);
8111 539229 : if (SymbolTable_IsConst (Actual))
8112 : {
8113 : /* avoid dangling else. */
8114 120815 : if (SymbolTable_IsVarParamAny (Proc, i))
8115 : {
8116 0 : FailParameter (paramtok, (const char *) "trying to pass a constant to a VAR parameter", 44, Actual, Proc, i);
8117 : }
8118 120815 : else if (SymbolTable_IsConstString (Actual))
8119 : {
8120 : /* avoid dangling else. */
8121 39548 : if (! (SymbolTable_IsConstStringKnown (Actual)))
8122 : {} /* empty. */
8123 39314 : else if ((SymbolTable_IsArray (SymbolTable_GetDType (FormalI))) && ((SymbolTable_GetSType (SymbolTable_GetDType (FormalI))) == M2Base_Char))
8124 : {
8125 : /* avoid dangling else. */
8126 : }
8127 39290 : else if ((SymbolTable_GetStringLength (paramtok, Actual)) == 1)
8128 : {
8129 : /* avoid dangling else. */
8130 5408 : CheckParameter (paramtok, Actual, Dim, FormalI, Proc, i, static_cast<Lists_List> (NULL), ParamCheckId);
8131 : }
8132 33882 : else if (! (SymbolTable_IsUnboundedParamAny (Proc, i)))
8133 : {
8134 : /* avoid dangling else. */
8135 0 : if (IsForC && ((SymbolTable_GetSType (FormalI)) == M2System_Address))
8136 : {
8137 0 : FailParameter (paramtok, (const char *) "a string constant can either be passed to an ADDRESS parameter or an ARRAY OF CHAR", 82, Actual, Proc, i);
8138 : }
8139 : else
8140 : {
8141 0 : FailParameter (paramtok, (const char *) "cannot pass a string constant to a non unbounded array parameter", 64, Actual, Proc, i);
8142 : }
8143 : }
8144 : }
8145 : }
8146 : else
8147 : {
8148 418414 : CheckParameter (paramtok, Actual, Dim, FormalI, Proc, i, static_cast<Lists_List> (NULL), ParamCheckId);
8149 : }
8150 : }
8151 : else
8152 : {
8153 5254 : if (IsForC && (SymbolTable_UsesVarArgs (Proc)))
8154 : {
8155 : /* these are varargs, therefore we don't check them */
8156 5254 : i = ParamTotal;
8157 : }
8158 : else
8159 : {
8160 0 : M2MetaError_MetaErrorT2 (proctok, (const char *) "too many parameters, {%2n} passed to {%1a} ", 43, Proc, i);
8161 : }
8162 : }
8163 544477 : i += 1;
8164 544477 : pi -= 1;
8165 544477 : if (M2Options_CompilerDebugging)
8166 : {
8167 : /* avoid gcc warning by using compound statement even if not strictly necessary. */
8168 0 : if (i <= ParamTotal)
8169 : {
8170 0 : M2Printf_printf0 ((const char *) "; ", 2);
8171 : }
8172 : else
8173 : {
8174 0 : M2Printf_printf0 ((const char *) " ) ; \\n", 7);
8175 : }
8176 : }
8177 : }
8178 220622 : }
8179 :
8180 :
8181 : /*
8182 : CheckProcTypeAndProcedure - checks the ProcType with the call.
8183 : */
8184 :
8185 49261 : static void CheckProcTypeAndProcedure (unsigned int tokno, unsigned int ProcType, unsigned int call, unsigned int ParamCheckId)
8186 : {
8187 49261 : NameKey_Name n1;
8188 49261 : NameKey_Name n2;
8189 49261 : unsigned int i;
8190 49261 : unsigned int n;
8191 49261 : unsigned int t;
8192 49261 : unsigned int CheckedProcedure;
8193 49261 : M2Error_Error e;
8194 :
8195 49261 : if (((SymbolTable_IsVar (call)) || (SymbolTable_IsTemporary (call))) || (SymbolTable_IsParameter (call)))
8196 : {
8197 592 : CheckedProcedure = SymbolTable_GetDType (call);
8198 : }
8199 : else
8200 : {
8201 : CheckedProcedure = call;
8202 : }
8203 49261 : if (ProcType != CheckedProcedure)
8204 : {
8205 48739 : n = SymbolTable_NoOfParamAny (ProcType);
8206 : /* We need to check the formal parameters between the procedure and proc type. */
8207 48739 : if (n != (SymbolTable_NoOfParamAny (CheckedProcedure)))
8208 : {
8209 0 : e = M2Error_NewError (SymbolTable_GetDeclaredMod (ProcType));
8210 0 : n1 = SymbolTable_GetSymName (call);
8211 0 : n2 = SymbolTable_GetSymName (ProcType);
8212 0 : M2Error_ErrorFormat2 (e, (const char *) "procedure (%a) is a parameter being passed as variable (%a) but they are declared with different number of parameters", 117, (const unsigned char *) &n1, (sizeof (n1)-1), (const unsigned char *) &n2, (sizeof (n2)-1));
8213 0 : e = M2Error_ChainError (SymbolTable_GetDeclaredMod (call), e);
8214 0 : t = SymbolTable_NoOfParamAny (CheckedProcedure);
8215 0 : if (n < 2)
8216 : {
8217 0 : M2Error_ErrorFormat3 (e, (const char *) "procedure (%a) is being called incorrectly with (%d) parameter, declared with (%d)", 82, (const unsigned char *) &n1, (sizeof (n1)-1), (const unsigned char *) &n, (sizeof (n)-1), (const unsigned char *) &t, (sizeof (t)-1));
8218 : }
8219 : else
8220 : {
8221 0 : M2Error_ErrorFormat3 (e, (const char *) "procedure (%a) is being called incorrectly with (%d) parameters, declared with (%d)", 83, (const unsigned char *) &n1, (sizeof (n1)-1), (const unsigned char *) &n, (sizeof (n)-1), (const unsigned char *) &t, (sizeof (t)-1));
8222 : }
8223 : }
8224 : else
8225 : {
8226 : i = 1;
8227 145247 : while (i <= n)
8228 : {
8229 96508 : if ((SymbolTable_IsVarParamAny (ProcType, i)) != (SymbolTable_IsVarParamAny (CheckedProcedure, i)))
8230 : {
8231 0 : M2MetaError_MetaError3 ((const char *) "parameter {%3n} in {%1dD} causes a mismatch it was declared as a {%2dv}", 71, ProcType, SymbolTable_GetNth (ProcType, i), i);
8232 0 : M2MetaError_MetaError3 ((const char *) "parameter {%3n} in {%1dD} causes a mismatch it was declared as a {%2dv}", 71, call, SymbolTable_GetNth (call, i), i);
8233 : }
8234 96508 : BuildRange (M2Range_InitTypesParameterCheck (tokno, CheckedProcedure, i, SymbolTable_GetNthParamAnyClosest (CheckedProcedure, i, SymbolTable_GetCurrentModule ()), SymbolTable_GetParam (ProcType, i), ParamCheckId));
8235 96508 : i += 1;
8236 : }
8237 : }
8238 : }
8239 49261 : }
8240 :
8241 :
8242 : /*
8243 : IsReallyPointer - returns TRUE is sym is a pointer, address or a type declared
8244 : as a pointer or address.
8245 : */
8246 :
8247 1277 : static bool IsReallyPointer (unsigned int Sym)
8248 : {
8249 1277 : if (SymbolTable_IsVar (Sym))
8250 : {
8251 1276 : Sym = SymbolTable_GetSType (Sym);
8252 : }
8253 1277 : Sym = SymbolTable_SkipType (Sym);
8254 1277 : return (SymbolTable_IsPointer (Sym)) || (Sym == M2System_Address);
8255 : /* static analysis guarentees a RETURN statement will be used before here. */
8256 : __builtin_unreachable ();
8257 : }
8258 :
8259 :
8260 : /*
8261 : LegalUnboundedParam - returns TRUE if the parameter, Actual, can legitimately be
8262 : passed to ProcSym, i, the, Formal, parameter.
8263 : */
8264 :
8265 9930 : static bool LegalUnboundedParam (unsigned int tokpos, unsigned int ProcSym, unsigned int i, unsigned int ActualType, unsigned int Actual, unsigned int Dimension, unsigned int Formal)
8266 : {
8267 9930 : unsigned int FormalType;
8268 9930 : unsigned int n;
8269 9930 : unsigned int m;
8270 :
8271 9930 : ActualType = SymbolTable_SkipType (ActualType);
8272 9930 : FormalType = SymbolTable_GetDType (Formal);
8273 9930 : FormalType = SymbolTable_GetSType (FormalType); /* type of the unbounded ARRAY */
8274 9930 : if (SymbolTable_IsArray (ActualType)) /* type of the unbounded ARRAY */
8275 : {
8276 6900 : m = SymbolTable_GetDimension (Formal);
8277 6900 : n = 0;
8278 14046 : while (SymbolTable_IsArray (ActualType))
8279 : {
8280 7068 : n += 1;
8281 7068 : ActualType = SymbolTable_GetDType (ActualType);
8282 7068 : if ((m == n) && (ActualType == FormalType))
8283 : {
8284 : return true;
8285 : }
8286 : }
8287 78 : if (n == m)
8288 : {} /* empty. */
8289 : else
8290 : {
8291 : /* now we fall though and test ActualType against FormalType */
8292 24 : if (M2System_IsGenericSystemType (FormalType))
8293 : {
8294 : return true;
8295 : }
8296 : else
8297 : {
8298 12 : FailParameter (tokpos, (const char *) "attempting to pass an array with the incorrect number dimenisons to an unbounded formal parameter of different dimensions", 121, Actual, ProcSym, i);
8299 12 : return false;
8300 : }
8301 : }
8302 : }
8303 3030 : else if (SymbolTable_IsUnbounded (ActualType))
8304 : {
8305 : /* avoid dangling else. */
8306 36 : if ((Dimension == 0) && ((SymbolTable_GetDimension (Formal)) == (SymbolTable_GetDimension (Actual))))
8307 : {
8308 : /* now we fall though and test ActualType against FormalType */
8309 0 : ActualType = SymbolTable_GetSType (ActualType);
8310 : }
8311 : else
8312 : {
8313 36 : if (M2System_IsGenericSystemType (FormalType))
8314 : {
8315 : return true;
8316 : }
8317 : else
8318 : {
8319 12 : if (((SymbolTable_GetDimension (Actual))-Dimension) == (SymbolTable_GetDimension (Formal)))
8320 : {
8321 12 : ActualType = SymbolTable_GetSType (ActualType);
8322 : }
8323 : else
8324 : {
8325 0 : FailParameter (tokpos, (const char *) "attempting to pass an unbounded array with the incorrect number dimenisons to an unbounded formal parameter of different dimensions", 131, Actual, ProcSym, i);
8326 0 : return false;
8327 : }
8328 : }
8329 : }
8330 : }
8331 3060 : if (((M2System_IsGenericSystemType (FormalType)) || (M2System_IsGenericSystemType (ActualType))) || (M2Base_IsAssignmentCompatible (FormalType, ActualType)))
8332 : {
8333 : /* we think it is legal, but we ask post pass 3 to check as
8334 : not all types are known at this point */
8335 3054 : return true;
8336 : }
8337 : else
8338 : {
8339 6 : FailParameter (tokpos, (const char *) "identifier with an incompatible type is being passed to this procedure", 70, Actual, ProcSym, i);
8340 6 : return false;
8341 : }
8342 : /* static analysis guarentees a RETURN statement will be used before here. */
8343 : __builtin_unreachable ();
8344 : }
8345 :
8346 :
8347 : /*
8348 : CheckParameter - checks that types ActualType and FormalType are compatible for parameter
8349 : passing. ProcSym is the procedure and i is the parameter number.
8350 :
8351 : We obey the following rules:
8352 :
8353 : (1) we allow WORD, BYTE, LOC to be compitable with any like sized
8354 : type.
8355 : (2) we allow ADDRESS to be compatible with any pointer type.
8356 : (3) we relax INTEGER and CARDINAL checking for Temporary variables.
8357 :
8358 : Note that type sizes are checked during the code generation pass.
8359 : */
8360 :
8361 423822 : static void CheckParameter (unsigned int tokpos, unsigned int Actual, unsigned int Dimension, unsigned int Formal, unsigned int ProcSym, unsigned int i, Lists_List TypeList, unsigned int ParamCheckId)
8362 : {
8363 423822 : bool NewList;
8364 423822 : unsigned int ActualType;
8365 423822 : unsigned int FormalType;
8366 :
8367 423822 : if ((SymbolTable_IsConstString (Actual)) && (! (SymbolTable_IsConstStringKnown (Actual))))
8368 : {
8369 : /* Cannot check if the string content is not yet known. */
8370 : return;
8371 : }
8372 423822 : FormalType = SymbolTable_GetDType (Formal);
8373 423822 : if ((SymbolTable_IsConstString (Actual)) && ((SymbolTable_GetStringLength (tokpos, Actual)) == 1)) /* if = 1 then it maybe treated as a char */
8374 : {
8375 5408 : ActualType = M2Base_Char;
8376 : }
8377 418414 : else if (Actual == M2Base_Boolean)
8378 : {
8379 : /* avoid dangling else. */
8380 : ActualType = Actual;
8381 : }
8382 : else
8383 : {
8384 : /* avoid dangling else. */
8385 418414 : ActualType = SymbolTable_GetDType (Actual);
8386 : }
8387 423816 : if (TypeList == NULL)
8388 : {
8389 423816 : NewList = true;
8390 423816 : Lists_InitList (&TypeList);
8391 : }
8392 : else
8393 : {
8394 : NewList = false;
8395 : }
8396 423816 : if (Lists_IsItemInList (TypeList, ActualType))
8397 : {
8398 : /* no need to check */
8399 : return;
8400 : }
8401 423816 : Lists_IncludeItemIntoList (TypeList, ActualType);
8402 423816 : if (SymbolTable_IsProcType (FormalType))
8403 : {
8404 49261 : if ((! (SymbolTable_IsProcedure (Actual))) && ((ActualType == SymbolTable_NulSym) || (! (SymbolTable_IsProcType (SymbolTable_SkipType (ActualType))))))
8405 : {
8406 0 : FailParameter (tokpos, (const char *) "expecting a procedure or procedure variable as a parameter", 58, Actual, ProcSym, i);
8407 0 : return;
8408 : }
8409 49261 : if ((SymbolTable_IsProcedure (Actual)) && (SymbolTable_IsProcedureNested (Actual)))
8410 : {
8411 6 : M2MetaError_MetaError2 ((const char *) "cannot pass a nested procedure {%1Ea} seen in the {%2N} parameter as the outer scope will be unknown at runtime", 111, Actual, i);
8412 : }
8413 : /* we can check the return type of both proc types */
8414 49261 : if ((ActualType != SymbolTable_NulSym) && (SymbolTable_IsProcType (ActualType)))
8415 : {
8416 : /* avoid gcc warning by using compound statement even if not strictly necessary. */
8417 592 : if (((SymbolTable_GetSType (ActualType)) != SymbolTable_NulSym) && ((SymbolTable_GetSType (FormalType)) == SymbolTable_NulSym))
8418 : {
8419 0 : FailParameter (tokpos, (const char *) "the item being passed is a function whereas the formal procedure parameter is a procedure", 89, Actual, ProcSym, i);
8420 0 : return;
8421 : }
8422 592 : else if (((SymbolTable_GetSType (ActualType)) == SymbolTable_NulSym) && ((SymbolTable_GetSType (FormalType)) != SymbolTable_NulSym))
8423 : {
8424 : /* avoid dangling else. */
8425 0 : FailParameter (tokpos, (const char *) "the item being passed is a procedure whereas the formal procedure parameter is a function", 89, Actual, ProcSym, i);
8426 0 : return;
8427 : }
8428 592 : else if (M2Base_AssignmentRequiresWarning (SymbolTable_GetSType (ActualType), SymbolTable_GetSType (FormalType)))
8429 : {
8430 : /* avoid dangling else. */
8431 0 : WarnParameter (tokpos, (const char *) "the return result of the procedure variable parameter may not be compatible on other targets with the return result of the item being passed", 140, Actual, ProcSym, i);
8432 0 : return;
8433 : }
8434 592 : else if (((M2System_IsGenericSystemType (SymbolTable_GetSType (FormalType))) || (M2System_IsGenericSystemType (SymbolTable_GetSType (ActualType)))) || (M2Base_IsAssignmentCompatible (SymbolTable_GetSType (ActualType), SymbolTable_GetSType (FormalType))))
8435 : {
8436 : /* avoid dangling else. */
8437 : }
8438 : else
8439 : {
8440 : /* avoid dangling else. */
8441 : /* pass */
8442 0 : FailParameter (tokpos, (const char *) "the return result of the procedure variable parameter is not compatible with the return result of the item being passed", 119, Actual, ProcSym, i);
8443 0 : return;
8444 : }
8445 : }
8446 : /* now to check each parameter of the proc type */
8447 49261 : CheckProcTypeAndProcedure (tokpos, FormalType, Actual, ParamCheckId);
8448 : }
8449 374555 : else if ((ActualType != FormalType) && (ActualType != SymbolTable_NulSym))
8450 : {
8451 : /* avoid dangling else. */
8452 17880 : if (SymbolTable_IsUnknown (FormalType))
8453 : {
8454 : /* Spellcheck. */
8455 0 : FailParameter (tokpos, (const char *) "procedure parameter type is undeclared {%1&s}", 45, Actual, ProcSym, i);
8456 0 : return;
8457 : }
8458 17880 : if ((SymbolTable_IsUnbounded (ActualType)) && (! (SymbolTable_IsUnboundedParamAny (ProcSym, i))))
8459 : {
8460 0 : FailParameter (tokpos, (const char *) "attempting to pass an unbounded array to a NON unbounded parameter", 66, Actual, ProcSym, i);
8461 0 : return;
8462 : }
8463 17880 : else if (SymbolTable_IsUnboundedParamAny (ProcSym, i))
8464 : {
8465 : /* avoid dangling else. */
8466 9930 : if (! (LegalUnboundedParam (tokpos, ProcSym, i, ActualType, Actual, Dimension, Formal)))
8467 : {
8468 : return;
8469 : }
8470 : }
8471 7950 : else if (ActualType != FormalType)
8472 : {
8473 : /* avoid dangling else. */
8474 7950 : if (M2Base_AssignmentRequiresWarning (FormalType, ActualType))
8475 : {
8476 0 : WarnParameter (tokpos, (const char *) "identifier being passed to this procedure may contain a possibly incompatible type when compiling for a different target", 120, Actual, ProcSym, i);
8477 : }
8478 7950 : else if (((M2System_IsGenericSystemType (FormalType)) || (M2System_IsGenericSystemType (ActualType))) || (M2Base_IsAssignmentCompatible (ActualType, FormalType)))
8479 : {
8480 : /* avoid dangling else. */
8481 : }
8482 : else
8483 : {
8484 : /* avoid dangling else. */
8485 : /* so far we know it is legal, but not all types have been resolved
8486 : and so this is checked later on in another pass. */
8487 24 : FailParameter (tokpos, (const char *) "identifier with an incompatible type is being passed to this procedure", 70, Actual, ProcSym, i);
8488 : }
8489 : }
8490 : }
8491 423798 : if (NewList)
8492 : {
8493 423798 : Lists_KillList (&TypeList);
8494 : }
8495 : }
8496 :
8497 :
8498 : /*
8499 : DescribeType - returns a String describing a symbol, Sym, name and its type.
8500 : */
8501 :
8502 0 : static DynamicStrings_String DescribeType (unsigned int Sym)
8503 : {
8504 0 : DynamicStrings_String s;
8505 0 : DynamicStrings_String s1;
8506 0 : DynamicStrings_String s2;
8507 0 : unsigned int Low;
8508 0 : unsigned int High;
8509 0 : unsigned int Subrange;
8510 0 : unsigned int Subscript;
8511 0 : unsigned int Type;
8512 :
8513 0 : s = static_cast<DynamicStrings_String> (NULL);
8514 0 : if (SymbolTable_IsConstString (Sym))
8515 : {
8516 : /* If = 1 then it maybe treated as a char. */
8517 0 : if ((SymbolTable_IsConstStringKnown (Sym)) && ((SymbolTable_GetStringLength (SymbolTable_GetDeclaredMod (Sym), Sym)) == 1))
8518 : {
8519 0 : s = DynamicStrings_InitString ((const char *) "(constant string) or {%kCHAR}", 29);
8520 : }
8521 : else
8522 : {
8523 0 : s = DynamicStrings_InitString ((const char *) "(constant string)", 17);
8524 : }
8525 : }
8526 0 : else if (SymbolTable_IsConst (Sym))
8527 : {
8528 : /* avoid dangling else. */
8529 0 : s = DynamicStrings_InitString ((const char *) "(constant)", 10);
8530 : }
8531 0 : else if (SymbolTable_IsUnknown (Sym))
8532 : {
8533 : /* avoid dangling else. */
8534 0 : s = DynamicStrings_InitString ((const char *) "(unknown)", 9);
8535 : }
8536 : else
8537 : {
8538 : /* avoid dangling else. */
8539 0 : Type = SymbolTable_GetSType (Sym);
8540 0 : if (Type == SymbolTable_NulSym)
8541 : {
8542 0 : s = DynamicStrings_InitString ((const char *) "(unknown)", 9);
8543 : }
8544 0 : else if (SymbolTable_IsUnbounded (Type))
8545 : {
8546 : /* avoid dangling else. */
8547 0 : s1 = DynamicStrings_Mark (DynamicStrings_InitStringCharStar (NameKey_KeyToCharStar (SymbolTable_GetSymName (SymbolTable_GetSType (Type)))));
8548 0 : s = FormatStrings_Sprintf1 (DynamicStrings_Mark (DynamicStrings_InitString ((const char *) "{%%kARRAY} {%%kOF} %s", 21)), (const unsigned char *) &s1, (sizeof (s1)-1));
8549 : }
8550 0 : else if (SymbolTable_IsArray (Type))
8551 : {
8552 : /* avoid dangling else. */
8553 0 : s = DynamicStrings_InitString ((const char *) "{%kARRAY} [", 11);
8554 0 : Subscript = SymbolTable_GetArraySubscript (Type);
8555 0 : if (Subscript != SymbolTable_NulSym)
8556 : {
8557 0 : M2Debug_Assert (SymbolTable_IsSubscript (Subscript));
8558 0 : Subrange = SymbolTable_GetSType (Subscript);
8559 0 : if (! (SymbolTable_IsSubrange (Subrange)))
8560 : {
8561 0 : M2MetaError_MetaError3 ((const char *) "error in definition of array {%1Ead} in the {%2N} subscript which has no subrange, instead type given is {%3a}", 110, Sym, Subscript, Subrange);
8562 : }
8563 0 : M2Debug_Assert (SymbolTable_IsSubrange (Subrange));
8564 0 : SymbolTable_GetSubrange (Subrange, &High, &Low);
8565 0 : s1 = DynamicStrings_Mark (DynamicStrings_InitStringCharStar (NameKey_KeyToCharStar (SymbolTable_GetSymName (Low))));
8566 0 : s2 = DynamicStrings_Mark (DynamicStrings_InitStringCharStar (NameKey_KeyToCharStar (SymbolTable_GetSymName (High))));
8567 0 : s = DynamicStrings_ConCat (s, DynamicStrings_Mark (FormatStrings_Sprintf2 (DynamicStrings_Mark (DynamicStrings_InitString ((const char *) "%s..%s", 6)), (const unsigned char *) &s1, (sizeof (s1)-1), (const unsigned char *) &s2, (sizeof (s2)-1))));
8568 : }
8569 0 : s1 = DynamicStrings_Mark (DescribeType (Type));
8570 0 : s = DynamicStrings_ConCat (DynamicStrings_ConCat (s, DynamicStrings_Mark (DynamicStrings_InitString ((const char *) "] OF ", 5))), s1);
8571 : }
8572 : else
8573 : {
8574 : /* avoid dangling else. */
8575 0 : if (SymbolTable_IsUnknown (Type))
8576 : {
8577 : /* Spellcheck. */
8578 0 : s1 = DynamicStrings_Mark (DynamicStrings_InitStringCharStar (NameKey_KeyToCharStar (SymbolTable_GetSymName (Type))));
8579 0 : s = FormatStrings_Sprintf1 (DynamicStrings_Mark (DynamicStrings_InitString ((const char *) "%s (currently unknown, check declaration or import) {%1&s}", 58)), (const unsigned char *) &s1, (sizeof (s1)-1));
8580 : }
8581 : else
8582 : {
8583 0 : s = DynamicStrings_InitStringCharStar (NameKey_KeyToCharStar (SymbolTable_GetSymName (Type)));
8584 : }
8585 : }
8586 : }
8587 0 : return s;
8588 : /* static analysis guarentees a RETURN statement will be used before here. */
8589 : __builtin_unreachable ();
8590 : }
8591 :
8592 :
8593 : /*
8594 : FailParameter - generates an error message indicating that a parameter
8595 : declaration has failed.
8596 :
8597 : The parameters are:
8598 :
8599 : CurrentState - string describing the current failing state.
8600 : Actual - actual parameter.
8601 : ParameterNo - parameter number that has failed.
8602 : ProcedureSym - procedure symbol where parameter has failed.
8603 :
8604 : If any parameter is Nul then it is ignored.
8605 : */
8606 :
8607 42 : static void FailParameter (unsigned int tokpos, const char *CurrentState_, unsigned int _CurrentState_high, unsigned int Actual, unsigned int ProcedureSym, unsigned int ParameterNo)
8608 : {
8609 42 : unsigned int FormalParam;
8610 42 : DynamicStrings_String Msg;
8611 42 : char CurrentState[_CurrentState_high+1];
8612 :
8613 : /* make a local copy of each unbounded array. */
8614 42 : memcpy (CurrentState, CurrentState_, _CurrentState_high+1);
8615 :
8616 84 : Msg = DynamicStrings_InitString ((const char *) "parameter mismatch between the {%2N} parameter of procedure {%1Ead}, ", 69);
8617 42 : Msg = DynamicStrings_ConCat (Msg, DynamicStrings_Mark (DynamicStrings_InitString ((const char *) CurrentState, _CurrentState_high)));
8618 42 : M2MetaError_MetaErrorStringT2 (tokpos, Msg, ProcedureSym, ParameterNo);
8619 42 : if ((SymbolTable_NoOfParamAny (ProcedureSym)) >= ParameterNo)
8620 : {
8621 42 : FormalParam = SymbolTable_GetNthParamAnyClosest (ProcedureSym, ParameterNo, SymbolTable_GetCurrentModule ());
8622 42 : if (SymbolTable_IsUnboundedParamAny (ProcedureSym, ParameterNo))
8623 : {
8624 18 : M2MetaError_MetaErrorT2 (SymbolTable_GetVarDeclFullTok (FormalParam), (const char *) "formal parameter {%1ad} has an open array type {%2tad}", 54, FormalParam, SymbolTable_GetSType (SymbolTable_GetSType (FormalParam)));
8625 : }
8626 : else
8627 : {
8628 24 : M2MetaError_MetaErrorT1 (SymbolTable_GetVarDeclFullTok (FormalParam), (const char *) "formal parameter {%1ad} has type {%1tad}", 40, FormalParam);
8629 : }
8630 : }
8631 : else
8632 : {
8633 0 : M2MetaError_MetaErrorT1 (SymbolTable_GetDeclaredMod (ProcedureSym), (const char *) "procedure declaration", 21, ProcedureSym);
8634 : }
8635 42 : if ((SymbolTable_GetLType (Actual)) == SymbolTable_NulSym)
8636 : {
8637 0 : M2MetaError_MetaError1 ((const char *) "actual parameter being passed is {%1Eda} {%1ad}", 47, Actual);
8638 : }
8639 : else
8640 : {
8641 42 : if (SymbolTable_IsVar (Actual))
8642 : {
8643 36 : M2MetaError_MetaErrorT1 (SymbolTable_GetVarDeclFullTok (Actual), (const char *) "actual parameter variable being passed is {%1Eda} {%1ad} of an incompatible type {%1ts}", 87, Actual);
8644 : }
8645 : else
8646 : {
8647 6 : M2MetaError_MetaErrorT1 (tokpos, (const char *) "actual parameter being passed is {%1Eda} {%1ad} of an incompatible type {%1ts}", 78, Actual);
8648 : }
8649 : }
8650 42 : }
8651 :
8652 :
8653 : /*
8654 : WarnParameter - generates a warning message indicating that a parameter
8655 : use might cause problems on another target.
8656 :
8657 : CurrentState - string describing the current failing state.
8658 : Actual - actual parameter.
8659 : ParameterNo - parameter number that has failed.
8660 : ProcedureSym - procedure symbol where parameter has failed.
8661 :
8662 : If any parameter is Nul then it is ignored.
8663 : */
8664 :
8665 0 : static void WarnParameter (unsigned int tokpos, const char *CurrentState_, unsigned int _CurrentState_high, unsigned int Actual, unsigned int ProcedureSym, unsigned int ParameterNo)
8666 : {
8667 0 : unsigned int FormalParam;
8668 0 : DynamicStrings_String Msg;
8669 0 : char CurrentState[_CurrentState_high+1];
8670 :
8671 : /* make a local copy of each unbounded array. */
8672 0 : memcpy (CurrentState, CurrentState_, _CurrentState_high+1);
8673 :
8674 0 : Msg = DynamicStrings_InitString ((const char *) "{%W}parameter mismatch between the {%2N} parameter of procedure {%1ad}, ", 72);
8675 0 : Msg = DynamicStrings_ConCat (Msg, DynamicStrings_Mark (DynamicStrings_InitString ((const char *) CurrentState, _CurrentState_high)));
8676 0 : M2MetaError_MetaErrorStringT2 (tokpos, Msg, ProcedureSym, ParameterNo);
8677 0 : if ((SymbolTable_NoOfParamAny (ProcedureSym)) >= ParameterNo)
8678 : {
8679 0 : FormalParam = SymbolTable_GetNthParamAnyClosest (ProcedureSym, ParameterNo, SymbolTable_GetCurrentModule ());
8680 0 : if (SymbolTable_IsUnboundedParamAny (ProcedureSym, ParameterNo))
8681 : {
8682 0 : M2MetaError_MetaErrorT2 (SymbolTable_GetVarDeclFullTok (FormalParam), (const char *) "{%W}formal parameter {%1ad} has an open array type {%2tad}", 58, FormalParam, SymbolTable_GetSType (SymbolTable_GetSType (FormalParam)));
8683 : }
8684 : else
8685 : {
8686 0 : M2MetaError_MetaErrorT1 (SymbolTable_GetVarDeclFullTok (FormalParam), (const char *) "{%W}formal parameter {%1ad} has type {%1tad}", 44, FormalParam);
8687 : }
8688 : }
8689 : else
8690 : {
8691 0 : M2MetaError_MetaErrorT1 (SymbolTable_GetDeclaredMod (ProcedureSym), (const char *) "{%W}procedure declaration", 25, ProcedureSym);
8692 : }
8693 0 : if ((SymbolTable_GetLType (Actual)) == SymbolTable_NulSym)
8694 : {
8695 0 : M2MetaError_MetaError1 ((const char *) "actual parameter being passed is {%1Wda} {%1ad}", 47, Actual);
8696 : }
8697 : else
8698 : {
8699 0 : if (SymbolTable_IsVar (Actual))
8700 : {
8701 0 : M2MetaError_MetaErrorT1 (SymbolTable_GetVarDeclFullTok (Actual), (const char *) "actual parameter variable being passed is {%1Wda} {%1ad} of type {%1ts}", 71, Actual);
8702 : }
8703 : else
8704 : {
8705 0 : M2MetaError_MetaErrorT1 (tokpos, (const char *) "actual parameter being passed is {%1Wda} {%1ad} of type {%1ts}", 62, Actual);
8706 : }
8707 : }
8708 0 : }
8709 :
8710 :
8711 : /*
8712 : doIndrX - perform des = *exp with a conversion if necessary.
8713 : */
8714 :
8715 16999 : static void doIndrX (unsigned int tok, unsigned int des, unsigned int exp)
8716 : {
8717 16999 : unsigned int t;
8718 :
8719 16999 : if ((SymbolTable_GetDType (des)) == (SymbolTable_GetDType (exp)))
8720 : {
8721 16481 : GenQuadOtok (tok, M2Quads_IndrXOp, des, SymbolTable_GetSType (des), exp, true, tok, tok, tok);
8722 : }
8723 : else
8724 : {
8725 518 : if (M2Options_StrictTypeAssignment)
8726 : {
8727 518 : BuildRange (M2Range_InitTypesIndrXCheck (tok, des, exp));
8728 : }
8729 518 : t = SymbolTable_MakeTemporary (tok, SymbolTable_RightValue);
8730 518 : SymbolTable_PutVar (t, SymbolTable_GetSType (exp));
8731 518 : GenQuadOtok (tok, M2Quads_IndrXOp, t, SymbolTable_GetSType (exp), exp, true, tok, tok, tok);
8732 518 : GenQuadOtok (tok, M2Quads_BecomesOp, des, SymbolTable_NulSym, doVal (SymbolTable_GetSType (des), t), true, tok, M2LexBuf_UnknownTokenNo, tok);
8733 : }
8734 16999 : }
8735 :
8736 :
8737 : /*
8738 : MakeRightValue - returns a temporary which will have the RightValue of symbol, Sym.
8739 : If Sym is a right value and has type, type, then no quadruples are
8740 : generated and Sym is returned. Otherwise a new temporary is created
8741 : and an IndrX quadruple is generated.
8742 : */
8743 :
8744 1520 : static unsigned int MakeRightValue (unsigned int tok, unsigned int Sym, unsigned int type)
8745 : {
8746 1520 : unsigned int t;
8747 :
8748 1520 : if ((SymbolTable_GetMode (Sym)) == SymbolTable_RightValue)
8749 : {
8750 0 : if ((SymbolTable_GetSType (Sym)) == type)
8751 : {
8752 : return Sym;
8753 : }
8754 : else
8755 : {
8756 : /*
8757 : type change or mode change, type changes are a pain, but I've
8758 : left them here as it is perhaps easier to remove them later.
8759 : */
8760 0 : t = SymbolTable_MakeTemporary (tok, SymbolTable_RightValue);
8761 0 : SymbolTable_PutVar (t, type);
8762 0 : GenQuadOtok (tok, M2Quads_BecomesOp, t, SymbolTable_NulSym, doVal (type, Sym), true, tok, tok, tok);
8763 0 : return t;
8764 : }
8765 : }
8766 : else
8767 : {
8768 1520 : t = SymbolTable_MakeTemporary (tok, SymbolTable_RightValue);
8769 1520 : SymbolTable_PutVar (t, type);
8770 1520 : CheckPointerThroughNil (tok, Sym);
8771 1520 : doIndrX (tok, t, Sym);
8772 1520 : return t;
8773 : }
8774 : /* static analysis guarentees a RETURN statement will be used before here. */
8775 : __builtin_unreachable ();
8776 : }
8777 :
8778 :
8779 : /*
8780 : MakeLeftValue - returns a temporary coresponding to the LeftValue of
8781 : symbol, Sym. No quadruple is generated if Sym is already
8782 : a LeftValue and has the same type.
8783 : */
8784 :
8785 198312 : static unsigned int MakeLeftValue (unsigned int tok, unsigned int Sym, SymbolTable_ModeOfAddr with, unsigned int type)
8786 : {
8787 198312 : unsigned int t;
8788 :
8789 198312 : if ((SymbolTable_GetMode (Sym)) == SymbolTable_LeftValue)
8790 : {
8791 5142 : if ((SymbolTable_GetSType (Sym)) == type)
8792 : {
8793 : return Sym;
8794 : }
8795 : else
8796 : {
8797 : /*
8798 : type change or mode change, type changes are a pain, but I've
8799 : left them here as it is perhaps easier to remove them later
8800 : */
8801 172 : t = SymbolTable_MakeTemporary (tok, with);
8802 172 : SymbolTable_PutVar (t, type);
8803 172 : GenQuadOtok (tok, M2Quads_BecomesOp, t, SymbolTable_NulSym, Sym, true, tok, M2LexBuf_UnknownTokenNo, tok);
8804 172 : return t;
8805 : }
8806 : }
8807 : else
8808 : {
8809 193170 : t = SymbolTable_MakeTemporary (tok, with);
8810 193170 : SymbolTable_PutVar (t, type);
8811 193170 : GenQuadOtok (tok, M2Quads_AddrOp, t, SymbolTable_NulSym, Sym, true, tok, M2LexBuf_UnknownTokenNo, tok);
8812 193170 : return t;
8813 : }
8814 : /* static analysis guarentees a RETURN statement will be used before here. */
8815 : __builtin_unreachable ();
8816 : }
8817 :
8818 :
8819 : /*
8820 : ManipulatePseudoCallParameters - manipulates the parameters to a pseudo function or
8821 : procedure. It dereferences all LeftValue parameters
8822 : and Boolean parameters.
8823 : The Stack:
8824 :
8825 :
8826 : Entry Exit
8827 :
8828 : Ptr -> exactly the same
8829 : +----------------+
8830 : | NoOfParameters |
8831 : |----------------|
8832 : | Param 1 |
8833 : |----------------|
8834 : | Param 2 |
8835 : |----------------|
8836 : . .
8837 : . .
8838 : . .
8839 : |----------------|
8840 : | Param # |
8841 : |----------------|
8842 : | ProcSym | Type |
8843 : |----------------|
8844 :
8845 : */
8846 :
8847 66875 : static void ManipulatePseudoCallParameters (void)
8848 : {
8849 66875 : unsigned int NoOfParameters;
8850 66875 : unsigned int ProcSym;
8851 66875 : unsigned int Proc;
8852 66875 : unsigned int i;
8853 66875 : unsigned int pi;
8854 66875 : M2Quads_BoolFrame f;
8855 :
8856 66875 : M2Quads_PopT (&NoOfParameters);
8857 66875 : M2Quads_PushT (NoOfParameters); /* restored to original state */
8858 : /* Ptr points to the ProcSym */
8859 66875 : ProcSym = static_cast<unsigned int> (M2Quads_OperandT ((NoOfParameters+1)+1));
8860 66875 : if (SymbolTable_IsVar (ProcSym))
8861 : {
8862 0 : M2Error_InternalError ((const char *) "expecting a pseudo procedure or a type", 38);
8863 : }
8864 : else
8865 : {
8866 66875 : Proc = ProcSym;
8867 : }
8868 66875 : i = 1;
8869 66875 : pi = NoOfParameters+1;
8870 146506 : while (i <= NoOfParameters)
8871 : {
8872 79631 : if (((((((SymbolTable_GetMode (M2Quads_OperandT (pi))) == SymbolTable_LeftValue) && (Proc != M2System_Adr)) && (Proc != M2Size_Size)) && (Proc != M2System_TSize)) && (Proc != M2Base_High)) && (((((((Proc != M2Base_Inc) && (Proc != M2Base_Incl)) && (Proc != M2Base_Dec)) && (Proc != M2Base_Excl)) && (Proc != M2Base_New)) && (Proc != M2Base_Dispose)) || (i > 1)))
8873 : {
8874 : /* must dereference LeftValue */
8875 1344 : f = static_cast<M2Quads_BoolFrame> (M2StackAddress_PeepAddress (BoolStack, pi));
8876 1344 : f->TrueExit = MakeRightValue (M2LexBuf_GetTokenNo (), M2Quads_OperandT (pi), SymbolTable_GetSType (M2Quads_OperandT (pi)));
8877 : }
8878 79631 : i += 1;
8879 79631 : pi -= 1;
8880 : }
8881 66875 : }
8882 :
8883 :
8884 : /*
8885 : ManipulateParameters - manipulates the procedure parameters in
8886 : preparation for a procedure call.
8887 : Prepares Boolean, Unbounded and VAR parameters.
8888 : The Stack:
8889 :
8890 :
8891 : Entry Exit
8892 :
8893 : Ptr -> exactly the same
8894 : +----------------+
8895 : | NoOfParameters |
8896 : |----------------|
8897 : | Param 1 |
8898 : |----------------|
8899 : | Param 2 |
8900 : |----------------|
8901 : . .
8902 : . .
8903 : . .
8904 : |----------------|
8905 : | Param # |
8906 : |----------------|
8907 : | ProcSym | Type |
8908 : |----------------|
8909 : */
8910 :
8911 220622 : static void ManipulateParameters (bool IsForC)
8912 : {
8913 220622 : unsigned int tokpos;
8914 220622 : unsigned int np;
8915 220622 : DynamicStrings_String s;
8916 220622 : unsigned int ArraySym;
8917 220622 : unsigned int UnboundedType;
8918 220622 : unsigned int ParamType;
8919 220622 : unsigned int NoOfParameters;
8920 220622 : unsigned int i;
8921 220622 : unsigned int pi;
8922 220622 : unsigned int ProcSym;
8923 220622 : unsigned int rw;
8924 220622 : unsigned int Proc;
8925 220622 : unsigned int t;
8926 220622 : M2Quads_BoolFrame f;
8927 :
8928 220622 : M2Quads_PopT (&NoOfParameters);
8929 220622 : ProcSym = static_cast<unsigned int> (M2Quads_OperandT (NoOfParameters+1));
8930 220622 : tokpos = OperandTtok (NoOfParameters+1);
8931 220622 : if (SymbolTable_IsVar (ProcSym))
8932 : {
8933 : /* Procedure Variable ? */
8934 772 : Proc = SymbolTable_SkipType (M2Quads_OperandF (NoOfParameters+1));
8935 : }
8936 : else
8937 : {
8938 219850 : Proc = PCSymBuild_SkipConst (ProcSym);
8939 : }
8940 220622 : if (IsForC && (SymbolTable_UsesVarArgs (Proc)))
8941 : {
8942 : /* avoid dangling else. */
8943 9761 : if (NoOfParameters < (SymbolTable_NoOfParamAny (Proc)))
8944 : {
8945 0 : s = DynamicStrings_Mark (DynamicStrings_InitStringCharStar (NameKey_KeyToCharStar (SymbolTable_GetSymName (Proc))));
8946 0 : np = SymbolTable_NoOfParamAny (Proc);
8947 0 : M2Error_ErrorStringAt2 (FormatStrings_Sprintf3 (DynamicStrings_Mark (DynamicStrings_InitString ((const char *) "attempting to pass (%d) parameters to procedure (%s) which was declared with varargs but contains at least (%d) parameters", 122)), (const unsigned char *) &NoOfParameters, (sizeof (NoOfParameters)-1), (const unsigned char *) &s, (sizeof (s)-1), (const unsigned char *) &np, (sizeof (np)-1)), tokpos, SymbolTable_GetDeclaredMod (ProcSym));
8948 : }
8949 : }
8950 210861 : else if (SymbolTable_UsesOptArgAny (Proc))
8951 : {
8952 : /* avoid dangling else. */
8953 3806 : if (! ((NoOfParameters == (SymbolTable_NoOfParamAny (Proc))) || ((NoOfParameters+1) == (SymbolTable_NoOfParamAny (Proc)))))
8954 : {
8955 0 : s = DynamicStrings_Mark (DynamicStrings_InitStringCharStar (NameKey_KeyToCharStar (SymbolTable_GetSymName (Proc))));
8956 0 : np = SymbolTable_NoOfParamAny (Proc);
8957 0 : M2Error_ErrorStringAt2 (FormatStrings_Sprintf3 (DynamicStrings_Mark (DynamicStrings_InitString ((const char *) "attempting to pass (%d) parameters to procedure (%s) which was declared with an optarg with a maximum of (%d) parameters", 120)), (const unsigned char *) &NoOfParameters, (sizeof (NoOfParameters)-1), (const unsigned char *) &s, (sizeof (s)-1), (const unsigned char *) &np, (sizeof (np)-1)), tokpos, SymbolTable_GetDeclaredMod (ProcSym));
8958 : }
8959 : }
8960 207055 : else if (NoOfParameters != (SymbolTable_NoOfParamAny (Proc)))
8961 : {
8962 : /* avoid dangling else. */
8963 0 : s = DynamicStrings_Mark (DynamicStrings_InitStringCharStar (NameKey_KeyToCharStar (SymbolTable_GetSymName (Proc))));
8964 0 : np = SymbolTable_NoOfParamAny (Proc);
8965 0 : M2Error_ErrorStringAt2 (FormatStrings_Sprintf3 (DynamicStrings_Mark (DynamicStrings_InitString ((const char *) "attempting to pass (%d) parameters to procedure (%s) which was declared with (%d) parameters", 92)), (const unsigned char *) &NoOfParameters, (sizeof (NoOfParameters)-1), (const unsigned char *) &s, (sizeof (s)-1), (const unsigned char *) &np, (sizeof (np)-1)), tokpos, SymbolTable_GetDeclaredMod (ProcSym));
8966 : }
8967 220622 : i = 1;
8968 220622 : pi = NoOfParameters;
8969 768233 : while (i <= NoOfParameters)
8970 : {
8971 547611 : f = static_cast<M2Quads_BoolFrame> (M2StackAddress_PeepAddress (BoolStack, pi));
8972 547611 : rw = static_cast<unsigned int> (OperandMergeRW (pi));
8973 547611 : M2Debug_Assert (SymbolTable_IsLegal (rw));
8974 547611 : if (i > (SymbolTable_NoOfParamAny (Proc)))
8975 : {
8976 8388 : if (IsForC && (SymbolTable_UsesVarArgs (Proc)))
8977 : {
8978 : /* avoid dangling else. */
8979 8388 : if (((SymbolTable_GetSType (M2Quads_OperandT (pi))) != SymbolTable_NulSym) && (SymbolTable_IsArray (SymbolTable_GetDType (M2Quads_OperandT (pi)))))
8980 : {
8981 156 : f->TrueExit = MakeLeftValue (M2Quads_OperandTok (pi), M2Quads_OperandT (pi), SymbolTable_RightValue, M2System_Address);
8982 156 : MarkAsReadWrite (rw);
8983 : }
8984 8232 : else if (SymbolTable_IsConstString (M2Quads_OperandT (pi)))
8985 : {
8986 : /* avoid dangling else. */
8987 284 : f->TrueExit = MakeLeftValue (M2Quads_OperandTok (pi), DeferMakeConstStringCnul (M2Quads_OperandTok (pi), M2Quads_OperandT (pi)), SymbolTable_RightValue, M2System_Address);
8988 284 : MarkAsReadWrite (rw);
8989 : }
8990 7948 : else if (((SymbolTable_GetSType (M2Quads_OperandT (pi))) != SymbolTable_NulSym) && (SymbolTable_IsUnbounded (SymbolTable_GetSType (M2Quads_OperandT (pi)))))
8991 : {
8992 : /* avoid dangling else. */
8993 200 : MarkAsReadWrite (rw);
8994 : /* pass the address field of an unbounded variable */
8995 200 : M2Quads_PushTFtok (M2System_Adr, M2System_Address, M2Quads_OperandTok (pi));
8996 200 : PushTFAD (f->TrueExit, f->FalseExit, f->Unbounded, f->Dimension);
8997 200 : M2Quads_PushT (static_cast<unsigned int> (1));
8998 200 : BuildAdrFunction ();
8999 200 : M2Quads_PopT (&f->TrueExit);
9000 : }
9001 7748 : else if ((SymbolTable_GetMode (M2Quads_OperandT (pi))) == SymbolTable_LeftValue)
9002 : {
9003 : /* avoid dangling else. */
9004 464 : MarkAsReadWrite (rw);
9005 : /* must dereference LeftValue (even if we are passing variable as a vararg) */
9006 464 : t = SymbolTable_MakeTemporary (M2Quads_OperandTok (pi), SymbolTable_RightValue);
9007 464 : SymbolTable_PutVar (t, SymbolTable_GetSType (M2Quads_OperandT (pi)));
9008 464 : CheckPointerThroughNil (tokpos, M2Quads_OperandT (pi));
9009 464 : doIndrX (M2Quads_OperandTok (pi), t, M2Quads_OperandT (pi));
9010 464 : f->TrueExit = t;
9011 : }
9012 : }
9013 : else
9014 : {
9015 0 : M2MetaError_MetaErrorT2 (tokpos, (const char *) "attempting to pass too many parameters to procedure {%1a}, the {%2N} parameter does not exist", 93, Proc, i);
9016 : }
9017 : }
9018 539223 : else if (((IsForC && (SymbolTable_IsUnboundedParamAny (Proc, i))) && ((SymbolTable_GetSType (M2Quads_OperandT (pi))) != SymbolTable_NulSym)) && (SymbolTable_IsArray (SymbolTable_GetDType (M2Quads_OperandT (pi)))))
9019 : {
9020 : /* avoid dangling else. */
9021 24 : f->TrueExit = MakeLeftValue (M2Quads_OperandTok (pi), M2Quads_OperandT (pi), SymbolTable_RightValue, M2System_Address);
9022 24 : MarkAsReadWrite (rw);
9023 : }
9024 539199 : else if (((IsForC && (SymbolTable_IsUnboundedParamAny (Proc, i))) && ((SymbolTable_GetSType (M2Quads_OperandT (pi))) != SymbolTable_NulSym)) && (SymbolTable_IsUnbounded (SymbolTable_GetDType (M2Quads_OperandT (pi)))))
9025 : {
9026 : /* avoid dangling else. */
9027 184 : MarkAsReadWrite (rw);
9028 : /* pass the address field of an unbounded variable */
9029 184 : M2Quads_PushTFtok (M2System_Adr, M2System_Address, M2Quads_OperandTok (pi));
9030 184 : PushTFAD (f->TrueExit, f->FalseExit, f->Unbounded, f->Dimension);
9031 184 : M2Quads_PushT (static_cast<unsigned int> (1));
9032 184 : BuildAdrFunction ();
9033 184 : M2Quads_PopT (&f->TrueExit);
9034 : }
9035 539015 : else if ((IsForC && (SymbolTable_IsConstString (M2Quads_OperandT (pi)))) && ((SymbolTable_IsUnboundedParamAny (Proc, i)) || ((SymbolTable_GetDType (SymbolTable_GetParam (Proc, i))) == M2System_Address)))
9036 : {
9037 : /* avoid dangling else. */
9038 9449 : f->TrueExit = MakeLeftValue (M2Quads_OperandTok (pi), DeferMakeConstStringCnul (M2Quads_OperandTok (pi), M2Quads_OperandT (pi)), SymbolTable_RightValue, M2System_Address);
9039 9449 : MarkAsReadWrite (rw);
9040 : }
9041 529566 : else if (SymbolTable_IsUnboundedParamAny (Proc, i))
9042 : {
9043 : /* avoid dangling else. */
9044 : /* always pass constant strings with a nul terminator, but leave the HIGH as before. */
9045 40821 : if (SymbolTable_IsConstString (M2Quads_OperandT (pi)))
9046 : {
9047 : /* this is a Modula-2 string which must be nul terminated. */
9048 26723 : f->TrueExit = DeferMakeConstStringM2nul (M2Quads_OperandTok (pi), M2Quads_OperandT (pi));
9049 : }
9050 40821 : t = SymbolTable_MakeTemporary (M2Quads_OperandTok (pi), SymbolTable_RightValue);
9051 40821 : UnboundedType = SymbolTable_GetSType (SymbolTable_GetParam (Proc, i));
9052 40821 : SymbolTable_PutVar (t, UnboundedType);
9053 40821 : ParamType = SymbolTable_GetSType (UnboundedType);
9054 40821 : if ((OperandD (pi)) == 0)
9055 : {
9056 40773 : ArraySym = static_cast<unsigned int> (M2Quads_OperandT (pi));
9057 : }
9058 : else
9059 : {
9060 48 : ArraySym = static_cast<unsigned int> (M2Quads_OperandA (pi));
9061 : }
9062 40821 : if (SymbolTable_IsVarParamAny (Proc, i))
9063 : {
9064 4450 : MarkArrayWritten (M2Quads_OperandT (pi));
9065 4450 : MarkArrayWritten (M2Quads_OperandA (pi));
9066 4450 : MarkAsReadWrite (rw);
9067 4450 : AssignUnboundedVar (OperandTtok (pi), M2Quads_OperandT (pi), ArraySym, t, ParamType, OperandD (pi));
9068 : }
9069 : else
9070 : {
9071 36371 : MarkAsRead (rw);
9072 36371 : AssignUnboundedNonVar (OperandTtok (pi), M2Quads_OperandT (pi), ArraySym, t, ParamType, OperandD (pi));
9073 : }
9074 40821 : f->TrueExit = t;
9075 : }
9076 488745 : else if (SymbolTable_IsVarParamAny (Proc, i))
9077 : {
9078 : /* avoid dangling else. */
9079 : /* must reference by address, but we contain the type of the referenced entity */
9080 16036 : MarkArrayWritten (M2Quads_OperandT (pi));
9081 16036 : MarkArrayWritten (M2Quads_OperandA (pi));
9082 16036 : MarkAsReadWrite (rw);
9083 16036 : f->TrueExit = MakeLeftValue (M2Quads_OperandTok (pi), M2Quads_OperandT (pi), SymbolTable_LeftValue, SymbolTable_GetSType (SymbolTable_GetParam (Proc, i)));
9084 : }
9085 472709 : else if ((! (SymbolTable_IsVarParamAny (Proc, i))) && ((SymbolTable_GetMode (M2Quads_OperandT (pi))) == SymbolTable_LeftValue))
9086 : {
9087 : /* avoid dangling else. */
9088 : /* must dereference LeftValue */
9089 1514 : t = SymbolTable_MakeTemporary (M2Quads_OperandTok (pi), SymbolTable_RightValue);
9090 1514 : SymbolTable_PutVar (t, SymbolTable_GetSType (M2Quads_OperandT (pi)));
9091 1514 : CheckPointerThroughNil (tokpos, M2Quads_OperandT (pi));
9092 1514 : doIndrX (M2Quads_OperandTok (pi), t, M2Quads_OperandT (pi));
9093 1514 : f->TrueExit = t;
9094 1514 : MarkAsRead (rw);
9095 : }
9096 : else
9097 : {
9098 : /* avoid dangling else. */
9099 471195 : MarkAsRead (rw);
9100 : }
9101 547611 : i += 1;
9102 547611 : pi -= 1;
9103 : }
9104 220622 : M2Quads_PushT (NoOfParameters);
9105 220622 : }
9106 :
9107 :
9108 : /*
9109 : CheckParameterOrdinals - check that ordinal values are within type range.
9110 : */
9111 :
9112 220622 : static void CheckParameterOrdinals (void)
9113 : {
9114 220622 : unsigned int tokno;
9115 220622 : unsigned int Proc;
9116 220622 : unsigned int ProcSym;
9117 220622 : unsigned int Actual;
9118 220622 : unsigned int FormalI;
9119 220622 : unsigned int ParamTotal;
9120 220622 : unsigned int pi;
9121 220622 : unsigned int i;
9122 :
9123 220622 : M2Quads_PopT (&ParamTotal);
9124 220622 : M2Quads_PushT (ParamTotal); /* Restore stack to origional state */
9125 220622 : ProcSym = static_cast<unsigned int> (M2Quads_OperandT ((ParamTotal+1)+1)); /* Restore stack to origional state */
9126 220622 : if ((SymbolTable_IsVar (ProcSym)) && (SymbolTable_IsProcType (SymbolTable_GetDType (ProcSym))))
9127 : {
9128 : /* Indirect procedure call. */
9129 772 : Proc = SymbolTable_SkipType (M2Quads_OperandF ((ParamTotal+1)+1));
9130 : }
9131 : else
9132 : {
9133 219850 : Proc = PCSymBuild_SkipConst (ProcSym);
9134 : }
9135 220622 : i = 1;
9136 220622 : pi = ParamTotal+1; /* stack index referencing stacked parameter, i */
9137 768233 : while (i <= ParamTotal) /* stack index referencing stacked parameter, i */
9138 : {
9139 547611 : if (i <= (SymbolTable_NoOfParamAny (Proc)))
9140 : {
9141 539223 : FormalI = SymbolTable_GetParam (Proc, i);
9142 539223 : Actual = static_cast<unsigned int> (M2Quads_OperandT (pi));
9143 539223 : tokno = static_cast<unsigned int> (M2Quads_OperandTok (pi));
9144 539223 : if (M2Base_IsOrdinalType (SymbolTable_GetLType (FormalI)))
9145 : {
9146 142599 : if (! (SymbolTable_IsSet (SymbolTable_GetDType (FormalI))))
9147 : {
9148 : /* Tell the code generator to test the runtime values of the assignment
9149 : so ensure we catch overflow and underflow. */
9150 142599 : BuildRange (M2Range_InitParameterRangeCheck (tokno, Proc, i, FormalI, Actual, OperandRangeDep (pi)));
9151 : }
9152 : }
9153 : }
9154 547611 : i += 1;
9155 547611 : pi -= 1;
9156 : }
9157 220622 : }
9158 :
9159 :
9160 : /*
9161 : IsSameUnbounded - returns TRUE if unbounded types, t1, and, t2,
9162 : are compatible.
9163 : */
9164 :
9165 36 : static bool IsSameUnbounded (unsigned int t1, unsigned int t2)
9166 : {
9167 36 : M2Debug_Assert (SymbolTable_IsUnbounded (t1));
9168 36 : M2Debug_Assert (SymbolTable_IsUnbounded (t2));
9169 36 : return (SymbolTable_GetDType (t1)) == (SymbolTable_GetDType (t2));
9170 : /* static analysis guarentees a RETURN statement will be used before here. */
9171 : __builtin_unreachable ();
9172 : }
9173 :
9174 :
9175 : /*
9176 : AssignUnboundedVar - assigns an Unbounded symbol fields,
9177 : ArrayAddress and ArrayHigh, from an array symbol.
9178 : UnboundedSym is not a VAR parameter and therefore
9179 : this procedure can complete both of the fields.
9180 : Sym can be a Variable with type Unbounded.
9181 : Sym can be a Variable with type Array.
9182 : Sym can be a String Constant.
9183 :
9184 : ParamType is the TYPE of the parameter
9185 : */
9186 :
9187 4450 : static void AssignUnboundedVar (unsigned int tok, unsigned int Sym, unsigned int ArraySym, unsigned int UnboundedSym, unsigned int ParamType, unsigned int dim)
9188 : {
9189 4450 : unsigned int Type;
9190 :
9191 4450 : if (SymbolTable_IsConst (Sym))
9192 : {
9193 0 : M2MetaError_MetaErrorT1 (tok, (const char *) "{%1ad} cannot be passed to a VAR formal parameter", 49, Sym);
9194 : }
9195 4450 : else if (SymbolTable_IsVar (Sym))
9196 : {
9197 : /* avoid dangling else. */
9198 4450 : Type = SymbolTable_GetDType (Sym);
9199 4450 : if (Type == SymbolTable_NulSym)
9200 : {
9201 0 : M2MetaError_MetaErrorT1 (tok, (const char *) "{%1ad} has no type and cannot be passed to a VAR formal parameter", 65, Sym);
9202 : }
9203 4450 : else if (SymbolTable_IsUnbounded (Type))
9204 : {
9205 : /* avoid dangling else. */
9206 1462 : if (Type == (SymbolTable_GetSType (UnboundedSym)))
9207 : {
9208 : /* Copy Unbounded Symbol ie. UnboundedSym := Sym */
9209 1426 : M2Quads_PushT (UnboundedSym);
9210 1426 : M2Quads_PushT (Sym);
9211 1426 : BuildAssignmentWithoutBounds (tok, false, true);
9212 : }
9213 36 : else if ((IsSameUnbounded (Type, SymbolTable_GetSType (UnboundedSym))) || (M2System_IsGenericSystemType (ParamType)))
9214 : {
9215 : /* avoid dangling else. */
9216 36 : UnboundedVarLinkToArray (tok, Sym, ArraySym, UnboundedSym, ParamType, dim);
9217 : }
9218 : else
9219 : {
9220 : /* avoid dangling else. */
9221 0 : M2MetaError_MetaErrorT1 (tok, (const char *) "{%1ad} cannot be passed to a VAR formal parameter", 49, Sym);
9222 : }
9223 : }
9224 2988 : else if ((SymbolTable_IsArray (Type)) || (M2System_IsGenericSystemType (ParamType)))
9225 : {
9226 : /* avoid dangling else. */
9227 2988 : UnboundedVarLinkToArray (tok, Sym, ArraySym, UnboundedSym, ParamType, dim);
9228 : }
9229 : else
9230 : {
9231 : /* avoid dangling else. */
9232 0 : M2MetaError_MetaErrorT1 (tok, (const char *) "{%1ad} cannot be passed to a VAR formal parameter", 49, Sym);
9233 : }
9234 : }
9235 : else
9236 : {
9237 : /* avoid dangling else. */
9238 0 : M2MetaError_MetaErrorT1 (tok, (const char *) "{%1ad} cannot be passed to a VAR formal parameter", 49, Sym);
9239 : }
9240 4450 : }
9241 :
9242 :
9243 : /*
9244 : AssignUnboundedNonVar - assigns an Unbounded symbol fields,
9245 : The difference between this procedure and
9246 : AssignUnboundedVar is that this procedure cannot
9247 : set the Unbounded.Address since the data from
9248 : Sym will be copied because parameter is NOT a VAR
9249 : parameter.
9250 : UnboundedSym is not a VAR parameter and therefore
9251 : this procedure can only complete the HIGH field
9252 : and not the ADDRESS field.
9253 : Sym can be a Variable with type Unbounded.
9254 : Sym can be a Variable with type Array.
9255 : Sym can be a String Constant.
9256 :
9257 : ParamType is the TYPE of the paramater
9258 : */
9259 :
9260 36371 : static void AssignUnboundedNonVar (unsigned int tok, unsigned int Sym, unsigned int ArraySym, unsigned int UnboundedSym, unsigned int ParamType, unsigned int dim)
9261 : {
9262 36371 : unsigned int Type;
9263 :
9264 36371 : if (SymbolTable_IsConst (Sym)) /* was IsConstString(Sym) */
9265 : {
9266 26777 : UnboundedNonVarLinkToArray (tok, Sym, ArraySym, UnboundedSym, ParamType, dim);
9267 : }
9268 9594 : else if (SymbolTable_IsVar (Sym))
9269 : {
9270 : /* avoid dangling else. */
9271 9594 : Type = SymbolTable_GetDType (Sym);
9272 9594 : if (Type == SymbolTable_NulSym)
9273 : {
9274 0 : M2MetaError_MetaErrorT1 (tok, (const char *) "{%1ad} has no type and cannot be passed to a non VAR formal parameter", 69, Sym);
9275 : }
9276 9594 : else if (SymbolTable_IsUnbounded (Type))
9277 : {
9278 : /* avoid dangling else. */
9279 4800 : UnboundedNonVarLinkToArray (tok, Sym, ArraySym, UnboundedSym, ParamType, dim);
9280 : }
9281 4794 : else if ((SymbolTable_IsArray (Type)) || (M2System_IsGenericSystemType (ParamType)))
9282 : {
9283 : /* avoid dangling else. */
9284 4782 : UnboundedNonVarLinkToArray (tok, Sym, ArraySym, UnboundedSym, ParamType, dim);
9285 : }
9286 : else
9287 : {
9288 : /* avoid dangling else. */
9289 12 : M2MetaError_MetaErrorT1 (tok, (const char *) "illegal type parameter {%1Ead} expecting array or dynamic array", 63, Sym);
9290 : }
9291 : }
9292 : else
9293 : {
9294 : /* avoid dangling else. */
9295 0 : M2MetaError_MetaErrorT1 (tok, (const char *) "illegal parameter {%1Ead} which cannot be passed as {%kVAR} {%kARRAY} {%kOF} {%1tsad}", 85, Sym);
9296 : }
9297 36371 : }
9298 :
9299 :
9300 : /*
9301 : GenHigh - generates a HighOp but it checks if op3 is a
9302 : L value and if so it dereferences it. This
9303 : is inefficient, however it is clean and we let the gcc
9304 : backend detect these as common subexpressions.
9305 : It will also detect that a R value -> L value -> R value
9306 : via indirection and eleminate these.
9307 : */
9308 :
9309 42265 : static void GenHigh (unsigned int tok, unsigned int op1, unsigned int op2, unsigned int op3)
9310 : {
9311 42265 : unsigned int sym;
9312 :
9313 42265 : if (((SymbolTable_GetMode (op3)) == SymbolTable_LeftValue) && (SymbolTable_IsUnbounded (SymbolTable_GetSType (op3))))
9314 : {
9315 48 : sym = SymbolTable_MakeTemporary (tok, SymbolTable_RightValue);
9316 48 : SymbolTable_PutVar (sym, SymbolTable_GetSType (op3));
9317 48 : doIndrX (tok, sym, op3);
9318 48 : GenQuadO (tok, M2Quads_HighOp, op1, op2, sym, true);
9319 : }
9320 : else
9321 : {
9322 42217 : GenQuadO (tok, M2Quads_HighOp, op1, op2, op3, true);
9323 : }
9324 42265 : }
9325 :
9326 :
9327 : /*
9328 : AssignHighField -
9329 : */
9330 :
9331 39539 : static void AssignHighField (unsigned int tok, unsigned int Sym, unsigned int ArraySym, unsigned int UnboundedSym, unsigned int ParamType, unsigned int actuali, unsigned int formali)
9332 : {
9333 39539 : unsigned int ReturnVar;
9334 39539 : unsigned int ArrayType;
9335 39539 : unsigned int Field;
9336 :
9337 : /* Unbounded.ArrayHigh := HIGH(ArraySym) */
9338 39539 : M2Quads_PushTFtok (UnboundedSym, SymbolTable_GetSType (UnboundedSym), tok);
9339 39539 : Field = SymbolTable_GetUnboundedHighOffset (SymbolTable_GetSType (UnboundedSym), formali);
9340 39539 : M2Quads_PushTFtok (Field, SymbolTable_GetSType (Field), tok);
9341 39539 : M2Quads_PushT (static_cast<unsigned int> (1));
9342 39539 : M2Quads_BuildDesignatorRecord (tok);
9343 39539 : if (M2System_IsGenericSystemType (ParamType))
9344 : {
9345 2036 : if (SymbolTable_IsConstString (Sym))
9346 : {
9347 18 : M2Quads_PushTtok (DeferMakeLengthConst (tok, Sym), tok);
9348 : }
9349 : else
9350 : {
9351 2018 : ArrayType = SymbolTable_GetSType (Sym);
9352 2018 : if (SymbolTable_IsUnbounded (ArrayType))
9353 : {
9354 : /*
9355 : * SIZE(parameter) DIV TSIZE(ParamType)
9356 : * however in this case parameter
9357 : * is an unbounded symbol and therefore we must use
9358 : * (HIGH(parameter)+1)*SIZE(unbounded type) DIV TSIZE(ParamType)
9359 : *
9360 : * we call upon the function SIZE(ArraySym)
9361 : * remember SIZE doubles as
9362 : * (HIGH(a)+1) * SIZE(ArrayType) for unbounded symbols
9363 : */
9364 1106 : M2Quads_PushTFtok (calculateMultipicand (tok, ArraySym, ArrayType, actuali-1), M2Base_Cardinal, tok);
9365 1106 : M2Quads_PushT (M2Reserved_DivideTok); /* Divide by */
9366 1106 : M2Quads_PushTFtok (M2System_TSize, M2Base_Cardinal, tok); /* TSIZE(ParamType) */
9367 1106 : M2Quads_PushTtok (ParamType, tok); /* TSIZE(ParamType) */
9368 1106 : M2Quads_PushT (static_cast<unsigned int> (1)); /* 1 parameter for TSIZE() */
9369 1106 : M2Quads_BuildFunctionCall (false); /* 1 parameter for TSIZE() */
9370 1106 : M2Quads_BuildBinaryOp ();
9371 : }
9372 : else
9373 : {
9374 : /* SIZE(parameter) DIV TSIZE(ParamType) */
9375 912 : M2Quads_PushTFtok (M2System_TSize, M2Base_Cardinal, tok); /* TSIZE(ArrayType) */
9376 912 : M2Quads_PushTtok (ArrayType, tok); /* TSIZE(ArrayType) */
9377 912 : M2Quads_PushT (static_cast<unsigned int> (1)); /* 1 parameter for TSIZE() */
9378 912 : M2Quads_BuildFunctionCall (true); /* 1 parameter for TSIZE() */
9379 912 : M2Quads_PushT (M2Reserved_DivideTok); /* Divide by */
9380 912 : M2Quads_PushTFtok (M2System_TSize, M2Base_Cardinal, tok); /* TSIZE(ParamType) */
9381 912 : M2Quads_PushTtok (ParamType, tok); /* TSIZE(ParamType) */
9382 912 : M2Quads_PushT (static_cast<unsigned int> (1)); /* 1 parameter for TSIZE() */
9383 912 : M2Quads_BuildFunctionCall (true); /* 1 parameter for TSIZE() */
9384 912 : M2Quads_BuildBinaryOp ();
9385 : }
9386 : /* now convert from no of elements into HIGH by subtracting 1 */
9387 2018 : M2Quads_PushT (M2Reserved_MinusTok); /* -1 */
9388 2018 : M2Quads_PushTtok (SymbolTable_MakeConstLit (tok, NameKey_MakeKey ((const char *) "1", 1), M2Base_Cardinal), tok); /* -1 */
9389 2018 : M2Quads_BuildBinaryOp ();
9390 : }
9391 : }
9392 : else
9393 : {
9394 37503 : ReturnVar = SymbolTable_MakeTemporary (tok, SymbolTable_RightValue);
9395 37503 : SymbolTable_PutVar (ReturnVar, M2Base_Cardinal);
9396 37503 : if (((actuali != formali) && (ArraySym != SymbolTable_NulSym)) && (SymbolTable_IsUnbounded (SymbolTable_GetSType (ArraySym))))
9397 : {
9398 12 : GenHigh (tok, ReturnVar, actuali, ArraySym);
9399 : }
9400 : else
9401 : {
9402 37491 : GenHigh (tok, ReturnVar, formali, Sym);
9403 : }
9404 37503 : M2Quads_PushTFtok (ReturnVar, SymbolTable_GetSType (ReturnVar), tok);
9405 : }
9406 39539 : BuildAssignmentWithoutBounds (tok, false, true);
9407 39539 : }
9408 :
9409 :
9410 : /*
9411 : AssignHighFields -
9412 : */
9413 :
9414 39383 : static void AssignHighFields (unsigned int tok, unsigned int Sym, unsigned int ArraySym, unsigned int UnboundedSym, unsigned int ParamType, unsigned int dim)
9415 : {
9416 39383 : unsigned int type;
9417 39383 : unsigned int actuali;
9418 39383 : unsigned int formali;
9419 39383 : unsigned int actualn;
9420 39383 : unsigned int formaln;
9421 :
9422 39383 : type = SymbolTable_GetDType (Sym);
9423 39383 : actualn = 1;
9424 39383 : if ((type != SymbolTable_NulSym) && ((SymbolTable_IsUnbounded (type)) || (SymbolTable_IsArray (type))))
9425 : {
9426 11724 : actualn = SymbolTable_GetDimension (type);
9427 : }
9428 39383 : actuali = dim+1;
9429 39383 : formali = 1;
9430 39383 : formaln = SymbolTable_GetDimension (SymbolTable_GetDType (UnboundedSym));
9431 78922 : while ((actuali < actualn) && (formali < formaln))
9432 : {
9433 156 : AssignHighField (tok, Sym, ArraySym, UnboundedSym, SymbolTable_NulSym, actuali, formali);
9434 156 : actuali += 1;
9435 156 : formali += 1;
9436 : }
9437 39383 : AssignHighField (tok, Sym, ArraySym, UnboundedSym, ParamType, actuali, formali);
9438 39383 : }
9439 :
9440 :
9441 : /*
9442 : UnboundedNonVarLinkToArray - links an array, ArraySym, to an unbounded
9443 : array, UnboundedSym. The parameter is a
9444 : NON VAR variety.
9445 : */
9446 :
9447 36359 : static void UnboundedNonVarLinkToArray (unsigned int tok, unsigned int Sym, unsigned int ArraySym, unsigned int UnboundedSym, unsigned int ParamType, unsigned int dim)
9448 : {
9449 36359 : unsigned int Field;
9450 36359 : unsigned int AddressField;
9451 :
9452 : /* Unbounded.ArrayAddress := to be assigned at runtime. */
9453 36359 : M2Quads_PushTFtok (UnboundedSym, SymbolTable_GetSType (UnboundedSym), tok);
9454 36359 : Field = SymbolTable_GetUnboundedAddressOffset (SymbolTable_GetSType (UnboundedSym));
9455 36359 : M2Quads_PushTFtok (Field, SymbolTable_GetSType (Field), tok);
9456 36359 : M2Quads_PushT (static_cast<unsigned int> (1));
9457 36359 : M2Quads_BuildDesignatorRecord (tok);
9458 36359 : M2Quads_PopT (&AddressField);
9459 : /* caller saves non var unbounded array contents. */
9460 72718 : GenQuadO (tok, M2Quads_UnboundedOp, AddressField, SymbolTable_NulSym, Sym, false);
9461 36359 : AssignHighFields (tok, Sym, ArraySym, UnboundedSym, ParamType, dim);
9462 36359 : }
9463 :
9464 :
9465 : /*
9466 : UnboundedVarLinkToArray - links an array, ArraySym, to an unbounded array,
9467 : UnboundedSym. The parameter is a VAR variety.
9468 : */
9469 :
9470 3024 : static void UnboundedVarLinkToArray (unsigned int tok, unsigned int Sym, unsigned int ArraySym, unsigned int UnboundedSym, unsigned int ParamType, unsigned int dim)
9471 : {
9472 3024 : unsigned int SymType;
9473 3024 : unsigned int Field;
9474 :
9475 3024 : SymType = SymbolTable_GetSType (Sym);
9476 : /* Unbounded.ArrayAddress := ADR(Sym) */
9477 3024 : M2Quads_PushTFtok (UnboundedSym, SymbolTable_GetSType (UnboundedSym), tok);
9478 3024 : Field = SymbolTable_GetUnboundedAddressOffset (SymbolTable_GetSType (UnboundedSym));
9479 3024 : M2Quads_PushTFtok (Field, SymbolTable_GetSType (Field), tok);
9480 3024 : M2Quads_PushT (static_cast<unsigned int> (1));
9481 3024 : M2Quads_BuildDesignatorRecord (tok);
9482 3024 : M2Quads_PushTFtok (M2System_Adr, M2System_Address, tok); /* ADR (Sym). */
9483 3024 : if ((SymbolTable_IsUnbounded (SymType)) && (dim == 0)) /* ADR (Sym). */
9484 : {
9485 12 : PushTFADtok (Sym, SymType, UnboundedSym, dim, tok);
9486 : }
9487 : else
9488 : {
9489 3012 : PushTFADtok (Sym, SymType, ArraySym, dim, tok);
9490 : }
9491 3024 : M2Quads_PushT (static_cast<unsigned int> (1)); /* 1 parameter for ADR(). */
9492 3024 : M2Quads_BuildFunctionCall (false); /* 1 parameter for ADR(). */
9493 3024 : BuildAssignmentWithoutBounds (tok, false, true);
9494 3024 : AssignHighFields (tok, Sym, ArraySym, UnboundedSym, ParamType, dim);
9495 3024 : }
9496 :
9497 :
9498 : /*
9499 : BuildPseudoProcedureCall - builds a pseudo procedure call.
9500 : This procedure does not directly alter the
9501 : stack, but by calling routines the stack
9502 : will change in the following way when this
9503 : procedure returns.
9504 :
9505 : The Stack:
9506 :
9507 :
9508 : Entry Exit
9509 :
9510 : Ptr ->
9511 : +----------------+
9512 : | NoOfParam |
9513 : |----------------|
9514 : | Param 1 |
9515 : |----------------|
9516 : | Param 2 |
9517 : |----------------|
9518 : . .
9519 : . .
9520 : . .
9521 : |----------------|
9522 : | Param # |
9523 : |----------------|
9524 : | ProcSym | Type | Empty
9525 : |----------------|
9526 : */
9527 :
9528 21535 : static void BuildPseudoProcedureCall (unsigned int tokno)
9529 : {
9530 21535 : unsigned int NoOfParam;
9531 21535 : unsigned int ProcSym;
9532 :
9533 21535 : M2Quads_PopT (&NoOfParam);
9534 21535 : ProcSym = static_cast<unsigned int> (M2Quads_OperandT (NoOfParam+1));
9535 21535 : M2Quads_PushT (NoOfParam);
9536 : /* Compile time stack restored to entry state */
9537 21535 : if (ProcSym == M2Base_New)
9538 : {
9539 873 : BuildNewProcedure (tokno);
9540 : }
9541 20662 : else if (ProcSym == M2Base_Dispose)
9542 : {
9543 : /* avoid dangling else. */
9544 332 : BuildDisposeProcedure (tokno);
9545 : }
9546 20330 : else if (ProcSym == M2Base_Inc)
9547 : {
9548 : /* avoid dangling else. */
9549 14391 : BuildIncProcedure (tokno);
9550 : }
9551 5939 : else if (ProcSym == M2Base_Dec)
9552 : {
9553 : /* avoid dangling else. */
9554 3933 : BuildDecProcedure (tokno);
9555 : }
9556 2006 : else if (ProcSym == M2Base_Incl)
9557 : {
9558 : /* avoid dangling else. */
9559 1123 : BuildInclProcedure (tokno);
9560 : }
9561 883 : else if (ProcSym == M2Base_Excl)
9562 : {
9563 : /* avoid dangling else. */
9564 771 : BuildExclProcedure (tokno);
9565 : }
9566 112 : else if (ProcSym == M2System_Throw)
9567 : {
9568 : /* avoid dangling else. */
9569 112 : BuildThrowProcedure (tokno);
9570 : }
9571 : else
9572 : {
9573 : /* avoid dangling else. */
9574 0 : M2Error_InternalError ((const char *) "pseudo procedure not implemented yet", 36);
9575 : }
9576 21535 : }
9577 :
9578 :
9579 : /*
9580 : GetItemPointedTo - returns the symbol type that is being pointed to
9581 : by Sym.
9582 : */
9583 :
9584 3034 : static unsigned int GetItemPointedTo (unsigned int Sym)
9585 : {
9586 6076 : if (SymbolTable_IsPointer (Sym))
9587 : {
9588 3034 : return SymbolTable_GetSType (Sym);
9589 : }
9590 3042 : else if ((SymbolTable_IsVar (Sym)) || (SymbolTable_IsType (Sym)))
9591 : {
9592 : /* avoid dangling else. */
9593 3042 : return GetItemPointedTo (SymbolTable_GetSType (Sym));
9594 : }
9595 : else
9596 : {
9597 : /* avoid dangling else. */
9598 : return SymbolTable_NulSym;
9599 : }
9600 : /* static analysis guarentees a RETURN statement will be used before here. */
9601 : __builtin_unreachable ();
9602 : }
9603 :
9604 :
9605 : /*
9606 : BuildThrowProcedure - builds the pseudo procedure call M2RTS.Throw.
9607 : The Stack:
9608 :
9609 :
9610 : Entry Exit
9611 :
9612 : Ptr ->
9613 : +----------------+
9614 : | NoOfParam |
9615 : |----------------|
9616 : | Param 1 |
9617 : |----------------|
9618 : | Param 2 |
9619 : |----------------|
9620 : . .
9621 : . .
9622 : . .
9623 : |----------------|
9624 : | Param # |
9625 : |----------------|
9626 : | ProcSym | Type | Empty
9627 : |----------------|
9628 : */
9629 :
9630 112 : static void BuildThrowProcedure (unsigned int functok)
9631 : {
9632 112 : unsigned int op;
9633 112 : unsigned int NoOfParam;
9634 :
9635 112 : M2Quads_PopT (&NoOfParam);
9636 112 : if (NoOfParam == 1)
9637 : {
9638 112 : op = static_cast<unsigned int> (M2Quads_OperandT (NoOfParam));
9639 112 : GenQuadO (functok, M2Quads_ThrowOp, SymbolTable_NulSym, SymbolTable_NulSym, op, false);
9640 : }
9641 : else
9642 : {
9643 0 : M2MetaError_MetaErrorT1 (functok, (const char *) "the pseudo procedure %{1Ea} takes one INTEGER parameter", 55, M2System_Throw);
9644 : }
9645 112 : M2Quads_PopN (NoOfParam+1);
9646 112 : }
9647 :
9648 :
9649 : /*
9650 : BuildNewProcedure - builds the pseudo procedure call NEW.
9651 : This procedure is traditionally a "macro" for
9652 : NEW(x, ...) --> ALLOCATE(x, TSIZE(x^, ...))
9653 : One method of implementation is to emulate a "macro"
9654 : processor by pushing the relevant input tokens
9655 : back onto the input stack.
9656 : However this causes two problems:
9657 :
9658 : (i) Unnecessary code is produced for x^
9659 : (ii) SIZE must be imported from SYSTEM
9660 : Therefore we chose an alternative method of
9661 : implementation;
9662 : generate quadruples for ALLOCATE(x, TSIZE(x^, ...))
9663 : this, although slightly more efficient,
9664 : is more complex and circumvents problems (i) and (ii).
9665 :
9666 : The Stack:
9667 :
9668 :
9669 : Entry Exit
9670 :
9671 : Ptr ->
9672 : +----------------+
9673 : | NoOfParam |
9674 : |----------------|
9675 : | Param 1 |
9676 : |----------------|
9677 : | Param 2 |
9678 : |----------------|
9679 : . .
9680 : . .
9681 : . .
9682 : |----------------|
9683 : | Param # |
9684 : |----------------|
9685 : | ProcSym | Type | Empty
9686 : |----------------|
9687 : */
9688 :
9689 873 : static void BuildNewProcedure (unsigned int functok)
9690 : {
9691 873 : unsigned int NoOfParam;
9692 873 : unsigned int SizeSym;
9693 873 : unsigned int PtrSym;
9694 873 : unsigned int ProcSym;
9695 873 : unsigned int paramtok;
9696 873 : unsigned int combinedtok;
9697 :
9698 873 : M2Quads_PopT (&NoOfParam);
9699 873 : if (NoOfParam >= 1)
9700 : {
9701 873 : ProcSym = SymbolTable_RequestSym (functok, NameKey_MakeKey ((const char *) "ALLOCATE", 8));
9702 873 : if ((ProcSym != SymbolTable_NulSym) && (SymbolTable_IsProcedure (ProcSym)))
9703 : {
9704 873 : PtrSym = static_cast<unsigned int> (M2Quads_OperandT (NoOfParam));
9705 873 : paramtok = OperandTtok (1);
9706 873 : if (IsReallyPointer (PtrSym))
9707 : {
9708 872 : combinedtok = M2LexBuf_MakeVirtualTok (functok, functok, paramtok);
9709 : /*
9710 : Build macro: ALLOCATE( PtrSym, SIZE(PtrSym^) )
9711 : */
9712 872 : M2Quads_PushTFtok (M2System_TSize, M2Base_Cardinal, paramtok); /* Procedure */
9713 : /* x^ */
9714 872 : M2Quads_PushTtok (GetItemPointedTo (PtrSym), paramtok);
9715 872 : M2Quads_PushT (static_cast<unsigned int> (1)); /* One parameter */
9716 872 : M2Quads_BuildFunctionCall (false); /* One parameter */
9717 872 : M2Quads_PopT (&SizeSym);
9718 872 : M2Quads_PushTtok (ProcSym, combinedtok); /* ALLOCATE */
9719 872 : M2Quads_PushTtok (PtrSym, paramtok); /* x */
9720 872 : M2Quads_PushTtok (SizeSym, paramtok); /* TSIZE(x^) */
9721 872 : M2Quads_PushT (static_cast<unsigned int> (2)); /* Two parameters */
9722 872 : M2Quads_BuildProcedureCall (combinedtok); /* Two parameters */
9723 : }
9724 : else
9725 : {
9726 1 : M2MetaError_MetaErrorT1 (paramtok, (const char *) "parameter to {%EkNEW} must be a pointer, seen {%1Ed} {%1&s}", 59, PtrSym);
9727 : }
9728 : }
9729 : else
9730 : {
9731 0 : M2MetaError_MetaErrorT0 (functok, (const char *) "{%E}ALLOCATE procedure not found for NEW substitution", 53);
9732 : }
9733 : }
9734 : else
9735 : {
9736 0 : M2MetaError_MetaErrorT0 (functok, (const char *) "the pseudo procedure {%EkNEW} has one or more parameters", 56);
9737 : }
9738 873 : M2Quads_PopN (NoOfParam+1);
9739 873 : }
9740 :
9741 :
9742 : /*
9743 : BuildDisposeProcedure - builds the pseudo procedure call DISPOSE.
9744 : This procedure is traditionally a "macro" for
9745 : DISPOSE(x) --> DEALLOCATE(x, TSIZE(x^))
9746 : One method of implementation is to emulate a "macro"
9747 : processor by pushing the relevant input tokens
9748 : back onto the input stack.
9749 : However this causes two problems:
9750 :
9751 : (i) Unnecessary code is produced for x^
9752 : (ii) TSIZE must be imported from SYSTEM
9753 : Therefore we chose an alternative method of
9754 : implementation;
9755 : generate quadruples for DEALLOCATE(x, TSIZE(x^))
9756 : this, although slightly more efficient,
9757 : is more complex and circumvents problems (i)
9758 : and (ii).
9759 :
9760 : The Stack:
9761 :
9762 :
9763 : Entry Exit
9764 :
9765 : Ptr ->
9766 : +----------------+
9767 : | NoOfParam |
9768 : |----------------|
9769 : | Param 1 |
9770 : |----------------|
9771 : | Param 2 |
9772 : |----------------|
9773 : . .
9774 : . .
9775 : . .
9776 : |----------------|
9777 : | Param # |
9778 : |----------------|
9779 : | ProcSym | Type | Empty
9780 : |----------------|
9781 : */
9782 :
9783 332 : static void BuildDisposeProcedure (unsigned int functok)
9784 : {
9785 332 : unsigned int NoOfParam;
9786 332 : unsigned int SizeSym;
9787 332 : unsigned int PtrSym;
9788 332 : unsigned int ProcSym;
9789 332 : unsigned int combinedtok;
9790 332 : unsigned int paramtok;
9791 :
9792 332 : M2Quads_PopT (&NoOfParam);
9793 332 : if (NoOfParam >= 1)
9794 : {
9795 332 : ProcSym = SymbolTable_RequestSym (functok, NameKey_MakeKey ((const char *) "DEALLOCATE", 10));
9796 332 : if ((ProcSym != SymbolTable_NulSym) && (SymbolTable_IsProcedure (ProcSym)))
9797 : {
9798 332 : PtrSym = static_cast<unsigned int> (M2Quads_OperandT (NoOfParam));
9799 332 : paramtok = OperandTtok (1);
9800 332 : if (IsReallyPointer (PtrSym))
9801 : {
9802 332 : combinedtok = M2LexBuf_MakeVirtualTok (functok, functok, paramtok);
9803 : /*
9804 : Build macro: DEALLOCATE( PtrSym, TSIZE(PtrSym^) )
9805 : */
9806 332 : M2Quads_PushTFtok (M2System_TSize, M2Base_Cardinal, paramtok); /* Procedure */
9807 : /* x^ */
9808 332 : M2Quads_PushTtok (GetItemPointedTo (PtrSym), paramtok);
9809 332 : M2Quads_PushT (static_cast<unsigned int> (1)); /* One parameter */
9810 332 : M2Quads_BuildFunctionCall (false); /* One parameter */
9811 332 : M2Quads_PopT (&SizeSym);
9812 332 : M2Quads_PushTtok (ProcSym, combinedtok); /* DEALLOCATE */
9813 332 : M2Quads_PushTtok (PtrSym, paramtok); /* x */
9814 332 : M2Quads_PushTtok (SizeSym, paramtok); /* TSIZE(x^) */
9815 332 : M2Quads_PushT (static_cast<unsigned int> (2)); /* Two parameters */
9816 332 : M2Quads_BuildProcedureCall (combinedtok); /* Two parameters */
9817 : }
9818 : else
9819 : {
9820 0 : M2MetaError_MetaErrorT1 (paramtok, (const char *) "argument to {%EkDISPOSE} must be a pointer, seen {%1Ed} {%1&s}", 62, PtrSym);
9821 : }
9822 : }
9823 : else
9824 : {
9825 0 : M2MetaError_MetaErrorT0 (functok, (const char *) "{%E}DEALLOCATE procedure not found for DISPOSE substitution", 59);
9826 : }
9827 : }
9828 : else
9829 : {
9830 0 : M2MetaError_MetaErrorT0 (functok, (const char *) "the pseudo procedure {%EkDISPOSE} has one or more parameters", 60);
9831 : }
9832 332 : M2Quads_PopN (NoOfParam+1);
9833 332 : }
9834 :
9835 :
9836 : /*
9837 : CheckRangeIncDec - performs des := des <tok> expr
9838 : with range checking (if enabled).
9839 :
9840 : Stack
9841 : Entry Exit
9842 :
9843 : +------------+
9844 : empty | des + expr |
9845 : |------------|
9846 : */
9847 :
9848 18322 : static void CheckRangeIncDec (unsigned int tokenpos, unsigned int des, unsigned int expr, NameKey_Name tok)
9849 : {
9850 18322 : unsigned int dtype;
9851 18322 : unsigned int etype;
9852 :
9853 18322 : dtype = SymbolTable_GetDType (des);
9854 18322 : etype = SymbolTable_GetDType (expr);
9855 18322 : if ((etype == SymbolTable_NulSym) && (SymbolTable_IsPointer (SymbolTable_GetTypeMode (des))))
9856 : {
9857 24 : expr = ConvertToAddress (tokenpos, expr);
9858 24 : etype = M2System_Address;
9859 : }
9860 18322 : if (M2Options_WholeValueChecking && ! MustNotCheckBounds)
9861 : {
9862 : /* avoid gcc warning by using compound statement even if not strictly necessary. */
9863 1488 : if (tok == M2Reserved_PlusTok)
9864 : {
9865 804 : BuildRange (M2Range_InitIncRangeCheck (des, expr));
9866 : }
9867 : else
9868 : {
9869 684 : BuildRange (M2Range_InitDecRangeCheck (des, expr));
9870 : }
9871 : }
9872 18322 : if (M2Base_IsExpressionCompatible (dtype, etype))
9873 : {
9874 : /* the easy case simulate a straightforward macro */
9875 16852 : M2Quads_PushTFtok (des, dtype, tokenpos);
9876 16852 : M2Quads_PushT (tok);
9877 16852 : M2Quads_PushTFtok (expr, etype, tokenpos);
9878 16852 : doBuildBinaryOp (false, true);
9879 : }
9880 : else
9881 : {
9882 1470 : if ((((M2Base_IsOrdinalType (dtype)) || (dtype == M2System_Address)) || (SymbolTable_IsPointer (dtype))) && (((M2Base_IsOrdinalType (etype)) || (etype == M2System_Address)) || (SymbolTable_IsPointer (etype))))
9883 : {
9884 1470 : M2Quads_PushTFtok (des, dtype, tokenpos);
9885 1470 : M2Quads_PushT (tok);
9886 1470 : M2Quads_PushTFtok (M2Base_Convert, static_cast<unsigned int> (SymbolTable_NulSym), tokenpos);
9887 1470 : M2Quads_PushTtok (dtype, tokenpos);
9888 1470 : M2Quads_PushTtok (expr, tokenpos);
9889 1470 : M2Quads_PushT (static_cast<unsigned int> (2)); /* Two parameters */
9890 1470 : BuildConvertFunction (M2Base_Convert, false); /* Two parameters */
9891 1470 : doBuildBinaryOp (false, true);
9892 : }
9893 : else
9894 : {
9895 0 : if (tok == M2Reserved_PlusTok)
9896 : {
9897 0 : M2MetaError_MetaError0 ((const char *) "cannot perform {%EkINC} using non ordinal types", 47);
9898 : }
9899 : else
9900 : {
9901 0 : M2MetaError_MetaError0 ((const char *) "cannot perform {%EkDEC} using non ordinal types", 47);
9902 : }
9903 0 : M2Quads_PushTFtok (SymbolTable_MakeConstLit (tokenpos, NameKey_MakeKey ((const char *) "0", 1), SymbolTable_NulSym), static_cast<unsigned int> (SymbolTable_NulSym), tokenpos);
9904 : }
9905 : }
9906 18322 : }
9907 :
9908 :
9909 : /*
9910 : BuildIncProcedure - builds the pseudo procedure call INC.
9911 : INC is a procedure which increments a variable.
9912 : It takes one or two parameters:
9913 : INC(a, b) or INC(a)
9914 : a := a+b or a := a+1
9915 :
9916 : The Stack:
9917 :
9918 :
9919 : Entry Exit
9920 :
9921 : Ptr ->
9922 : +----------------+
9923 : | NoOfParam |
9924 : |----------------|
9925 : | Param 1 |
9926 : |----------------|
9927 : | Param 2 |
9928 : |----------------|
9929 : . .
9930 : . .
9931 : . .
9932 : |----------------|
9933 : | Param # |
9934 : |----------------|
9935 : | ProcSym | Type | Empty
9936 : |----------------|
9937 : */
9938 :
9939 14391 : static void BuildIncProcedure (unsigned int proctok)
9940 : {
9941 14391 : unsigned int vartok;
9942 14391 : unsigned int NoOfParam;
9943 14391 : unsigned int dtype;
9944 14391 : unsigned int OperandSym;
9945 14391 : unsigned int VarSym;
9946 14391 : unsigned int TempSym;
9947 :
9948 14391 : M2Quads_PopT (&NoOfParam);
9949 14391 : if ((NoOfParam == 1) || (NoOfParam == 2))
9950 : {
9951 14391 : VarSym = static_cast<unsigned int> (M2Quads_OperandT (NoOfParam)); /* Bottom/first parameter. */
9952 14391 : vartok = static_cast<unsigned int> (M2Quads_OperandTok (NoOfParam)); /* Bottom/first parameter. */
9953 14391 : if (SymbolTable_IsVar (VarSym))
9954 : {
9955 14390 : dtype = SymbolTable_GetDType (VarSym);
9956 14390 : if (NoOfParam == 2)
9957 : {
9958 2742 : OperandSym = DereferenceLValue (proctok, M2Quads_OperandT (1));
9959 : }
9960 : else
9961 : {
9962 11648 : PushOne (proctok, dtype, (const char *) "the {%EkINC} will cause an overflow {%1ad}", 42);
9963 11648 : M2Quads_PopT (&OperandSym);
9964 : }
9965 14390 : M2Quads_PushTtok (VarSym, vartok);
9966 14390 : TempSym = DereferenceLValue (vartok, VarSym);
9967 14390 : CheckRangeIncDec (proctok, TempSym, OperandSym, M2Reserved_PlusTok); /* TempSym + OperandSym. */
9968 14390 : BuildAssignmentWithoutBounds (proctok, false, true); /* VarSym := TempSym + OperandSym. */
9969 : }
9970 : else
9971 : {
9972 1 : M2MetaError_MetaErrorT1 (vartok, (const char *) "base procedure {%EkINC} expects a variable as a parameter but was given {%1Ed} {%1&s}", 85, VarSym);
9973 : }
9974 : }
9975 : else
9976 : {
9977 0 : M2MetaError_MetaErrorT0 (proctok, (const char *) "the base procedure {%EkINC} expects 1 or 2 parameters", 53);
9978 : }
9979 14391 : M2Quads_PopN (NoOfParam+1);
9980 14391 : }
9981 :
9982 :
9983 : /*
9984 : BuildDecProcedure - builds the pseudo procedure call DEC.
9985 : DEC is a procedure which decrements a variable.
9986 : It takes one or two parameters:
9987 : DEC(a, b) or DEC(a)
9988 : a := a-b or a := a-1
9989 :
9990 : The Stack:
9991 :
9992 :
9993 : Entry Exit
9994 :
9995 : Ptr ->
9996 : +----------------+
9997 : | NoOfParam |
9998 : |----------------|
9999 : | Param 1 |
10000 : |----------------|
10001 : | Param 2 |
10002 : |----------------|
10003 : . .
10004 : . .
10005 : . .
10006 : |----------------|
10007 : | Param # |
10008 : |----------------|
10009 : | ProcSym | Type | Empty
10010 : |----------------|
10011 : */
10012 :
10013 3933 : static void BuildDecProcedure (unsigned int proctok)
10014 : {
10015 3933 : unsigned int vartok;
10016 3933 : unsigned int NoOfParam;
10017 3933 : unsigned int dtype;
10018 3933 : unsigned int OperandSym;
10019 3933 : unsigned int VarSym;
10020 3933 : unsigned int TempSym;
10021 :
10022 3933 : M2Quads_PopT (&NoOfParam);
10023 3933 : if ((NoOfParam == 1) || (NoOfParam == 2))
10024 : {
10025 3933 : VarSym = static_cast<unsigned int> (M2Quads_OperandT (NoOfParam)); /* Bottom/first parameter. */
10026 3933 : vartok = static_cast<unsigned int> (M2Quads_OperandTok (NoOfParam)); /* Bottom/first parameter. */
10027 3933 : if (SymbolTable_IsVar (VarSym))
10028 : {
10029 3932 : dtype = SymbolTable_GetDType (VarSym);
10030 3932 : if (NoOfParam == 2)
10031 : {
10032 1392 : OperandSym = DereferenceLValue (proctok, M2Quads_OperandT (1));
10033 : }
10034 : else
10035 : {
10036 2540 : PushOne (proctok, dtype, (const char *) "the {%EkDEC} will cause an overflow {%1ad}", 42);
10037 2540 : M2Quads_PopT (&OperandSym);
10038 : }
10039 3932 : M2Quads_PushTtok (VarSym, vartok);
10040 3932 : TempSym = DereferenceLValue (vartok, VarSym);
10041 3932 : CheckRangeIncDec (proctok, TempSym, OperandSym, M2Reserved_MinusTok); /* TempSym - OperandSym. */
10042 3932 : BuildAssignmentWithoutBounds (proctok, false, true); /* VarSym := TempSym - OperandSym. */
10043 : }
10044 : else
10045 : {
10046 1 : M2MetaError_MetaErrorT1 (vartok, (const char *) "base procedure {%EkDEC} expects a variable as a parameter but was given {%1Ed} {%1&s}", 85, VarSym);
10047 : }
10048 : }
10049 : else
10050 : {
10051 0 : M2MetaError_MetaErrorT0 (proctok, (const char *) "the base procedure {%EkDEC} expects 1 or 2 parameters", 53);
10052 : }
10053 3933 : M2Quads_PopN (NoOfParam+1);
10054 3933 : }
10055 :
10056 :
10057 : /*
10058 : DereferenceLValue - checks to see whether, operand, is declare as an LValue
10059 : and if so it dereferences it.
10060 : */
10061 :
10062 30662 : static unsigned int DereferenceLValue (unsigned int tok, unsigned int operand)
10063 : {
10064 30662 : unsigned int sym;
10065 :
10066 30662 : if ((SymbolTable_GetMode (operand)) == SymbolTable_LeftValue)
10067 : {
10068 : /* dereference the pointer */
10069 1492 : sym = SymbolTable_MakeTemporary (tok, AreConstant (SymbolTable_IsConst (operand)));
10070 746 : SymbolTable_PutVar (sym, SymbolTable_GetSType (operand));
10071 746 : M2Quads_PushTtok (sym, tok);
10072 746 : M2Quads_PushTtok (operand, tok);
10073 746 : BuildAssignmentWithoutBounds (tok, false, true);
10074 746 : return sym;
10075 : }
10076 : else
10077 : {
10078 : return operand;
10079 : }
10080 : /* static analysis guarentees a RETURN statement will be used before here. */
10081 : __builtin_unreachable ();
10082 : }
10083 :
10084 :
10085 : /*
10086 : BuildInclProcedure - builds the pseudo procedure call INCL.
10087 : INCL is a procedure which adds bit b into a BITSET a.
10088 : It takes two parameters:
10089 : INCL(a, b)
10090 :
10091 : a := a + {b}
10092 :
10093 : The Stack:
10094 :
10095 :
10096 : Entry Exit
10097 :
10098 : Ptr ->
10099 : +----------------+
10100 : | NoOfParam |
10101 : |----------------|
10102 : | Param 1 |
10103 : |----------------|
10104 : | Param 2 |
10105 : |----------------|
10106 : | ProcSym | Type | Empty
10107 : |----------------|
10108 : */
10109 :
10110 1123 : static void BuildInclProcedure (unsigned int proctok)
10111 : {
10112 1123 : unsigned int vartok;
10113 1123 : unsigned int optok;
10114 1123 : unsigned int NoOfParam;
10115 1123 : unsigned int DerefSym;
10116 1123 : unsigned int OperandSym;
10117 1123 : unsigned int VarSym;
10118 :
10119 1123 : M2Quads_PopT (&NoOfParam);
10120 1123 : if (NoOfParam == 2)
10121 : {
10122 1123 : VarSym = static_cast<unsigned int> (M2Quads_OperandT (2));
10123 1123 : vartok = static_cast<unsigned int> (M2Quads_OperandTok (2));
10124 1123 : MarkArrayWritten (M2Quads_OperandA (2));
10125 1123 : OperandSym = static_cast<unsigned int> (M2Quads_OperandT (1));
10126 1123 : optok = static_cast<unsigned int> (M2Quads_OperandTok (1));
10127 1123 : if (SymbolTable_IsVar (VarSym))
10128 : {
10129 1116 : if (SymbolTable_IsSet (SymbolTable_GetDType (VarSym)))
10130 : {
10131 1116 : DerefSym = DereferenceLValue (optok, OperandSym);
10132 1116 : BuildRange (M2Range_InitInclCheck (VarSym, DerefSym));
10133 1116 : GenQuadO (proctok, M2Quads_InclOp, VarSym, SymbolTable_NulSym, DerefSym, false);
10134 : }
10135 : else
10136 : {
10137 0 : M2MetaError_MetaErrorT1 (vartok, (const char *) "the first parameter to {%EkINCL} must be a set variable, seen {%1Ed} {%1&s}", 75, VarSym);
10138 : }
10139 : }
10140 : else
10141 : {
10142 7 : M2MetaError_MetaErrorT1 (vartok, (const char *) "base procedure {%EkINCL} expects a variable as a parameter, seen {%1Ed} {%1&s}", 78, VarSym);
10143 : }
10144 : }
10145 : else
10146 : {
10147 0 : M2MetaError_MetaErrorT0 (proctok, (const char *) "the base procedure {%EkINCL} expects 1 or 2 parameters", 54);
10148 : }
10149 1123 : M2Quads_PopN (NoOfParam+1);
10150 1123 : }
10151 :
10152 :
10153 : /*
10154 : BuildExclProcedure - builds the pseudo procedure call EXCL.
10155 : INCL is a procedure which removes bit b from SET a.
10156 : It takes two parameters:
10157 : EXCL(a, b)
10158 :
10159 : a := a - {b}
10160 :
10161 : The Stack:
10162 :
10163 :
10164 : Entry Exit
10165 :
10166 : Ptr ->
10167 : +----------------+
10168 : | NoOfParam |
10169 : |----------------|
10170 : | Param 1 |
10171 : |----------------|
10172 : | Param 2 |
10173 : |----------------|
10174 : | ProcSym | Type | Empty
10175 : |----------------|
10176 : */
10177 :
10178 771 : static void BuildExclProcedure (unsigned int proctok)
10179 : {
10180 771 : unsigned int vartok;
10181 771 : unsigned int optok;
10182 771 : unsigned int NoOfParam;
10183 771 : unsigned int DerefSym;
10184 771 : unsigned int OperandSym;
10185 771 : unsigned int VarSym;
10186 :
10187 771 : M2Quads_PopT (&NoOfParam);
10188 771 : if (NoOfParam == 2)
10189 : {
10190 771 : VarSym = static_cast<unsigned int> (M2Quads_OperandT (2));
10191 771 : vartok = static_cast<unsigned int> (M2Quads_OperandTok (2));
10192 771 : MarkArrayWritten (M2Quads_OperandA (2));
10193 771 : OperandSym = static_cast<unsigned int> (M2Quads_OperandT (1));
10194 771 : optok = static_cast<unsigned int> (M2Quads_OperandTok (1));
10195 771 : if (SymbolTable_IsVar (VarSym))
10196 : {
10197 770 : if (SymbolTable_IsSet (SymbolTable_GetDType (VarSym)))
10198 : {
10199 770 : DerefSym = DereferenceLValue (optok, OperandSym);
10200 770 : BuildRange (M2Range_InitExclCheck (VarSym, DerefSym));
10201 770 : GenQuadO (proctok, M2Quads_ExclOp, VarSym, SymbolTable_NulSym, DerefSym, false);
10202 : }
10203 : else
10204 : {
10205 0 : M2MetaError_MetaErrorT1 (vartok, (const char *) "the first parameter to {%EkEXCL} must be a set variable, seen {%1Ed} {%1&s}", 75, VarSym);
10206 : }
10207 : }
10208 : else
10209 : {
10210 1 : M2MetaError_MetaErrorT1 (vartok, (const char *) "base procedure {%EkEXCL} expects a variable as a parameter, seen {%1Ed} {%1&s}", 78, VarSym);
10211 : }
10212 : }
10213 : else
10214 : {
10215 0 : M2MetaError_MetaErrorT0 (proctok, (const char *) "the base procedure {%EkEXCL} expects 1 or 2 parameters", 54);
10216 : }
10217 771 : M2Quads_PopN (NoOfParam+1);
10218 771 : }
10219 :
10220 :
10221 : /*
10222 : BuildTypeCoercion - builds the type coersion.
10223 : Modula-2 allows types to be coersed with no runtime
10224 : penility.
10225 : It insists that the TSIZE(t1)=TSIZE(t2) where
10226 : t2 variable := t2(variable of type t1).
10227 : The ReturnVar on the stack is of type t2.
10228 :
10229 : The Stack:
10230 :
10231 :
10232 : Entry Exit
10233 :
10234 : Ptr ->
10235 : +----------------+
10236 : | NoOfParam |
10237 : |----------------|
10238 : | Param 1 |
10239 : |----------------|
10240 : | Param 2 |
10241 : |----------------|
10242 : . .
10243 : . .
10244 : . .
10245 : |----------------|
10246 : | Param # | <- Ptr
10247 : |----------------| +------------+
10248 : | ProcSym | Type | | ReturnVar |
10249 : |----------------| |------------|
10250 :
10251 : Quadruples:
10252 :
10253 : CoerceOp ReturnVar Type Param1
10254 :
10255 : A type coercion will only be legal if the different
10256 : types have exactly the same size.
10257 : Since we can only decide this after M2Eval has processed
10258 : the symbol table then we create a quadruple explaining
10259 : the coercion taking place, the code generator can test
10260 : this assertion and report an error if the type sizes
10261 : differ.
10262 : */
10263 :
10264 2574 : static void BuildTypeCoercion (bool ConstExpr)
10265 : {
10266 2574 : unsigned int resulttok;
10267 2574 : unsigned int proctok;
10268 2574 : unsigned int exptok;
10269 2574 : unsigned int r;
10270 2574 : unsigned int exp;
10271 2574 : unsigned int NoOfParam;
10272 2574 : unsigned int ReturnVar;
10273 2574 : unsigned int ProcSym;
10274 :
10275 2574 : M2Quads_PopT (&NoOfParam);
10276 2574 : ProcSym = static_cast<unsigned int> (M2Quads_OperandT (NoOfParam+1));
10277 2574 : proctok = static_cast<unsigned int> (M2Quads_OperandTok (NoOfParam+1));
10278 2574 : if (! (SymbolTable_IsAModula2Type (ProcSym)))
10279 : {
10280 0 : M2MetaError_MetaError1 ((const char *) "coersion expecting a type, seen {%1Ea} which is {%1Ed} {%1&s}", 61, ProcSym);
10281 : }
10282 2574 : if (NoOfParam == 1)
10283 : {
10284 2574 : PopTrwtok (&exp, &r, &exptok);
10285 2574 : MarkAsRead (r);
10286 2574 : resulttok = M2LexBuf_MakeVirtual2Tok (proctok, exptok);
10287 2574 : M2Quads_PopN (1); /* Pop procedure. */
10288 2574 : if (ConstExprError (ProcSym, exp, exptok, ConstExpr)) /* Pop procedure. */
10289 : {
10290 0 : ReturnVar = SymbolTable_MakeTemporary (resulttok, SymbolTable_ImmediateValue);
10291 0 : SymbolTable_PutVar (ReturnVar, ProcSym); /* Set ReturnVar's TYPE. */
10292 : }
10293 : /* Set ReturnVar's TYPE. */
10294 2574 : else if ((SymbolTable_IsConst (exp)) || (SymbolTable_IsVar (exp)))
10295 : {
10296 : /* avoid dangling else. */
10297 5148 : ReturnVar = SymbolTable_MakeTemporary (resulttok, AreConstant (SymbolTable_IsConst (exp)));
10298 2574 : SymbolTable_PutVar (ReturnVar, ProcSym); /* Set ReturnVar's TYPE. */
10299 2574 : GenQuad (M2Quads_CoerceOp, ReturnVar, ProcSym, exp); /* Set ReturnVar's TYPE. */
10300 : }
10301 : else
10302 : {
10303 : /* avoid dangling else. */
10304 0 : M2MetaError_MetaError2 ((const char *) "trying to coerse {%1EMRad} which is not a variable or constant into {%2ad}", 74, exp, ProcSym);
10305 0 : M2MetaError_MetaError2 ((const char *) "trying to coerse {%1ECad} which is not a variable or constant into {%2ad}", 73, exp, ProcSym);
10306 0 : ReturnVar = SymbolTable_MakeTemporary (resulttok, SymbolTable_RightValue);
10307 0 : SymbolTable_PutVar (ReturnVar, ProcSym); /* Set ReturnVar's TYPE. */
10308 : }
10309 2574 : M2Quads_PushTFtok (ReturnVar, ProcSym, resulttok);
10310 : }
10311 : else
10312 : {
10313 0 : M2MetaError_MetaError0 ((const char *) "{%E}only one parameter expected in a TYPE coersion", 50);
10314 : }
10315 2574 : }
10316 :
10317 :
10318 : /*
10319 : BuildRealFunctionCall - builds a function call.
10320 : The Stack:
10321 :
10322 :
10323 : Entry Exit
10324 :
10325 : Ptr ->
10326 : +----------------+
10327 : | NoOfParam |
10328 : |----------------|
10329 : | Param 1 |
10330 : |----------------|
10331 : | Param 2 |
10332 : |----------------|
10333 : . .
10334 : . .
10335 : . .
10336 : |----------------|
10337 : | Param # | <- Ptr
10338 : |----------------| +------------+
10339 : | ProcSym | Type | | ReturnVar |
10340 : |----------------| |------------|
10341 : */
10342 :
10343 61948 : static void BuildRealFunctionCall (unsigned int tokno, bool ConstExpr)
10344 : {
10345 61948 : unsigned int NoOfParam;
10346 61948 : unsigned int ProcSym;
10347 :
10348 61948 : M2Quads_PopT (&NoOfParam);
10349 61948 : M2Quads_PushT (NoOfParam);
10350 61948 : ProcSym = static_cast<unsigned int> (M2Quads_OperandT (NoOfParam+2));
10351 61948 : ProcSym = PCSymBuild_SkipConst (ProcSym);
10352 61948 : if (SymbolTable_IsVar (ProcSym))
10353 : {
10354 : /* Procedure Variable therefore get its type to see if it is a FOR "C" call. */
10355 94 : ProcSym = SymbolTable_SkipType (M2Quads_OperandF (NoOfParam+2));
10356 : }
10357 61948 : if ((SymbolTable_IsDefImp (SymbolTable_GetScope (ProcSym))) && (SymbolTable_IsDefinitionForC (SymbolTable_GetScope (ProcSym))))
10358 : {
10359 7342 : BuildRealFuncProcCall (tokno, true, true, ConstExpr);
10360 : }
10361 : else
10362 : {
10363 54606 : BuildRealFuncProcCall (tokno, true, false, ConstExpr);
10364 : }
10365 61936 : }
10366 :
10367 :
10368 : /*
10369 : BuildPseudoFunctionCall - builds the pseudo function
10370 : The Stack:
10371 :
10372 :
10373 : Entry Exit
10374 :
10375 : Ptr ->
10376 : +----------------+
10377 : | NoOfParam |
10378 : |----------------|
10379 : | Param 1 |
10380 : |----------------|
10381 : | Param 2 |
10382 : |----------------|
10383 : . .
10384 : . .
10385 : . .
10386 : |----------------|
10387 : | Param # | <- Ptr
10388 : |----------------| +------------+
10389 : | ProcSym | Type | | ReturnVar |
10390 : |----------------| |------------|
10391 :
10392 : */
10393 :
10394 42796 : static void BuildPseudoFunctionCall (bool ConstExpr)
10395 : {
10396 42796 : unsigned int NoOfParam;
10397 42796 : unsigned int ProcSym;
10398 :
10399 42796 : M2Quads_PopT (&NoOfParam);
10400 42796 : ProcSym = static_cast<unsigned int> (M2Quads_OperandT (NoOfParam+1));
10401 42796 : ProcSym = PCSymBuild_SkipConst (ProcSym);
10402 42796 : M2Quads_PushT (NoOfParam);
10403 : /* Compile time stack restored to entry state. */
10404 42796 : if (ProcSym == M2Base_High)
10405 : {
10406 2978 : BuildHighFunction ();
10407 : }
10408 39818 : else if (ProcSym == M2Base_LengthS)
10409 : {
10410 : /* avoid dangling else. */
10411 346 : BuildLengthFunction (ProcSym, ConstExpr);
10412 : }
10413 39472 : else if (ProcSym == M2System_Adr)
10414 : {
10415 : /* avoid dangling else. */
10416 9711 : BuildAdrFunction ();
10417 : }
10418 29761 : else if (ProcSym == M2Size_Size)
10419 : {
10420 : /* avoid dangling else. */
10421 2099 : BuildSizeFunction ();
10422 : }
10423 27662 : else if (ProcSym == M2System_TSize)
10424 : {
10425 : /* avoid dangling else. */
10426 4774 : BuildTSizeFunction ();
10427 : }
10428 22888 : else if (ProcSym == M2System_TBitSize)
10429 : {
10430 : /* avoid dangling else. */
10431 6496 : BuildTBitSizeFunction ();
10432 : }
10433 16392 : else if (ProcSym == M2Base_Convert)
10434 : {
10435 : /* avoid dangling else. */
10436 12 : BuildConvertFunction (ProcSym, ConstExpr);
10437 : }
10438 16380 : else if (ProcSym == M2Base_Odd)
10439 : {
10440 : /* avoid dangling else. */
10441 46 : BuildOddFunction (ProcSym, ConstExpr);
10442 : }
10443 16334 : else if (ProcSym == M2Base_Abs)
10444 : {
10445 : /* avoid dangling else. */
10446 177 : BuildAbsFunction (ProcSym, ConstExpr);
10447 : }
10448 16157 : else if (ProcSym == M2Base_Cap)
10449 : {
10450 : /* avoid dangling else. */
10451 125 : BuildCapFunction (ProcSym, ConstExpr);
10452 : }
10453 16032 : else if (ProcSym == M2Base_Val)
10454 : {
10455 : /* avoid dangling else. */
10456 4920 : BuildValFunction (ProcSym, ConstExpr);
10457 : }
10458 11112 : else if (ProcSym == M2Base_Chr)
10459 : {
10460 : /* avoid dangling else. */
10461 1024 : BuildChrFunction (ProcSym, ConstExpr);
10462 : }
10463 10088 : else if (M2Base_IsOrd (ProcSym))
10464 : {
10465 : /* avoid dangling else. */
10466 4724 : BuildOrdFunction (ProcSym, ConstExpr);
10467 : }
10468 5364 : else if (M2Base_IsInt (ProcSym))
10469 : {
10470 : /* avoid dangling else. */
10471 6 : BuildIntFunction (ProcSym, ConstExpr);
10472 : }
10473 5358 : else if (M2Base_IsTrunc (ProcSym))
10474 : {
10475 : /* avoid dangling else. */
10476 60 : BuildTruncFunction (ProcSym, ConstExpr);
10477 : }
10478 5298 : else if (M2Base_IsFloat (ProcSym))
10479 : {
10480 : /* avoid dangling else. */
10481 88 : BuildFloatFunction (ProcSym, ConstExpr);
10482 : }
10483 5210 : else if (ProcSym == M2Base_Min)
10484 : {
10485 : /* avoid dangling else. */
10486 1250 : BuildMinFunction ();
10487 : }
10488 3960 : else if (ProcSym == M2Base_Max)
10489 : {
10490 : /* avoid dangling else. */
10491 2032 : BuildMaxFunction ();
10492 : }
10493 1928 : else if (ProcSym == M2System_AddAdr)
10494 : {
10495 : /* avoid dangling else. */
10496 36 : BuildAddAdrFunction (ProcSym, ConstExpr);
10497 : }
10498 1892 : else if (ProcSym == M2System_SubAdr)
10499 : {
10500 : /* avoid dangling else. */
10501 12 : BuildSubAdrFunction (ProcSym, ConstExpr);
10502 : }
10503 1880 : else if (ProcSym == M2System_DifAdr)
10504 : {
10505 : /* avoid dangling else. */
10506 12 : BuildDifAdrFunction (ProcSym, ConstExpr);
10507 : }
10508 1868 : else if (ProcSym == M2System_Cast)
10509 : {
10510 : /* avoid dangling else. */
10511 156 : BuildCastFunction (ProcSym, ConstExpr);
10512 : }
10513 1712 : else if (ProcSym == M2System_Shift)
10514 : {
10515 : /* avoid dangling else. */
10516 682 : BuildShiftFunction ();
10517 : }
10518 1030 : else if (ProcSym == M2System_Rotate)
10519 : {
10520 : /* avoid dangling else. */
10521 406 : BuildRotateFunction ();
10522 : }
10523 624 : else if (ProcSym == M2System_MakeAdr)
10524 : {
10525 : /* avoid dangling else. */
10526 12 : BuildMakeAdrFunction ();
10527 : }
10528 612 : else if (ProcSym == M2Base_Re)
10529 : {
10530 : /* avoid dangling else. */
10531 60 : BuildReFunction (ProcSym, ConstExpr);
10532 : }
10533 552 : else if (ProcSym == M2Base_Im)
10534 : {
10535 : /* avoid dangling else. */
10536 60 : BuildImFunction (ProcSym, ConstExpr);
10537 : }
10538 492 : else if (ProcSym == M2Base_Cmplx)
10539 : {
10540 : /* avoid dangling else. */
10541 492 : BuildCmplxFunction (ProcSym, ConstExpr);
10542 : }
10543 : else
10544 : {
10545 : /* avoid dangling else. */
10546 0 : M2Error_InternalError ((const char *) "pseudo function not implemented yet", 35);
10547 : }
10548 42781 : }
10549 :
10550 :
10551 : /*
10552 : BuildAddAdrFunction - builds the pseudo procedure call ADDADR.
10553 :
10554 : PROCEDURE ADDADR (addr: ADDRESS; offset: CARDINAL): ADDRESS ;
10555 :
10556 : Which returns address given by (addr + offset),
10557 : [ the standard says that it _may_
10558 : "raise an exception if this address is not valid."
10559 : currently we do not generate any exception code ]
10560 :
10561 : The Stack:
10562 :
10563 : Entry Exit
10564 :
10565 : Ptr ->
10566 : +----------------+
10567 : | NoOfParam |
10568 : |----------------|
10569 : | Param 1 |
10570 : |----------------|
10571 : | Param 2 | <- Ptr
10572 : |----------------| +------------+
10573 : | ProcSym | Type | | ReturnVar |
10574 : |----------------| |------------|
10575 : */
10576 :
10577 36 : static void BuildAddAdrFunction (unsigned int ProcSym, bool ConstExpr)
10578 : {
10579 36 : unsigned int combinedtok;
10580 36 : unsigned int functok;
10581 36 : unsigned int vartok;
10582 36 : unsigned int optok;
10583 36 : unsigned int opa;
10584 36 : unsigned int ReturnVar;
10585 36 : unsigned int NoOfParam;
10586 36 : unsigned int OperandSym;
10587 36 : unsigned int VarSym;
10588 :
10589 36 : M2Quads_PopT (&NoOfParam);
10590 36 : functok = OperandTtok (NoOfParam+1);
10591 36 : if (NoOfParam == 2)
10592 : {
10593 36 : VarSym = static_cast<unsigned int> (M2Quads_OperandT (2));
10594 36 : vartok = static_cast<unsigned int> (M2Quads_OperandTok (2));
10595 36 : OperandSym = static_cast<unsigned int> (M2Quads_OperandT (1));
10596 36 : optok = static_cast<unsigned int> (M2Quads_OperandTok (1));
10597 36 : combinedtok = M2LexBuf_MakeVirtual2Tok (functok, optok);
10598 36 : M2Quads_PopN (NoOfParam+1);
10599 36 : if ((ConstExprError (ProcSym, VarSym, vartok, ConstExpr)) || (ConstExprError (ProcSym, OperandSym, optok, ConstExpr)))
10600 : {
10601 : /* Fake return result. */
10602 0 : M2Quads_PushTFtok (SymbolTable_MakeConstLit (combinedtok, NameKey_MakeKey ((const char *) "0", 1), M2System_Address), M2System_Address, combinedtok);
10603 : }
10604 36 : else if (SymbolTable_IsVar (VarSym))
10605 : {
10606 : /* avoid dangling else. */
10607 36 : if ((IsReallyPointer (VarSym)) || ((SymbolTable_GetSType (VarSym)) == M2System_Address))
10608 : {
10609 36 : ReturnVar = SymbolTable_MakeTemporary (combinedtok, SymbolTable_RightValue);
10610 36 : SymbolTable_PutVar (ReturnVar, M2System_Address);
10611 36 : opa = ConvertToAddress (optok, DereferenceLValue (optok, OperandSym));
10612 72 : GenQuadOtok (combinedtok, M2Quads_AddOp, ReturnVar, VarSym, opa, true, combinedtok, combinedtok, combinedtok);
10613 36 : M2Quads_PushTFtok (ReturnVar, M2System_Address, combinedtok);
10614 : }
10615 : else
10616 : {
10617 0 : M2MetaError_MetaErrorT1 (functok, (const char *) "the first parameter to ADDADR {%1Ea} must be a variable of type ADDRESS or a {%EkPOINTER}, rather than a {%1Etsdv}", 114, VarSym);
10618 0 : M2Quads_PushTFtok (SymbolTable_MakeConstLit (combinedtok, NameKey_MakeKey ((const char *) "0", 1), M2System_Address), M2System_Address, combinedtok);
10619 : }
10620 : }
10621 : else
10622 : {
10623 : /* avoid dangling else. */
10624 0 : M2MetaError_MetaErrorT0 (functok, (const char *) "{%E}SYSTEM procedure ADDADR expects a variable of type ADDRESS or POINTER as its first parameter", 96);
10625 0 : M2Quads_PushTFtok (SymbolTable_MakeConstLit (combinedtok, NameKey_MakeKey ((const char *) "0", 1), M2System_Address), M2System_Address, combinedtok);
10626 : }
10627 : }
10628 : else
10629 : {
10630 0 : M2MetaError_MetaErrorT0 (functok, (const char *) "{%E}SYSTEM procedure {%EkADDADR} expects 2 parameters", 53);
10631 0 : M2Quads_PopN (NoOfParam+1);
10632 0 : M2Quads_PushTFtok (SymbolTable_MakeConstLit (functok, NameKey_MakeKey ((const char *) "0", 1), M2System_Address), M2System_Address, functok);
10633 : }
10634 36 : }
10635 :
10636 :
10637 : /*
10638 : BuildSubAdrFunction - builds the pseudo procedure call ADDADR.
10639 :
10640 : PROCEDURE SUBADR (addr: ADDRESS; offset: CARDINAL): ADDRESS ;
10641 :
10642 : Which returns address given by (addr - offset),
10643 : [ the standard says that it _may_
10644 : "raise an exception if this address is not valid."
10645 : currently we do not generate any exception code ]
10646 :
10647 : The Stack:
10648 :
10649 : Entry Exit
10650 :
10651 : Ptr ->
10652 : +----------------+
10653 : | NoOfParam |
10654 : |----------------|
10655 : | Param 1 |
10656 : |----------------|
10657 : | Param 2 | <- Ptr
10658 : |----------------| +------------+
10659 : | ProcSym | Type | | ReturnVar |
10660 : |----------------| |------------|
10661 : */
10662 :
10663 12 : static void BuildSubAdrFunction (unsigned int ProcSym, bool ConstExpr)
10664 : {
10665 12 : unsigned int functok;
10666 12 : unsigned int combinedtok;
10667 12 : unsigned int optok;
10668 12 : unsigned int vartok;
10669 12 : unsigned int ReturnVar;
10670 12 : unsigned int NoOfParam;
10671 12 : unsigned int OperandSym;
10672 12 : unsigned int opa;
10673 12 : unsigned int VarSym;
10674 :
10675 12 : M2Quads_PopT (&NoOfParam);
10676 12 : functok = OperandTtok (NoOfParam+1);
10677 12 : if (NoOfParam == 2)
10678 : {
10679 12 : optok = static_cast<unsigned int> (M2Quads_OperandTok (1));
10680 12 : OperandSym = static_cast<unsigned int> (M2Quads_OperandT (1));
10681 12 : VarSym = static_cast<unsigned int> (M2Quads_OperandT (2));
10682 12 : vartok = static_cast<unsigned int> (M2Quads_OperandTok (2));
10683 12 : combinedtok = M2LexBuf_MakeVirtualTok (functok, functok, optok);
10684 12 : M2Quads_PopN (NoOfParam+1);
10685 12 : if ((ConstExprError (ProcSym, VarSym, vartok, ConstExpr)) || (ConstExprError (ProcSym, OperandSym, optok, ConstExpr)))
10686 : {
10687 : /* Fake return result. */
10688 0 : M2Quads_PushTFtok (SymbolTable_MakeConstLit (combinedtok, NameKey_MakeKey ((const char *) "0", 1), M2System_Address), M2System_Address, combinedtok);
10689 : }
10690 12 : else if (SymbolTable_IsVar (VarSym))
10691 : {
10692 : /* avoid dangling else. */
10693 12 : if ((IsReallyPointer (VarSym)) || ((SymbolTable_GetSType (VarSym)) == M2System_Address))
10694 : {
10695 12 : ReturnVar = SymbolTable_MakeTemporary (combinedtok, SymbolTable_RightValue);
10696 12 : SymbolTable_PutVar (ReturnVar, M2System_Address);
10697 12 : opa = ConvertToAddress (optok, DereferenceLValue (optok, OperandSym));
10698 24 : GenQuadOtok (combinedtok, M2Quads_SubOp, ReturnVar, VarSym, opa, true, combinedtok, combinedtok, combinedtok);
10699 12 : M2Quads_PushTFtok (ReturnVar, M2System_Address, combinedtok);
10700 : }
10701 : else
10702 : {
10703 0 : M2MetaError_MetaErrorT1 (functok, (const char *) "the first parameter to {%EkSUBADR} {%1Ea} must be a variable of type ADDRESS or a {%EkPOINTER}, rather than a {%1Etsdv}", 119, VarSym);
10704 0 : M2Quads_PushTFtok (SymbolTable_MakeConstLit (vartok, NameKey_MakeKey ((const char *) "0", 1), M2System_Address), M2System_Address, vartok);
10705 : }
10706 : }
10707 : else
10708 : {
10709 : /* avoid dangling else. */
10710 0 : combinedtok = M2LexBuf_MakeVirtualTok (functok, functok, optok);
10711 0 : M2MetaError_MetaErrorT0 (combinedtok, (const char *) "{%E}SYSTEM procedure {%EkSUBADR} expects a variable of type ADDRESS or POINTER as its first parameter", 101);
10712 0 : M2Quads_PushTFtok (SymbolTable_MakeConstLit (combinedtok, NameKey_MakeKey ((const char *) "0", 1), M2System_Address), M2System_Address, combinedtok);
10713 : }
10714 : }
10715 : else
10716 : {
10717 0 : M2MetaError_MetaErrorT0 (functok, (const char *) "{%E}SYSTEM procedure {%EkSUBADR} expects 2 parameters", 53);
10718 0 : M2Quads_PopN (NoOfParam+1);
10719 0 : M2Quads_PushTFtok (SymbolTable_MakeConstLit (functok, NameKey_MakeKey ((const char *) "0", 1), M2System_Address), M2System_Address, functok);
10720 : }
10721 12 : }
10722 :
10723 :
10724 : /*
10725 : BuildDifAdrFunction - builds the pseudo procedure call DIFADR.
10726 :
10727 : PROCEDURE DIFADR (addr1, addr2: ADDRESS): INTEGER ;
10728 :
10729 : Which returns address given by (addr1 - addr2),
10730 : [ the standard says that it _may_
10731 : "raise an exception if this address is invalid or
10732 : address space is non-contiguous."
10733 : currently we do not generate any exception code ]
10734 :
10735 : The Stack:
10736 :
10737 : Entry Exit
10738 :
10739 : Ptr ->
10740 : +----------------+
10741 : | NoOfParam |
10742 : |----------------|
10743 : | Param 1 |
10744 : |----------------|
10745 : | Param 2 | <- Ptr
10746 : |----------------| +------------+
10747 : | ProcSym | Type | | ReturnVar |
10748 : |----------------| |------------|
10749 : */
10750 :
10751 12 : static void BuildDifAdrFunction (unsigned int ProcSym, bool ConstExpr)
10752 : {
10753 12 : unsigned int functok;
10754 12 : unsigned int optok;
10755 12 : unsigned int vartok;
10756 12 : unsigned int combinedtok;
10757 12 : unsigned int TempVar;
10758 12 : unsigned int NoOfParam;
10759 12 : unsigned int OperandSym;
10760 12 : unsigned int opa;
10761 12 : unsigned int VarSym;
10762 :
10763 12 : M2Quads_PopT (&NoOfParam);
10764 12 : functok = OperandTtok (NoOfParam+1);
10765 12 : if (NoOfParam >= 1)
10766 : {
10767 12 : OperandSym = static_cast<unsigned int> (M2Quads_OperandT (1));
10768 12 : optok = static_cast<unsigned int> (M2Quads_OperandTok (1));
10769 : }
10770 : else
10771 : {
10772 : optok = functok;
10773 : }
10774 12 : if (NoOfParam == 2)
10775 : {
10776 12 : VarSym = static_cast<unsigned int> (M2Quads_OperandT (2));
10777 12 : vartok = static_cast<unsigned int> (M2Quads_OperandTok (2));
10778 12 : combinedtok = M2LexBuf_MakeVirtualTok (functok, functok, optok);
10779 12 : M2Quads_PopN (NoOfParam+1);
10780 12 : if ((ConstExprError (ProcSym, VarSym, vartok, ConstExpr)) || (ConstExprError (ProcSym, OperandSym, optok, ConstExpr)))
10781 : {
10782 : /* Fake return result. */
10783 0 : M2Quads_PushTFtok (SymbolTable_MakeConstLit (combinedtok, NameKey_MakeKey ((const char *) "0", 1), M2Base_Integer), M2Base_Integer, combinedtok);
10784 : }
10785 12 : else if (SymbolTable_IsVar (VarSym))
10786 : {
10787 : /* avoid dangling else. */
10788 12 : if ((IsReallyPointer (VarSym)) || ((SymbolTable_GetSType (VarSym)) == M2System_Address))
10789 : {
10790 12 : if ((IsReallyPointer (OperandSym)) || ((SymbolTable_GetSType (OperandSym)) == M2System_Address))
10791 : {
10792 12 : TempVar = SymbolTable_MakeTemporary (vartok, SymbolTable_RightValue);
10793 12 : SymbolTable_PutVar (TempVar, M2System_Address);
10794 12 : opa = ConvertToAddress (optok, DereferenceLValue (optok, OperandSym));
10795 24 : GenQuadOtok (combinedtok, M2Quads_SubOp, TempVar, VarSym, opa, true, combinedtok, combinedtok, combinedtok);
10796 : /*
10797 : Build macro: CONVERT( INTEGER, TempVar )
10798 : */
10799 12 : M2Quads_PushTFtok (M2Base_Convert, static_cast<unsigned int> (SymbolTable_NulSym), functok);
10800 12 : M2Quads_PushTtok (M2Base_Integer, functok);
10801 12 : M2Quads_PushTtok (TempVar, vartok);
10802 12 : M2Quads_PushT (static_cast<unsigned int> (2)); /* Two parameters */
10803 12 : BuildConvertFunction (M2Base_Convert, ConstExpr); /* Two parameters */
10804 : }
10805 : else
10806 : {
10807 0 : M2MetaError_MetaError1 ((const char *) "the second parameter to {%EkDIFADR} {%1Ea} must be a variable of type ADDRESS or a {%EkPOINTER}, rather than a {%1Etsdv}", 120, OperandSym);
10808 0 : M2Quads_PushTFtok (SymbolTable_MakeConstLit (combinedtok, NameKey_MakeKey ((const char *) "0", 1), M2Base_Integer), M2Base_Integer, combinedtok);
10809 : }
10810 : }
10811 : else
10812 : {
10813 0 : M2MetaError_MetaErrorT1 (vartok, (const char *) "the first parameter to {%EkDIFADR} {%1Ea} must be a variable of type ADDRESS or a {%EkPOINTER}, rather than a {%1Etsdv}", 119, VarSym);
10814 0 : M2Quads_PushTFtok (SymbolTable_MakeConstLit (combinedtok, NameKey_MakeKey ((const char *) "0", 1), M2Base_Integer), M2Base_Integer, combinedtok);
10815 : }
10816 : }
10817 : else
10818 : {
10819 : /* avoid dangling else. */
10820 0 : M2MetaError_MetaError0 ((const char *) "{%E}SYSTEM procedure {%EkDIFADR} expects a variable of type ADDRESS or POINTER as its first parameter", 101);
10821 0 : M2Quads_PushTFtok (SymbolTable_MakeConstLit (combinedtok, NameKey_MakeKey ((const char *) "0", 1), M2Base_Integer), M2Base_Integer, combinedtok);
10822 : }
10823 : }
10824 : else
10825 : {
10826 0 : combinedtok = M2LexBuf_MakeVirtual2Tok (functok, optok);
10827 0 : M2MetaError_MetaErrorT0 (combinedtok, (const char *) "{%E}SYSTEM procedure {%EkDIFADR} expects 2 parameters", 53);
10828 0 : M2Quads_PopN (NoOfParam+1);
10829 0 : M2Quads_PushTFtok (SymbolTable_MakeConstLit (combinedtok, NameKey_MakeKey ((const char *) "0", 1), M2Base_Integer), M2Base_Integer, combinedtok);
10830 : }
10831 12 : }
10832 :
10833 :
10834 : /*
10835 : BuildHighFunction - checks the stack in preparation for generating
10836 : quadruples which perform HIGH.
10837 : This procedure does not alter the stack but
10838 : determines whether, a, in HIGH(a) is an ArraySym
10839 : or UnboundedSym.
10840 : Both cases are different and appropriate quadruple
10841 : generating routines are called.
10842 :
10843 : The Stack:
10844 :
10845 :
10846 : Entry Exit
10847 :
10848 : Ptr ->
10849 : +----------------+
10850 : | NoOfParam |
10851 : |----------------|
10852 : | Param 1 |
10853 : |----------------|
10854 : | Param 2 |
10855 : |----------------|
10856 : . .
10857 : . .
10858 : . .
10859 : |----------------|
10860 : | Param # | <- Ptr
10861 : |----------------| +------------+
10862 : | ProcSym | Type | | ReturnVar |
10863 : |----------------| |------------|
10864 :
10865 : */
10866 :
10867 2978 : static void BuildHighFunction (void)
10868 : {
10869 2978 : unsigned int functok;
10870 2978 : unsigned int combinedtok;
10871 2978 : unsigned int paramtok;
10872 2978 : unsigned int ProcSym;
10873 2978 : unsigned int Type;
10874 2978 : unsigned int NoOfParam;
10875 2978 : unsigned int Param;
10876 :
10877 2978 : M2Quads_PopT (&NoOfParam);
10878 2978 : ProcSym = static_cast<unsigned int> (M2Quads_OperandT (NoOfParam+1));
10879 2978 : functok = static_cast<unsigned int> (M2Quads_OperandTok (NoOfParam+1));
10880 2978 : BuildSizeCheckEnd (ProcSym); /* quadruple generation now on */
10881 2978 : if (NoOfParam == 1) /* quadruple generation now on */
10882 : {
10883 2978 : Param = static_cast<unsigned int> (M2Quads_OperandT (1));
10884 2978 : paramtok = static_cast<unsigned int> (M2Quads_OperandTok (1));
10885 2978 : combinedtok = M2LexBuf_MakeVirtualTok (paramtok, functok, paramtok);
10886 2978 : Type = SymbolTable_GetDType (Param);
10887 : /* Restore stack to original form */
10888 2978 : M2Quads_PushT (NoOfParam);
10889 2978 : if (((! (SymbolTable_IsVar (Param))) && (! (SymbolTable_IsConstString (Param)))) && (! (SymbolTable_IsConst (Param))))
10890 : {
10891 : /* we cannot test for IsConst(Param) AND (GetSType(Param)=Char) as the type might not be assigned yet */
10892 0 : M2MetaError_MetaError1 ((const char *) "base procedure {%EkHIGH} expects a variable or string constant as its parameter {%1d:rather than {%1d}} {%1asa}", 111, Param);
10893 : }
10894 2978 : else if ((Type != SymbolTable_NulSym) && (SymbolTable_IsUnbounded (Type)))
10895 : {
10896 : /* avoid dangling else. */
10897 2744 : BuildHighFromUnbounded (combinedtok);
10898 : }
10899 : else
10900 : {
10901 : /* avoid dangling else. */
10902 234 : BuildConstHighFromSym (combinedtok);
10903 : }
10904 : }
10905 : else
10906 : {
10907 0 : M2MetaError_MetaError0 ((const char *) "base procedure {%EkHIGH} requires one parameter", 47);
10908 0 : M2Quads_PopN (2);
10909 0 : M2Quads_PushTFtok (SymbolTable_MakeConstLit (functok, NameKey_MakeKey ((const char *) "0", 1), M2Base_Cardinal), M2Base_Cardinal, functok);
10910 : }
10911 2978 : }
10912 :
10913 :
10914 : /*
10915 : BuildConstHighFromSym - builds the pseudo function HIGH from an Sym.
10916 : Sym is a constant or an array which has constant bounds
10917 : and therefore it can be calculated at compile time.
10918 :
10919 : The Stack:
10920 :
10921 :
10922 : Entry Exit
10923 :
10924 : Ptr ->
10925 : +----------------+
10926 : | NoOfParam |
10927 : |----------------|
10928 : | Param 1 |
10929 : |----------------|
10930 : | Param 2 |
10931 : |----------------|
10932 : . .
10933 : . .
10934 : . .
10935 : |----------------|
10936 : | Param # | <- Ptr
10937 : |----------------| +------------+
10938 : | ProcSym | Type | | ReturnVar |
10939 : |----------------| |------------|
10940 : */
10941 :
10942 234 : static void BuildConstHighFromSym (unsigned int tok)
10943 : {
10944 234 : unsigned int NoOfParam;
10945 234 : unsigned int ReturnVar;
10946 :
10947 234 : M2Quads_PopT (&NoOfParam);
10948 234 : ReturnVar = SymbolTable_MakeTemporary (tok, SymbolTable_ImmediateValue);
10949 234 : SymbolTable_PutConst (ReturnVar, M2Base_Cardinal);
10950 234 : GenHigh (tok, ReturnVar, 1, M2Quads_OperandT (1));
10951 234 : M2Quads_PopN (NoOfParam+1);
10952 234 : M2Quads_PushTtok (ReturnVar, tok);
10953 234 : }
10954 :
10955 :
10956 : /*
10957 : BuildHighFromUnbounded - builds the pseudo function HIGH from an
10958 : UnboundedSym.
10959 :
10960 : The Stack:
10961 :
10962 :
10963 : Entry Exit
10964 :
10965 : Ptr ->
10966 : +----------------+
10967 : | NoOfParam |
10968 : |----------------|
10969 : | Param # | <- Ptr
10970 : |----------------| +------------+
10971 : | ProcSym | Type | | ReturnVar |
10972 : |----------------| |------------|
10973 :
10974 : */
10975 :
10976 2744 : static void BuildHighFromUnbounded (unsigned int tok)
10977 : {
10978 2744 : unsigned int Dim;
10979 2744 : unsigned int NoOfParam;
10980 2744 : unsigned int ReturnVar;
10981 :
10982 2744 : M2Quads_PopT (&NoOfParam);
10983 2744 : M2Debug_Assert (NoOfParam == 1);
10984 2744 : ReturnVar = SymbolTable_MakeTemporary (tok, SymbolTable_RightValue);
10985 2744 : SymbolTable_PutVar (ReturnVar, M2Base_Cardinal);
10986 2744 : Dim = static_cast<unsigned int> (OperandD (1));
10987 2744 : Dim += 1;
10988 2744 : if (Dim > 1)
10989 : {
10990 36 : GenHigh (tok, ReturnVar, Dim, M2Quads_OperandA (1));
10991 : }
10992 : else
10993 : {
10994 2708 : GenHigh (tok, ReturnVar, Dim, M2Quads_OperandT (1));
10995 : }
10996 2744 : M2Quads_PopN (2);
10997 2744 : M2Quads_PushTFtok (ReturnVar, SymbolTable_GetSType (ReturnVar), tok);
10998 2744 : }
10999 :
11000 :
11001 : /*
11002 : GetQualidentImport - returns the symbol as if it were qualified from, module.n.
11003 : This is used to reference runtime support procedures and an
11004 : error is generated if the symbol cannot be obtained.
11005 : */
11006 :
11007 47459 : static unsigned int GetQualidentImport (unsigned int tokno, NameKey_Name n, NameKey_Name module)
11008 : {
11009 47459 : unsigned int sym;
11010 47459 : unsigned int ModSym;
11011 :
11012 47459 : ModSym = M2Batch_MakeDefinitionSource (tokno, module);
11013 47459 : if (ModSym == SymbolTable_NulSym)
11014 : {
11015 0 : M2MetaError_MetaErrorNT2 (tokno, (const char *) "module %a cannot be found and is needed to import %a", 52, module, n);
11016 0 : M2Error_FlushErrors ();
11017 0 : return SymbolTable_NulSym;
11018 : }
11019 47459 : M2Debug_Assert (SymbolTable_IsDefImp (ModSym));
11020 47459 : if (((SymbolTable_GetExported (tokno, ModSym, n)) == SymbolTable_NulSym) || (SymbolTable_IsUnknown (SymbolTable_GetExported (tokno, ModSym, n))))
11021 : {
11022 0 : sym = SymbolTable_GetExported (tokno, ModSym, n);
11023 0 : if (SymbolTable_IsUnknown (sym))
11024 : {
11025 : /* Spellcheck. */
11026 0 : M2MetaError_MetaErrorN2 ((const char *) "module %a does not export procedure %a which is a necessary component of the runtime system, hint check the path and library/language variant", 141, module, n);
11027 0 : M2MetaError_MetaErrorT1 (tokno, (const char *) "unknown symbol {%1&s}", 21, sym);
11028 0 : SymbolTable_UnknownReported (sym);
11029 : }
11030 : else
11031 : {
11032 0 : M2MetaError_MetaErrorN2 ((const char *) "module %a does not export procedure %a which is a necessary component of the runtime system, hint check the path and library/language variant", 141, module, n);
11033 : }
11034 0 : M2Error_FlushErrors ();
11035 0 : return SymbolTable_NulSym;
11036 : }
11037 47459 : return SymbolTable_GetExported (tokno, M2Batch_MakeDefinitionSource (tokno, module), n);
11038 : /* static analysis guarentees a RETURN statement will be used before here. */
11039 : __builtin_unreachable ();
11040 : }
11041 :
11042 :
11043 : /*
11044 : ConstExprError - return TRUE if a constant expression is being built and Var is a variable.
11045 : */
11046 :
11047 71945 : static bool ConstExprError (unsigned int Func, unsigned int Var, unsigned int optok, bool ConstExpr)
11048 : {
11049 71945 : if (ConstExpr && (SymbolTable_IsVar (Var)))
11050 : {
11051 108 : M2MetaError_MetaErrorT2 (optok, (const char *) "the procedure function {%1Ea} is being called from within a constant expression and therefore the parameter {%2a} must be a constant, seen a {%2dav} {%2&s}", 155, Func, Var);
11052 108 : return true;
11053 : }
11054 : else
11055 : {
11056 71837 : return false;
11057 : }
11058 : /* static analysis guarentees a RETURN statement will be used before here. */
11059 : __builtin_unreachable ();
11060 : }
11061 :
11062 :
11063 : /*
11064 : DeferMakeLengthConst - creates a constant which contains the length of string, sym.
11065 : */
11066 :
11067 66 : static unsigned int DeferMakeLengthConst (unsigned int tok, unsigned int sym)
11068 : {
11069 66 : unsigned int const_;
11070 :
11071 66 : const_ = SymbolTable_MakeTemporary (tok, SymbolTable_ImmediateValue);
11072 66 : SymbolTable_PutVar (const_, M2Base_ZType);
11073 132 : GenQuadO (tok, M2Quads_StringLengthOp, const_, 0, sym, false);
11074 66 : return const_;
11075 : /* static analysis guarentees a RETURN statement will be used before here. */
11076 : __builtin_unreachable ();
11077 : }
11078 :
11079 :
11080 : /*
11081 : BuildLengthFunction - builds the inline standard function LENGTH.
11082 :
11083 : The Stack:
11084 :
11085 :
11086 : Entry Exit
11087 :
11088 : Ptr ->
11089 : +----------------+
11090 : | NoOfParam |
11091 : |----------------|
11092 : | Param 1 | <- Ptr
11093 : |----------------| +------------+
11094 : | ProcSym | Type | | ReturnVar |
11095 : |----------------| |------------|
11096 :
11097 : */
11098 :
11099 346 : static void BuildLengthFunction (unsigned int Function, bool ConstExpr)
11100 : {
11101 346 : unsigned int combinedtok;
11102 346 : unsigned int paramtok;
11103 346 : unsigned int functok;
11104 346 : unsigned int ProcSym;
11105 346 : unsigned int Type;
11106 346 : unsigned int NoOfParam;
11107 346 : unsigned int Param;
11108 346 : unsigned int ReturnVar;
11109 :
11110 346 : M2Quads_PopT (&NoOfParam);
11111 346 : Param = static_cast<unsigned int> (M2Quads_OperandT (1));
11112 346 : paramtok = static_cast<unsigned int> (M2Quads_OperandTok (1));
11113 346 : functok = static_cast<unsigned int> (M2Quads_OperandTok (NoOfParam+1));
11114 : /* Restore stack to origional form. */
11115 346 : M2Quads_PushT (NoOfParam);
11116 346 : Type = SymbolTable_GetSType (Param); /* Get the type from the symbol, not the stack. */
11117 346 : if (NoOfParam != 1) /* Get the type from the symbol, not the stack. */
11118 : {
11119 0 : M2MetaError_MetaErrorT1 (functok, (const char *) "base procedure {%1EkLENGTH} expects 1 parameter, seen {%1n} parameters", 70, NoOfParam);
11120 : }
11121 346 : if (NoOfParam >= 1)
11122 : {
11123 346 : combinedtok = M2LexBuf_MakeVirtual2Tok (functok, paramtok);
11124 346 : if ((SymbolTable_IsConst (Param)) && ((SymbolTable_GetSType (Param)) == M2Base_Char))
11125 : {
11126 6 : M2Quads_PopT (&NoOfParam);
11127 6 : M2Quads_PopN (NoOfParam+1);
11128 6 : ReturnVar = SymbolTable_MakeConstLit (combinedtok, NameKey_MakeKey ((const char *) "1", 1), M2Base_Cardinal);
11129 6 : M2Quads_PushTtok (ReturnVar, combinedtok);
11130 : }
11131 340 : else if (SymbolTable_IsConstString (Param))
11132 : {
11133 : /* avoid dangling else. */
11134 48 : M2Quads_PopT (&NoOfParam);
11135 48 : ReturnVar = DeferMakeLengthConst (combinedtok, M2Quads_OperandT (1));
11136 48 : M2Quads_PopN (NoOfParam+1);
11137 48 : M2Quads_PushTtok (ReturnVar, combinedtok);
11138 : }
11139 : else
11140 : {
11141 : /* avoid dangling else. */
11142 292 : ProcSym = GetQualidentImport (functok, NameKey_MakeKey ((const char *) "Length", 6), NameKey_MakeKey ((const char *) "M2RTS", 5));
11143 292 : if ((ProcSym != SymbolTable_NulSym) && (SymbolTable_IsProcedure (ProcSym)))
11144 : {
11145 292 : M2Quads_PopT (&NoOfParam);
11146 292 : if (SymbolTable_IsConst (Param))
11147 : {
11148 : /* This can be folded in M2GenGCC. */
11149 0 : ReturnVar = SymbolTable_MakeTemporary (combinedtok, SymbolTable_ImmediateValue);
11150 0 : SymbolTable_PutVar (ReturnVar, M2Base_Cardinal);
11151 0 : GenQuad (M2Quads_StandardFunctionOp, ReturnVar, ProcSym, Param);
11152 0 : M2Quads_PopN (NoOfParam+1);
11153 0 : M2Quads_PushTtok (ReturnVar, combinedtok);
11154 : }
11155 292 : else if (ConstExprError (Function, Param, paramtok, ConstExpr))
11156 : {
11157 : /* avoid dangling else. */
11158 : /* Fake a result as we have detected and reported an error. */
11159 6 : M2Quads_PopN (NoOfParam+1);
11160 6 : ReturnVar = SymbolTable_MakeConstLit (combinedtok, NameKey_MakeKey ((const char *) "1", 1), M2Base_Cardinal);
11161 6 : M2Quads_PushTtok (ReturnVar, combinedtok);
11162 : }
11163 : else
11164 : {
11165 : /* avoid dangling else. */
11166 : /* We must resolve this at runtime or in the GCC optimizer. */
11167 286 : M2Quads_PopTF (&Param, &Type);
11168 286 : M2Quads_PopN (NoOfParam);
11169 286 : M2Quads_PushTtok (ProcSym, functok);
11170 286 : M2Quads_PushTFtok (Param, Type, paramtok);
11171 286 : M2Quads_PushT (NoOfParam);
11172 286 : BuildRealFunctionCall (functok, false);
11173 : }
11174 : }
11175 : else
11176 : {
11177 0 : M2Quads_PopT (&NoOfParam);
11178 0 : M2Quads_PopN (NoOfParam+1);
11179 0 : M2Quads_PushTtok (SymbolTable_MakeConstLit (combinedtok, NameKey_MakeKey ((const char *) "0", 1), M2Base_Cardinal), combinedtok);
11180 0 : M2MetaError_MetaErrorT0 (functok, (const char *) "no procedure Length found for substitution to the standard function {%1EkLENGTH} which is required to calculate non constant string lengths", 139);
11181 : }
11182 : }
11183 : }
11184 : else
11185 : {
11186 : /* NoOfParam is _very_ wrong, we flush all outstanding errors */
11187 0 : M2Error_FlushErrors ();
11188 : }
11189 346 : }
11190 :
11191 :
11192 : /*
11193 : BuildOddFunction - builds the pseudo procedure call ODD.
11194 : This procedure is actually a "macro" for
11195 : ORD(x) --> VAL(BOOLEAN, x MOD 2)
11196 : However we cannot push tokens back onto the input stack
11197 : because the compiler is currently building a function
11198 : call and expecting a ReturnVar on the stack.
11199 : Hence we manipulate the stack and call
11200 : BuildConvertFunction.
11201 :
11202 : The Stack:
11203 :
11204 :
11205 : Entry Exit
11206 :
11207 : Ptr ->
11208 : +----------------+
11209 : | NoOfParam |
11210 : |----------------|
11211 : | Param 1 |
11212 : |----------------|
11213 : | Param 2 |
11214 : |----------------|
11215 : . .
11216 : . .
11217 : . .
11218 : |----------------|
11219 : | Param # |
11220 : |----------------|
11221 : | ProcSym | Type | Empty
11222 : |----------------|
11223 : */
11224 :
11225 46 : static void BuildOddFunction (unsigned int ProcSym, bool ConstExpr)
11226 : {
11227 46 : unsigned int combinedtok;
11228 46 : unsigned int optok;
11229 46 : unsigned int functok;
11230 46 : unsigned int NoOfParam;
11231 46 : unsigned int Res;
11232 46 : unsigned int Var;
11233 :
11234 46 : M2Quads_PopT (&NoOfParam);
11235 46 : functok = static_cast<unsigned int> (M2Quads_OperandTok (NoOfParam+1));
11236 46 : if (NoOfParam == 1)
11237 : {
11238 46 : Var = static_cast<unsigned int> (M2Quads_OperandT (1));
11239 46 : optok = static_cast<unsigned int> (M2Quads_OperandTok (1));
11240 46 : combinedtok = M2LexBuf_MakeVirtualTok (functok, functok, optok);
11241 46 : if (ConstExprError (ProcSym, Var, optok, ConstExpr))
11242 : {
11243 : /* Nothing to do. */
11244 6 : M2Quads_PushTtok (M2Base_False, combinedtok);
11245 : }
11246 40 : else if ((SymbolTable_IsVar (Var)) || (SymbolTable_IsConst (Var)))
11247 : {
11248 : /* avoid dangling else. */
11249 40 : M2Quads_PopN (NoOfParam+1);
11250 : /* compute (x MOD 2) */
11251 40 : M2Quads_PushTFtok (Var, SymbolTable_GetSType (Var), optok);
11252 40 : M2Quads_PushT (M2Reserved_ModTok);
11253 40 : M2Quads_PushTFtok (SymbolTable_MakeConstLit (optok, NameKey_MakeKey ((const char *) "2", 1), M2Base_ZType), M2Base_ZType, optok);
11254 40 : M2Quads_BuildBinaryOp ();
11255 40 : M2Quads_PopT (&Res);
11256 : /* compute IF ...=0 */
11257 40 : M2Quads_PushTtok (Res, optok);
11258 40 : M2Quads_PushT (M2Reserved_EqualTok);
11259 40 : M2Quads_PushTFtok (SymbolTable_MakeConstLit (optok, NameKey_MakeKey ((const char *) "0", 1), M2Base_ZType), M2Base_ZType, optok);
11260 40 : M2Quads_BuildRelOp (combinedtok);
11261 40 : M2Quads_BuildThenIf ();
11262 40 : Res = SymbolTable_MakeTemporary (combinedtok, SymbolTable_RightValue);
11263 40 : SymbolTable_PutVar (Res, M2Base_Boolean);
11264 40 : M2Quads_PushTtok (Res, combinedtok);
11265 40 : M2Quads_PushTtok (M2Base_False, combinedtok);
11266 40 : M2Quads_BuildAssignment (combinedtok);
11267 40 : M2Quads_BuildElse ();
11268 40 : M2Quads_PushTtok (Res, combinedtok);
11269 40 : M2Quads_PushTtok (M2Base_True, combinedtok);
11270 40 : M2Quads_BuildAssignment (combinedtok);
11271 40 : M2Quads_BuildEndIf ();
11272 40 : M2Quads_PushTtok (Res, combinedtok);
11273 : }
11274 : else
11275 : {
11276 : /* avoid dangling else. */
11277 0 : M2MetaError_MetaErrorT1 (optok, (const char *) "the parameter to {%1EkODD} must be a variable or constant, seen {%1ad} {%1&s}", 77, Var);
11278 0 : M2Quads_PushTtok (M2Base_False, combinedtok);
11279 : }
11280 : }
11281 : else
11282 : {
11283 0 : M2MetaError_MetaErrorT1 (functok, (const char *) "the pseudo procedure {%E1kODD} only has one parameter, seen {%1n} parameters", 76, NoOfParam);
11284 0 : M2Quads_PushTtok (M2Base_False, functok);
11285 : }
11286 46 : }
11287 :
11288 :
11289 : /*
11290 : BuildAbsFunction - builds a call to the standard function ABS.
11291 :
11292 : We cannot implement it as a macro or inline an
11293 : IF THEN statement as the IF THEN ELSE requires
11294 : we write the value to the same variable (or constant)
11295 : twice. The macro implementation will fail as
11296 : the compiler maybe building a function
11297 : call and expecting a ReturnVar on the stack.
11298 : The only method to implement this is to pass it to the
11299 : gcc backend.
11300 :
11301 : The Stack:
11302 :
11303 :
11304 : Entry Exit
11305 :
11306 : Ptr ->
11307 : +----------------+
11308 : | NoOfParam |
11309 : |----------------|
11310 : | Param 1 |
11311 : |----------------|
11312 : | Param 2 |
11313 : |----------------|
11314 : . .
11315 : . .
11316 : . .
11317 : |----------------|
11318 : | Param # |
11319 : |----------------|
11320 : | ProcSym | Type | Empty
11321 : |----------------|
11322 : */
11323 :
11324 177 : static void BuildAbsFunction (unsigned int ProcSym, bool ConstExpr)
11325 : {
11326 177 : unsigned int vartok;
11327 177 : unsigned int functok;
11328 177 : unsigned int combinedtok;
11329 177 : unsigned int NoOfParam;
11330 177 : unsigned int Res;
11331 177 : unsigned int Var;
11332 :
11333 177 : M2Quads_PopT (&NoOfParam);
11334 177 : functok = static_cast<unsigned int> (M2Quads_OperandTok (NoOfParam+1));
11335 177 : if (NoOfParam == 1)
11336 : {
11337 177 : Var = static_cast<unsigned int> (M2Quads_OperandT (1));
11338 177 : vartok = static_cast<unsigned int> (M2Quads_OperandTok (1));
11339 177 : M2Quads_PopN (NoOfParam+1);
11340 177 : combinedtok = M2LexBuf_MakeVirtualTok (functok, functok, vartok);
11341 177 : if (ConstExprError (ProcSym, Var, vartok, ConstExpr))
11342 : {
11343 : /* Create fake result. */
11344 24 : Res = SymbolTable_MakeTemporary (combinedtok, AreConstant (SymbolTable_IsConst (Var)));
11345 12 : SymbolTable_PutVar (Res, SymbolTable_GetSType (Var));
11346 12 : M2Quads_PushTFtok (Res, SymbolTable_GetSType (Var), combinedtok);
11347 : }
11348 165 : else if ((SymbolTable_IsVar (Var)) || (SymbolTable_IsConst (Var)))
11349 : {
11350 : /* avoid dangling else. */
11351 316 : Res = SymbolTable_MakeTemporary (combinedtok, AreConstant (SymbolTable_IsConst (Var)));
11352 158 : SymbolTable_PutVar (Res, SymbolTable_GetSType (Var));
11353 316 : GenQuadO (combinedtok, M2Quads_StandardFunctionOp, Res, ProcSym, Var, false);
11354 158 : M2Quads_PushTFtok (Res, SymbolTable_GetSType (Var), combinedtok);
11355 : }
11356 : else
11357 : {
11358 : /* avoid dangling else. */
11359 7 : M2MetaError_MetaErrorT1 (vartok, (const char *) "the parameter to {%AkABS} must be a variable or constant, seen {%1ad} {%1&s}", 76, Var);
11360 : }
11361 : }
11362 : else
11363 : {
11364 0 : M2MetaError_MetaErrorT1 (functok, (const char *) "the pseudo procedure {%AkABS} only has one parameter, seen {%1n} parameters", 75, NoOfParam);
11365 : }
11366 170 : }
11367 :
11368 :
11369 : /*
11370 : BuildCapFunction - builds the pseudo procedure call CAP.
11371 : We generate a the following quad:
11372 :
11373 :
11374 : StandardFunctionOp ReturnVal Cap Param1
11375 :
11376 : The Stack:
11377 :
11378 :
11379 : Entry Exit
11380 :
11381 : Ptr ->
11382 : +----------------+
11383 : | NoOfParam = 1 |
11384 : |----------------|
11385 : | Param 1 |
11386 : |----------------| +-------------+
11387 : | ProcSym | Type | | ReturnVal |
11388 : |----------------| |-------------|
11389 : */
11390 :
11391 125 : static void BuildCapFunction (unsigned int ProcSym, bool ConstExpr)
11392 : {
11393 125 : unsigned int optok;
11394 125 : unsigned int functok;
11395 125 : unsigned int combinedtok;
11396 125 : unsigned int NoOfParam;
11397 125 : unsigned int Res;
11398 125 : unsigned int Var;
11399 :
11400 125 : M2Quads_PopT (&NoOfParam);
11401 125 : functok = static_cast<unsigned int> (M2Quads_OperandTok (NoOfParam+1));
11402 125 : if (NoOfParam == 1)
11403 : {
11404 125 : Var = static_cast<unsigned int> (M2Quads_OperandT (1));
11405 125 : optok = static_cast<unsigned int> (M2Quads_OperandTok (1));
11406 125 : M2Quads_PopN (NoOfParam+1);
11407 125 : if (ConstExprError (ProcSym, Var, optok, ConstExpr))
11408 : {
11409 : /* Create fake result. */
11410 12 : combinedtok = M2LexBuf_MakeVirtual2Tok (functok, optok);
11411 24 : Res = SymbolTable_MakeTemporary (combinedtok, AreConstant (SymbolTable_IsConst (Var)));
11412 12 : SymbolTable_PutVar (Res, M2Base_Char);
11413 12 : M2Quads_PushTFtok (Res, M2Base_Char, combinedtok);
11414 : }
11415 113 : else if ((SymbolTable_IsVar (Var)) || (SymbolTable_IsConst (Var)))
11416 : {
11417 : /* avoid dangling else. */
11418 112 : combinedtok = M2LexBuf_MakeVirtual2Tok (functok, optok);
11419 224 : Res = SymbolTable_MakeTemporary (combinedtok, AreConstant (SymbolTable_IsConst (Var)));
11420 112 : SymbolTable_PutVar (Res, M2Base_Char);
11421 224 : GenQuadO (combinedtok, M2Quads_StandardFunctionOp, Res, ProcSym, Var, false);
11422 112 : M2Quads_PushTFtok (Res, M2Base_Char, combinedtok);
11423 : }
11424 : else
11425 : {
11426 : /* avoid dangling else. */
11427 1 : M2MetaError_MetaErrorT1 (optok, (const char *) "the parameter to {%AkCAP} must be a variable or constant, seen {%1ad} {%1&s}", 76, Var);
11428 : }
11429 : }
11430 : else
11431 : {
11432 0 : M2MetaError_MetaErrorT1 (functok, (const char *) "the pseudo procedure {%AkCAP} only has one parameter, seen {%1n} parameters", 75, NoOfParam);
11433 : }
11434 124 : }
11435 :
11436 :
11437 : /*
11438 : BuildChrFunction - builds the pseudo procedure call CHR.
11439 : This procedure is actually a "macro" for
11440 : CHR(x) --> CONVERT(CHAR, x)
11441 : However we cannot push tokens back onto the input stack
11442 : because the compiler is currently building a function
11443 : call and expecting a ReturnVar on the stack.
11444 : Hence we manipulate the stack and call
11445 : BuildConvertFunction.
11446 :
11447 : The Stack:
11448 :
11449 :
11450 : Entry Exit
11451 :
11452 : Ptr ->
11453 : +----------------+
11454 : | NoOfParam |
11455 : |----------------|
11456 : | Param 1 |
11457 : |----------------|
11458 : | Param 2 |
11459 : |----------------|
11460 : . .
11461 : . .
11462 : . .
11463 : |----------------|
11464 : | Param # |
11465 : |----------------|
11466 : | ProcSym | Type | Empty
11467 : |----------------|
11468 : */
11469 :
11470 1024 : static void BuildChrFunction (unsigned int ProcSym, bool ConstExpr)
11471 : {
11472 1024 : unsigned int functok;
11473 1024 : unsigned int combinedtok;
11474 1024 : unsigned int optok;
11475 1024 : unsigned int ReturnVar;
11476 1024 : unsigned int NoOfParam;
11477 1024 : unsigned int Var;
11478 :
11479 1024 : M2Quads_PopT (&NoOfParam);
11480 1024 : functok = static_cast<unsigned int> (M2Quads_OperandTok (NoOfParam+1));
11481 1024 : if (NoOfParam == 1)
11482 : {
11483 1024 : Var = static_cast<unsigned int> (M2Quads_OperandT (1));
11484 1024 : optok = static_cast<unsigned int> (M2Quads_OperandTok (1));
11485 1024 : M2Quads_PopN (NoOfParam+1);
11486 1024 : if (ConstExprError (ProcSym, Var, optok, ConstExpr))
11487 : {
11488 : /* Generate fake result. */
11489 12 : combinedtok = M2LexBuf_MakeVirtual2Tok (functok, optok);
11490 24 : ReturnVar = SymbolTable_MakeTemporary (combinedtok, AreConstant (SymbolTable_IsConst (Var)));
11491 12 : SymbolTable_PutVar (ReturnVar, M2Base_Char);
11492 12 : M2Quads_PushTFtok (ReturnVar, M2Base_Char, combinedtok);
11493 : }
11494 1012 : else if ((SymbolTable_IsVar (Var)) || (SymbolTable_IsConst (Var)))
11495 : {
11496 : /* avoid dangling else. */
11497 : /*
11498 : Build macro: CONVERT( CHAR, Var )
11499 : */
11500 1011 : M2Quads_PushTFtok (M2Base_Convert, static_cast<unsigned int> (SymbolTable_NulSym), functok);
11501 1011 : M2Quads_PushTtok (M2Base_Char, functok);
11502 1011 : M2Quads_PushTtok (Var, optok);
11503 1011 : M2Quads_PushT (static_cast<unsigned int> (2)); /* Two parameters */
11504 1011 : BuildConvertFunction (M2Base_Convert, ConstExpr); /* Two parameters */
11505 : }
11506 : else
11507 : {
11508 : /* avoid dangling else. */
11509 1 : M2MetaError_MetaErrorT1 (optok, (const char *) "the parameter to {%AkCHR} must be a variable or constant, seen {%1ad} {%1&s}", 76, Var);
11510 : }
11511 : }
11512 : else
11513 : {
11514 0 : M2MetaError_MetaErrorT1 (functok, (const char *) "the pseudo procedure {%AkCHR} only has one parameter, seen {%1n} parameters", 75, NoOfParam);
11515 : }
11516 1023 : }
11517 :
11518 :
11519 : /*
11520 : BuildOrdFunction - builds the pseudo procedure call ORD.
11521 : This procedure is actually a "macro" for
11522 : ORD(x) --> CONVERT(GetSType(sym), x)
11523 : However we cannot push tokens back onto the input stack
11524 : because the compiler is currently building a function
11525 : call and expecting a ReturnVar on the stack.
11526 : Hence we manipulate the stack and call
11527 : BuildConvertFunction.
11528 :
11529 : The Stack:
11530 :
11531 :
11532 : Entry Exit
11533 :
11534 : Ptr ->
11535 : +----------------+
11536 : | NoOfParam |
11537 : |----------------|
11538 : | Param 1 |
11539 : |----------------|
11540 : | Param 2 |
11541 : |----------------|
11542 : . .
11543 : . .
11544 : . .
11545 : |----------------|
11546 : | Param # |
11547 : |----------------|
11548 : | ProcSym | Type | Empty
11549 : |----------------|
11550 : */
11551 :
11552 4724 : static void BuildOrdFunction (unsigned int Sym, bool ConstExpr)
11553 : {
11554 4724 : unsigned int combinedtok;
11555 4724 : unsigned int functok;
11556 4724 : unsigned int optok;
11557 4724 : unsigned int ReturnVar;
11558 4724 : unsigned int NoOfParam;
11559 4724 : unsigned int Type;
11560 4724 : unsigned int Var;
11561 :
11562 4724 : M2Quads_PopT (&NoOfParam);
11563 4724 : functok = static_cast<unsigned int> (M2Quads_OperandTok (NoOfParam+1));
11564 4724 : if (NoOfParam == 1)
11565 : {
11566 4724 : Var = static_cast<unsigned int> (M2Quads_OperandT (1));
11567 4724 : optok = static_cast<unsigned int> (M2Quads_OperandTok (1));
11568 4724 : M2Quads_PopN (NoOfParam+1);
11569 4724 : if (ConstExprError (Sym, Var, optok, ConstExpr))
11570 : {
11571 : /* Generate fake result. */
11572 12 : combinedtok = M2LexBuf_MakeVirtual2Tok (functok, optok);
11573 24 : ReturnVar = SymbolTable_MakeTemporary (combinedtok, AreConstant (SymbolTable_IsConst (Var)));
11574 12 : SymbolTable_PutVar (ReturnVar, M2Base_Cardinal);
11575 12 : M2Quads_PushTFtok (ReturnVar, M2Base_Cardinal, combinedtok);
11576 : }
11577 4712 : else if ((SymbolTable_IsVar (Var)) || (SymbolTable_IsConst (Var)))
11578 : {
11579 : /* avoid dangling else. */
11580 4712 : Type = SymbolTable_GetSType (Sym);
11581 : /*
11582 : Build macro: CONVERT( CARDINAL, Var )
11583 : */
11584 4712 : M2Quads_PushTFtok (M2Base_Convert, static_cast<unsigned int> (SymbolTable_NulSym), functok);
11585 4712 : M2Quads_PushTtok (Type, optok);
11586 4712 : M2Quads_PushTtok (Var, optok);
11587 4712 : M2Quads_PushT (static_cast<unsigned int> (2)); /* Two parameters */
11588 4712 : BuildConvertFunction (M2Base_Convert, ConstExpr); /* Two parameters */
11589 : }
11590 : else
11591 : {
11592 : /* avoid dangling else. */
11593 0 : M2MetaError_MetaErrorT2 (optok, (const char *) "the parameter to {%1Aa} must be a variable or constant, seen {%2ad} {%2&s}", 74, Sym, Var);
11594 : }
11595 : }
11596 : else
11597 : {
11598 0 : M2MetaError_MetaErrorT2 (functok, (const char *) "the pseudo procedure {%1Aa} only has one parameter, seen {%2n} parameters", 73, Sym, NoOfParam);
11599 : }
11600 4724 : }
11601 :
11602 :
11603 : /*
11604 : BuildIntFunction - builds the pseudo procedure call INT.
11605 : This procedure is actually a "macro" for
11606 : INT(x) --> CONVERT(INTEGER, x)
11607 : However we cannot push tokens back onto the input stack
11608 : because the compiler is currently building a function
11609 : call and expecting a ReturnVar on the stack.
11610 : Hence we manipulate the stack and call
11611 : BuildConvertFunction.
11612 :
11613 : The Stack:
11614 :
11615 :
11616 : Entry Exit
11617 :
11618 : Ptr ->
11619 : +----------------+
11620 : | NoOfParam |
11621 : |----------------|
11622 : | Param 1 |
11623 : |----------------|
11624 : | Param 2 |
11625 : |----------------|
11626 : . .
11627 : . .
11628 : . .
11629 : |----------------|
11630 : | Param # |
11631 : |----------------|
11632 : | ProcSym | Type | Empty
11633 : |----------------|
11634 : */
11635 :
11636 6 : static void BuildIntFunction (unsigned int Sym, bool ConstExpr)
11637 : {
11638 6 : unsigned int combinedtok;
11639 6 : unsigned int functok;
11640 6 : unsigned int optok;
11641 6 : unsigned int ReturnVar;
11642 6 : unsigned int NoOfParam;
11643 6 : unsigned int Type;
11644 6 : unsigned int Var;
11645 :
11646 6 : M2Quads_PopT (&NoOfParam);
11647 6 : functok = static_cast<unsigned int> (M2Quads_OperandTok (NoOfParam+1));
11648 6 : if (NoOfParam == 1)
11649 : {
11650 6 : Var = static_cast<unsigned int> (M2Quads_OperandT (1));
11651 6 : optok = static_cast<unsigned int> (M2Quads_OperandTok (1));
11652 6 : M2Quads_PopN (NoOfParam+1);
11653 6 : if (ConstExprError (Sym, Var, optok, ConstExpr))
11654 : {
11655 : /* Generate fake result. */
11656 6 : combinedtok = M2LexBuf_MakeVirtual2Tok (functok, optok);
11657 12 : ReturnVar = SymbolTable_MakeTemporary (combinedtok, AreConstant (SymbolTable_IsConst (Var)));
11658 6 : SymbolTable_PutVar (ReturnVar, M2Base_Integer);
11659 6 : M2Quads_PushTFtok (ReturnVar, M2Base_Integer, combinedtok);
11660 : }
11661 0 : else if ((SymbolTable_IsVar (Var)) || (SymbolTable_IsConst (Var)))
11662 : {
11663 : /* avoid dangling else. */
11664 0 : Type = SymbolTable_GetSType (Sym); /* return type of function */
11665 : /* Build macro: CONVERT( CARDINAL, Var ). */
11666 0 : M2Quads_PushTFtok (M2Base_Convert, static_cast<unsigned int> (SymbolTable_NulSym), functok);
11667 0 : M2Quads_PushTtok (Type, functok);
11668 0 : M2Quads_PushTtok (Var, optok);
11669 0 : M2Quads_PushT (static_cast<unsigned int> (2)); /* Two parameters */
11670 0 : BuildConvertFunction (M2Base_Convert, ConstExpr); /* Two parameters */
11671 : }
11672 : else
11673 : {
11674 : /* avoid dangling else. */
11675 0 : combinedtok = M2LexBuf_MakeVirtualTok (functok, optok, optok);
11676 0 : M2MetaError_MetaErrorT2 (optok, (const char *) "the parameter to {%1Ea} must be a variable or constant, seen {%2ad} {%2&s}", 74, Sym, Var);
11677 0 : M2Quads_PushTtok (combinedtok, SymbolTable_MakeConstLit (combinedtok, NameKey_MakeKey ((const char *) "0", 1), M2Base_ZType));
11678 : }
11679 : }
11680 : else
11681 : {
11682 0 : M2MetaError_MetaErrorT2 (functok, (const char *) "the pseudo procedure {%1Ea} only has one parameter, seen {%2n} parameters", 73, Sym, NoOfParam);
11683 0 : M2Quads_PushTtok (functok, SymbolTable_MakeConstLit (functok, NameKey_MakeKey ((const char *) "0", 1), M2Base_ZType));
11684 : }
11685 6 : }
11686 :
11687 :
11688 : /*
11689 : BuildMakeAdrFunction - builds the pseudo procedure call MAKEADR.
11690 :
11691 : The Stack:
11692 :
11693 :
11694 : Entry Exit
11695 :
11696 : Ptr ->
11697 : +----------------+
11698 : | NoOfParam |
11699 : |----------------|
11700 : | Param 1 |
11701 : |----------------|
11702 : | Param 2 |
11703 : |----------------|
11704 : . .
11705 : . .
11706 : . .
11707 : |----------------|
11708 : | Param # |
11709 : |----------------|
11710 : | ProcSym | Type | Empty
11711 : |----------------|
11712 : */
11713 :
11714 12 : static void BuildMakeAdrFunction (void)
11715 : {
11716 12 : unsigned int functok;
11717 12 : unsigned int starttok;
11718 12 : unsigned int endtok;
11719 12 : unsigned int resulttok;
11720 12 : bool AreConst;
11721 12 : unsigned int i;
11722 12 : unsigned int pi;
11723 12 : unsigned int NoOfParameters;
11724 12 : unsigned int ReturnVar;
11725 :
11726 12 : M2Quads_PopT (&NoOfParameters);
11727 12 : functok = static_cast<unsigned int> (M2Quads_OperandTok (NoOfParameters+1));
11728 12 : if (NoOfParameters > 0)
11729 : {
11730 12 : starttok = static_cast<unsigned int> (M2Quads_OperandTok (NoOfParameters+1)); /* ADR token. */
11731 12 : endtok = static_cast<unsigned int> (M2Quads_OperandTok (1)); /* last parameter. */
11732 24 : GenQuad (M2Quads_ParamOp, 0, M2System_MakeAdr, M2System_MakeAdr); /* last parameter. */
11733 12 : i = NoOfParameters;
11734 : /* stack index referencing stacked parameter, i */
11735 12 : pi = 1;
11736 24 : while (i > 0)
11737 : {
11738 12 : GenQuadO (M2Quads_OperandTok (pi), M2Quads_ParamOp, i, M2System_MakeAdr, M2Quads_OperandT (pi), true);
11739 12 : i -= 1;
11740 12 : pi += 1;
11741 : }
11742 : AreConst = true;
11743 : i = 1;
11744 24 : while (i <= NoOfParameters)
11745 : {
11746 12 : if (SymbolTable_IsVar (M2Quads_OperandT (i)))
11747 : {
11748 : AreConst = false;
11749 : }
11750 12 : else if (! (SymbolTable_IsConst (M2Quads_OperandT (i))))
11751 : {
11752 : /* avoid dangling else. */
11753 0 : M2MetaError_MetaError1 ((const char *) "problem in the {%1EN} argument for {%kMAKEADR}, all arguments to {%kMAKEADR} must be either variables or constants", 114, i);
11754 : }
11755 12 : i += 1;
11756 : }
11757 : /* ReturnVar - will have the type of the procedure */
11758 12 : resulttok = M2LexBuf_MakeVirtualTok (starttok, starttok, endtok);
11759 12 : ReturnVar = SymbolTable_MakeTemporary (resulttok, AreConstant (AreConst));
11760 12 : SymbolTable_PutVar (ReturnVar, SymbolTable_GetSType (M2System_MakeAdr));
11761 24 : GenQuadO (resulttok, M2Quads_FunctValueOp, ReturnVar, SymbolTable_NulSym, M2System_MakeAdr, true);
11762 12 : M2Quads_PopN (NoOfParameters+1);
11763 12 : M2Quads_PushTFtok (ReturnVar, SymbolTable_GetSType (M2System_MakeAdr), resulttok);
11764 : }
11765 : else
11766 : {
11767 0 : M2MetaError_MetaError1 ((const char *) "the pseudo procedure {%EkMAKEADR} requires at least one parameter, seen {%1n}", 77, NoOfParameters);
11768 0 : M2Quads_PopN (1);
11769 0 : M2Quads_PushTFtok (M2Base_Nil, SymbolTable_GetSType (M2System_MakeAdr), functok);
11770 : }
11771 12 : }
11772 :
11773 :
11774 : /*
11775 : BuildShiftFunction - builds the pseudo procedure call SHIFT.
11776 :
11777 : PROCEDURE SHIFT (val: <any type>;
11778 : num: INTEGER): <any type> ;
11779 :
11780 : "Returns a bit sequence obtained from val by
11781 : shifting up or down (left or right) by the
11782 : absolute value of num, introducing
11783 : zeros as necessary. The direction is down if
11784 : the sign of num is negative, otherwise the
11785 : direction is up."
11786 :
11787 : The Stack:
11788 :
11789 : Entry Exit
11790 :
11791 : Ptr ->
11792 : +----------------+
11793 : | NoOfParam |
11794 : |----------------|
11795 : | Param 1 |
11796 : |----------------|
11797 : | Param 2 | <- Ptr
11798 : |----------------| +------------+
11799 : | ProcSym | Type | | ReturnVar |
11800 : |----------------| |------------|
11801 : */
11802 :
11803 682 : static void BuildShiftFunction (void)
11804 : {
11805 682 : unsigned int combinedtok;
11806 682 : unsigned int paramtok;
11807 682 : unsigned int functok;
11808 682 : unsigned int vartok;
11809 682 : unsigned int exptok;
11810 682 : unsigned int r;
11811 682 : unsigned int procSym;
11812 682 : unsigned int returnVar;
11813 682 : unsigned int NoOfParam;
11814 682 : unsigned int derefExp;
11815 682 : unsigned int Exp;
11816 682 : unsigned int varSet;
11817 :
11818 682 : M2Quads_PopT (&NoOfParam);
11819 682 : paramtok = static_cast<unsigned int> (M2Quads_OperandTok (1));
11820 682 : functok = static_cast<unsigned int> (M2Quads_OperandTok (NoOfParam+1));
11821 682 : if (NoOfParam == 2)
11822 : {
11823 682 : PopTrwtok (&Exp, &r, &exptok);
11824 682 : MarkAsRead (r);
11825 682 : M2Quads_PopTtok (&varSet, &vartok);
11826 682 : M2Quads_PopT (&procSym);
11827 682 : combinedtok = M2LexBuf_MakeVirtualTok (functok, functok, exptok);
11828 682 : if (((SymbolTable_GetSType (varSet)) != SymbolTable_NulSym) && ((SymbolTable_IsSet (SymbolTable_GetDType (varSet))) || (M2System_IsGenericSystemType (SymbolTable_GetDType (varSet)))))
11829 : {
11830 682 : derefExp = DereferenceLValue (exptok, Exp);
11831 682 : BuildRange (M2Range_InitShiftCheck (varSet, derefExp));
11832 682 : returnVar = SymbolTable_MakeTemporary (combinedtok, SymbolTable_RightValue);
11833 682 : SymbolTable_PutVar (returnVar, SymbolTable_GetSType (varSet));
11834 1364 : GenQuadO (combinedtok, M2Quads_LogicalShiftOp, returnVar, varSet, derefExp, true);
11835 682 : M2Quads_PushTFtok (returnVar, SymbolTable_GetSType (varSet), combinedtok);
11836 : }
11837 : else
11838 : {
11839 0 : M2MetaError_MetaErrorT1 (vartok, (const char *) "SYSTEM procedure {%1EkSHIFT} expects a constant or variable which has a type of SET as its first parameter, seen {%1ad} {%1&s}", 126, varSet);
11840 0 : M2Quads_PushTFtok (SymbolTable_MakeConstLit (combinedtok, NameKey_MakeKey ((const char *) "0", 1), M2Base_Cardinal), M2Base_Cardinal, combinedtok);
11841 : }
11842 : }
11843 : else
11844 : {
11845 0 : combinedtok = M2LexBuf_MakeVirtualTok (functok, functok, paramtok);
11846 0 : M2MetaError_MetaErrorT1 (functok, (const char *) "the pseudo procedure {%kSHIFT} requires at least two parameters, seen {%1En}", 76, NoOfParam);
11847 0 : M2Quads_PopN (NoOfParam+1);
11848 0 : M2Quads_PushTFtok (SymbolTable_MakeConstLit (combinedtok, NameKey_MakeKey ((const char *) "0", 1), M2Base_Cardinal), M2Base_Cardinal, combinedtok);
11849 : }
11850 682 : }
11851 :
11852 :
11853 : /*
11854 : BuildRotateFunction - builds the pseudo procedure call ROTATE.
11855 :
11856 : PROCEDURE ROTATE (val: <any type>;
11857 : num: INTEGER): <any type> ;
11858 :
11859 : "Returns a bit sequence obtained from val
11860 : by rotating up or down (left or right) by
11861 : the absolute value of num. The direction is
11862 : down if the sign of num is negative, otherwise
11863 : the direction is up."
11864 :
11865 : The Stack:
11866 :
11867 : Entry Exit
11868 :
11869 : Ptr ->
11870 : +----------------+
11871 : | NoOfParam |
11872 : |----------------|
11873 : | Param 1 |
11874 : |----------------|
11875 : | Param 2 | <- Ptr
11876 : |----------------| +------------+
11877 : | ProcSym | Type | | ReturnVar |
11878 : |----------------| |------------|
11879 : */
11880 :
11881 406 : static void BuildRotateFunction (void)
11882 : {
11883 406 : unsigned int combinedtok;
11884 406 : unsigned int functok;
11885 406 : unsigned int vartok;
11886 406 : unsigned int exptok;
11887 406 : unsigned int r;
11888 406 : unsigned int procSym;
11889 406 : unsigned int returnVar;
11890 406 : unsigned int NoOfParam;
11891 406 : unsigned int derefExp;
11892 406 : unsigned int Exp;
11893 406 : unsigned int varSet;
11894 :
11895 406 : M2Quads_PopT (&NoOfParam);
11896 406 : functok = static_cast<unsigned int> (M2Quads_OperandTok (NoOfParam+1));
11897 406 : if (NoOfParam == 2)
11898 : {
11899 406 : PopTrwtok (&Exp, &r, &exptok);
11900 406 : MarkAsRead (r);
11901 406 : M2Quads_PopTtok (&varSet, &vartok);
11902 406 : M2Quads_PopT (&procSym);
11903 406 : if (((SymbolTable_GetSType (varSet)) != SymbolTable_NulSym) && ((SymbolTable_IsSet (SymbolTable_GetDType (varSet))) || (M2System_IsGenericSystemType (SymbolTable_GetDType (varSet)))))
11904 : {
11905 406 : combinedtok = M2LexBuf_MakeVirtualTok (functok, functok, exptok);
11906 406 : derefExp = DereferenceLValue (exptok, Exp);
11907 406 : BuildRange (M2Range_InitRotateCheck (varSet, derefExp));
11908 406 : returnVar = SymbolTable_MakeTemporary (combinedtok, SymbolTable_RightValue);
11909 406 : SymbolTable_PutVar (returnVar, SymbolTable_GetSType (varSet));
11910 812 : GenQuadO (combinedtok, M2Quads_LogicalRotateOp, returnVar, varSet, derefExp, true);
11911 406 : M2Quads_PushTFtok (returnVar, SymbolTable_GetSType (varSet), combinedtok);
11912 : }
11913 : else
11914 : {
11915 0 : M2MetaError_MetaErrorT1 (vartok, (const char *) "SYSTEM procedure {%EkROTATE} expects a constant or variable which has a type of SET as its first parameter, seen {%1ad} {%1&s}", 126, varSet);
11916 0 : M2Quads_PushTFtok (SymbolTable_MakeConstLit (functok, NameKey_MakeKey ((const char *) "0", 1), M2Base_Cardinal), M2Base_Cardinal, functok);
11917 : }
11918 : }
11919 : else
11920 : {
11921 0 : M2MetaError_MetaErrorT1 (functok, (const char *) "SYSTEM procedure {%EkROTATE} expects 2 parameters and was given {%1n} parameters", 80, NoOfParam);
11922 0 : M2Quads_PopN (NoOfParam+1);
11923 0 : M2Quads_PushTFtok (SymbolTable_MakeConstLit (functok, NameKey_MakeKey ((const char *) "0", 1), M2Base_Cardinal), M2Base_Cardinal, functok);
11924 : }
11925 406 : }
11926 :
11927 :
11928 : /*
11929 : BuildValFunction - builds the pseudo procedure call VAL.
11930 : This procedure is actually a "macro" for
11931 : VAL(Type, x) --> CONVERT(Type, x)
11932 : However we cannot push tokens back onto the input stack
11933 : because the compiler is currently building a function
11934 : call and expecting a ReturnVar on the stack.
11935 : Hence we manipulate the stack and call
11936 : BuildConvertFunction.
11937 :
11938 : The Stack:
11939 :
11940 :
11941 : Entry Exit
11942 :
11943 : Ptr ->
11944 : +----------------+
11945 : | NoOfParam |
11946 : |----------------|
11947 : | Param 1 |
11948 : |----------------|
11949 : | Param 2 |
11950 : |----------------|
11951 : . .
11952 : . .
11953 : . .
11954 : |----------------|
11955 : | Param # |
11956 : |----------------|
11957 : | ProcSym | Type | Empty
11958 : |----------------|
11959 : */
11960 :
11961 4920 : static void BuildValFunction (unsigned int ProcSym, bool ConstExpr)
11962 : {
11963 4920 : unsigned int combinedtok;
11964 4920 : unsigned int functok;
11965 4920 : unsigned int ReturnVar;
11966 4920 : unsigned int NoOfParam;
11967 4920 : unsigned int Exp;
11968 4920 : unsigned int Type;
11969 4920 : unsigned int tok;
11970 4920 : unsigned int r;
11971 4920 : unsigned int typetok;
11972 4920 : unsigned int exptok;
11973 :
11974 4920 : M2Quads_PopT (&NoOfParam);
11975 4920 : functok = static_cast<unsigned int> (M2Quads_OperandTok (NoOfParam+1));
11976 4920 : if (NoOfParam == 2)
11977 : {
11978 4920 : PopTrwtok (&Exp, &r, &exptok);
11979 4920 : MarkAsRead (r);
11980 4920 : M2Quads_PopTtok (&Type, &typetok);
11981 4920 : M2Quads_PopTtok (&ProcSym, &tok);
11982 4920 : if (SymbolTable_IsUnknown (Type))
11983 : {
11984 : /* It is sensible not to try and recover when we dont know the return type. */
11985 6 : M2MetaError_MetaErrorT1 (typetok, (const char *) "undeclared type found in builtin procedure function {%AkVAL} {%1ad} {%1&s}", 74, Type);
11986 : /* Non recoverable error. */
11987 0 : SymbolTable_UnknownReported (Type);
11988 : }
11989 4914 : else if (ConstExprError (ProcSym, Exp, exptok, ConstExpr))
11990 : {
11991 : /* avoid dangling else. */
11992 : /* Generate fake result. */
11993 6 : combinedtok = M2LexBuf_MakeVirtualTok (functok, functok, exptok);
11994 12 : ReturnVar = SymbolTable_MakeTemporary (combinedtok, AreConstant (SymbolTable_IsConst (Exp)));
11995 6 : SymbolTable_PutVar (ReturnVar, Type);
11996 6 : M2Quads_PushTFtok (ReturnVar, Type, combinedtok);
11997 : }
11998 4908 : else if (((((((SymbolTable_IsSet (Type)) || (SymbolTable_IsEnumeration (Type))) || (SymbolTable_IsSubrange (Type))) || (SymbolTable_IsType (Type))) || (SymbolTable_IsPointer (Type))) || (SymbolTable_IsProcType (Type))) && (((SymbolTable_IsVar (Exp)) || (SymbolTable_IsConst (Exp))) || (SymbolTable_IsProcedure (Exp))))
11999 : {
12000 : /* avoid dangling else. */
12001 : /*
12002 : Build macro: CONVERT( Type, Var )
12003 : */
12004 4908 : M2Quads_PushTFtok (M2Base_Convert, static_cast<unsigned int> (SymbolTable_NulSym), tok);
12005 4908 : M2Quads_PushTtok (Type, typetok);
12006 4908 : M2Quads_PushTtok (Exp, exptok);
12007 4908 : M2Quads_PushT (static_cast<unsigned int> (2)); /* Two parameters */
12008 4908 : BuildConvertFunction (M2Base_Convert, ConstExpr);
12009 : }
12010 : else
12011 : {
12012 : /* avoid dangling else. */
12013 : /* non recoverable error. */
12014 0 : M2MetaError_MetaErrorT0 (functok, (const char *) "the builtin procedure {%AkVAL} has the following formal parameter declaration {%kVAL} (type, expression)", 104);
12015 : }
12016 : }
12017 : else
12018 : {
12019 : /* non recoverable error. */
12020 0 : M2MetaError_MetaErrorT1 (functok, (const char *) "the builtin procedure {%AkVAL} expects 2 parameters, a type and an expression, but was given {%1n} parameters", 109, NoOfParam);
12021 : }
12022 4914 : }
12023 :
12024 :
12025 : /*
12026 : BuildCastFunction - builds the pseudo procedure call CAST.
12027 : This procedure is actually a "macro" for
12028 : CAST(Type, x) --> Type(x)
12029 : However we cannot push tokens back onto the input stack
12030 : because the compiler is currently building a function
12031 : call and expecting a ReturnVar on the stack.
12032 : Hence we manipulate the stack and call
12033 : BuildConvertFunction.
12034 :
12035 : The Stack:
12036 :
12037 :
12038 : Entry Exit
12039 :
12040 : Ptr ->
12041 : +----------------+
12042 : | NoOfParam |
12043 : |----------------|
12044 : | Param 1 |
12045 : |----------------|
12046 : | Param 2 |
12047 : |----------------|
12048 : . .
12049 : . .
12050 : . .
12051 : |----------------|
12052 : | Param # |
12053 : |----------------|
12054 : | ProcSym | Type | Empty
12055 : |----------------|
12056 : */
12057 :
12058 156 : static void BuildCastFunction (unsigned int ProcSym, bool ConstExpr)
12059 : {
12060 156 : unsigned int combinedtok;
12061 156 : unsigned int exptok;
12062 156 : unsigned int typetok;
12063 156 : unsigned int functok;
12064 156 : unsigned int ReturnVar;
12065 156 : unsigned int NoOfParam;
12066 156 : unsigned int Exp;
12067 156 : unsigned int Type;
12068 :
12069 156 : M2Quads_PopT (&NoOfParam);
12070 156 : functok = static_cast<unsigned int> (M2Quads_OperandTok (NoOfParam+1));
12071 156 : if (NoOfParam == 2)
12072 : {
12073 156 : Type = static_cast<unsigned int> (M2Quads_OperandT (2));
12074 156 : typetok = static_cast<unsigned int> (M2Quads_OperandTok (2));
12075 156 : Exp = static_cast<unsigned int> (M2Quads_OperandT (1));
12076 156 : exptok = static_cast<unsigned int> (M2Quads_OperandTok (1));
12077 156 : if (SymbolTable_IsUnknown (Type))
12078 : {
12079 : /* We cannot recover if we dont have a type. */
12080 0 : M2MetaError_MetaErrorT1 (typetok, (const char *) "undeclared type {%1Aad} found in {%kCAST} {%1&s}", 48, Type);
12081 : /* Non recoverable error. */
12082 0 : SymbolTable_UnknownReported (Type);
12083 : }
12084 156 : else if (ConstExprError (ProcSym, Exp, exptok, ConstExpr))
12085 : {
12086 : /* avoid dangling else. */
12087 : /* Generate fake result. */
12088 0 : combinedtok = M2LexBuf_MakeVirtualTok (functok, functok, exptok);
12089 0 : ReturnVar = SymbolTable_MakeTemporary (combinedtok, AreConstant (SymbolTable_IsConst (Exp)));
12090 0 : SymbolTable_PutVar (ReturnVar, Type);
12091 0 : M2Quads_PushTFtok (ReturnVar, Type, combinedtok);
12092 : }
12093 156 : else if (((((((SymbolTable_IsSet (Type)) || (SymbolTable_IsEnumeration (Type))) || (SymbolTable_IsSubrange (Type))) || (SymbolTable_IsType (Type))) || (SymbolTable_IsPointer (Type))) || (SymbolTable_IsArray (Type))) || (SymbolTable_IsProcType (Type)))
12094 : {
12095 : /* avoid dangling else. */
12096 156 : if (SymbolTable_IsConst (Exp))
12097 : {
12098 30 : M2Quads_PopN (NoOfParam+1);
12099 : /*
12100 : Build macro: Type( Var )
12101 : */
12102 30 : M2Quads_PushTFtok (Type, static_cast<unsigned int> (SymbolTable_NulSym), typetok);
12103 30 : M2Quads_PushTtok (Exp, exptok);
12104 30 : M2Quads_PushT (static_cast<unsigned int> (1)); /* one parameter */
12105 30 : BuildTypeCoercion (ConstExpr); /* one parameter */
12106 : }
12107 126 : else if ((SymbolTable_IsVar (Exp)) || (SymbolTable_IsProcedure (Exp)))
12108 : {
12109 : /* avoid dangling else. */
12110 126 : M2Quads_PopN (NoOfParam+1);
12111 126 : combinedtok = M2LexBuf_MakeVirtual2Tok (functok, exptok);
12112 126 : ReturnVar = SymbolTable_MakeTemporary (combinedtok, SymbolTable_RightValue);
12113 126 : SymbolTable_PutVar (ReturnVar, Type);
12114 252 : GenQuadO (combinedtok, M2Quads_CastOp, ReturnVar, Type, Exp, false);
12115 126 : M2Quads_PushTFtok (ReturnVar, Type, combinedtok);
12116 : }
12117 : else
12118 : {
12119 : /* avoid dangling else. */
12120 : /* non recoverable error. */
12121 0 : M2MetaError_MetaErrorT0 (functok, (const char *) "the second parameter to the builtin procedure {%AkCAST} must either be a variable, constant or a procedure. The formal parameters to cast are {%kCAST} (type, variable or constant or procedure)", 193);
12122 : }
12123 : }
12124 : else
12125 : {
12126 : /* avoid dangling else. */
12127 : /* non recoverable error. */
12128 0 : M2MetaError_MetaErrorT0 (functok, (const char *) "the builtin procedure {%AkCAST} has the following formal parameter declaration {%kCAST} (type, expression)", 106);
12129 : }
12130 : }
12131 : else
12132 : {
12133 : /* non recoverable error. */
12134 0 : M2MetaError_MetaErrorT1 (functok, (const char *) "the builtin procedure {%AkCAST} `expects 2 parameters, a type and an expression, but was given {%1n} parameters", 111, NoOfParam);
12135 : }
12136 156 : }
12137 :
12138 :
12139 : /*
12140 : BuildConvertFunction - builds the pseudo function CONVERT.
12141 : CONVERT( Type, Variable ) ;
12142 :
12143 : The Stack:
12144 :
12145 :
12146 : Entry Exit
12147 :
12148 : Ptr ->
12149 : +----------------+
12150 : | NoOfParam |
12151 : |----------------|
12152 : | Param 1 |
12153 : |----------------|
12154 : | Param 2 |
12155 : |----------------|
12156 : . .
12157 : . .
12158 : . .
12159 : |----------------|
12160 : | Param # | <- Ptr
12161 : |----------------| +---------------------+
12162 : | ProcSym | Type | | ReturnVar | Param1 |
12163 : |----------------| |---------------------|
12164 :
12165 : Quadruples:
12166 :
12167 : ConvertOp ReturnVar Param1 Param2
12168 :
12169 : Converts variable Param2 into a variable Param1
12170 : with a type Param1.
12171 : */
12172 :
12173 56535 : static void BuildConvertFunction (unsigned int ProcSym, bool ConstExpr)
12174 : {
12175 56535 : unsigned int combinedtok;
12176 56535 : unsigned int functok;
12177 56535 : unsigned int typetok;
12178 56535 : unsigned int exptok;
12179 56535 : unsigned int t;
12180 56535 : unsigned int r;
12181 56535 : unsigned int Exp;
12182 56535 : unsigned int Type;
12183 56535 : unsigned int NoOfParam;
12184 56535 : unsigned int ReturnVar;
12185 :
12186 56535 : M2Quads_PopT (&NoOfParam);
12187 56535 : functok = static_cast<unsigned int> (M2Quads_OperandTok (NoOfParam+1));
12188 56535 : if (NoOfParam == 2)
12189 : {
12190 56535 : PopTrwtok (&Exp, &r, &exptok);
12191 56535 : MarkAsRead (r);
12192 56535 : M2Quads_PopTtok (&Type, &typetok);
12193 56535 : M2Quads_PopT (&ProcSym);
12194 56535 : if (SymbolTable_IsUnknown (Type))
12195 : {
12196 : /* We cannot recover if we dont have a type. */
12197 0 : M2MetaError_MetaErrorT1 (typetok, (const char *) "undeclared type {%1Aad} found in {%kCONVERT} {%1&s}", 51, Type);
12198 : /* Non recoverable error. */
12199 0 : SymbolTable_UnknownReported (Type);
12200 : }
12201 56535 : else if (SymbolTable_IsUnknown (Exp))
12202 : {
12203 : /* avoid dangling else. */
12204 : /* We cannot recover if we dont have an expression. */
12205 0 : M2MetaError_MetaErrorT1 (typetok, (const char *) "unknown {%1Ad} {%1ad} found in {%kCONVERT} {%1&s}", 49, Exp);
12206 : /* Non recoverable error. */
12207 0 : SymbolTable_UnknownReported (Exp);
12208 : }
12209 56535 : else if (ConstExprError (ProcSym, Exp, exptok, ConstExpr))
12210 : {
12211 : /* avoid dangling else. */
12212 : /* Generate fake result. */
12213 0 : combinedtok = M2LexBuf_MakeVirtualTok (functok, functok, exptok);
12214 0 : ReturnVar = SymbolTable_MakeTemporary (combinedtok, AreConstant (SymbolTable_IsConst (Exp)));
12215 0 : SymbolTable_PutVar (ReturnVar, Type);
12216 0 : M2Quads_PushTFtok (ReturnVar, Type, combinedtok);
12217 : }
12218 56535 : else if ((((((((SymbolTable_IsSet (Type)) || (SymbolTable_IsEnumeration (Type))) || (SymbolTable_IsSubrange (Type))) || (SymbolTable_IsType (Type))) || (SymbolTable_IsPointer (Type))) || (SymbolTable_IsProcType (Type))) || (SymbolTable_IsRecord (Type))) && (((SymbolTable_IsVar (Exp)) || (SymbolTable_IsConst (Exp))) || (SymbolTable_IsProcedure (Exp))))
12219 : {
12220 : /* avoid dangling else. */
12221 : /* firstly dereference Var */
12222 56529 : if ((SymbolTable_GetMode (Exp)) == SymbolTable_LeftValue)
12223 : {
12224 0 : t = SymbolTable_MakeTemporary (exptok, SymbolTable_RightValue);
12225 0 : SymbolTable_PutVar (t, SymbolTable_GetSType (Exp));
12226 0 : CheckPointerThroughNil (exptok, Exp);
12227 0 : doIndrX (exptok, t, Exp);
12228 0 : Exp = t;
12229 : }
12230 56529 : combinedtok = M2LexBuf_MakeVirtualTok (functok, functok, exptok);
12231 113058 : ReturnVar = SymbolTable_MakeTemporary (combinedtok, AreConstant (SymbolTable_IsConst (Exp)));
12232 56529 : SymbolTable_PutVar (ReturnVar, Type);
12233 113058 : GenQuadO (combinedtok, M2Quads_ConvertOp, ReturnVar, Type, Exp, true);
12234 56529 : M2Quads_PushTFtok (ReturnVar, Type, combinedtok);
12235 : }
12236 : else
12237 : {
12238 : /* avoid dangling else. */
12239 : /* non recoverable error. */
12240 6 : M2MetaError_MetaErrorT0 (functok, (const char *) "the builtin procedure {%AkCONVERT} has the following formal parameter declaration {%kCONVERT} (type, expression)", 112);
12241 : }
12242 : }
12243 : else
12244 : {
12245 : /* non recoverable error. */
12246 0 : M2MetaError_MetaErrorT1 (functok, (const char *) "the builtin procedure {%AkCONVERT} expects 2 parameters, a type and an expression, but was given {%1n} parameters", 113, NoOfParam);
12247 : }
12248 56529 : }
12249 :
12250 :
12251 : /*
12252 : CheckBaseTypeValue - checks to see whether the value, min, really exists.
12253 : */
12254 :
12255 2026 : static unsigned int CheckBaseTypeValue (unsigned int tok, unsigned int type, unsigned int min, unsigned int func)
12256 : {
12257 2026 : if (((type == M2Base_Real) || (type == M2Base_LongReal)) || (type == M2Base_ShortReal))
12258 : {
12259 102 : SymbolTable_PushValue (min);
12260 102 : if (! (M2ALU_IsValueAndTreeKnown ()))
12261 : {
12262 0 : M2MetaError_MetaErrorT2 (tok, (const char *) "{%1Ead} ({%2ad}) cannot be calculated at compile time for the target architecture", 81, func, type);
12263 0 : return SymbolTable_MakeConstLit (tok, NameKey_MakeKey ((const char *) "1.0", 3), M2Base_RType);
12264 : }
12265 : }
12266 : return min;
12267 : /* static analysis guarentees a RETURN statement will be used before here. */
12268 : __builtin_unreachable ();
12269 : }
12270 :
12271 :
12272 : /*
12273 : GetTypeMin - returns the minimium value of type and generate an error
12274 : if this is unavailable.
12275 : */
12276 :
12277 1326 : static unsigned int GetTypeMin (unsigned int tok, unsigned int func, unsigned int type)
12278 : {
12279 1326 : unsigned int min;
12280 :
12281 1326 : min = GetTypeMinLower (tok, func, type);
12282 1326 : if (min == SymbolTable_NulSym)
12283 : {
12284 0 : M2MetaError_MetaErrorT1 (tok, (const char *) "unable to obtain the {%AkMIN} value for type {%1ad}", 51, type);
12285 : }
12286 1326 : return min;
12287 : /* static analysis guarentees a RETURN statement will be used before here. */
12288 : __builtin_unreachable ();
12289 : }
12290 :
12291 :
12292 : /*
12293 : GetTypeMinLower - obtain the maximum value for type.
12294 : */
12295 :
12296 1326 : static unsigned int GetTypeMinLower (unsigned int tok, unsigned int func, unsigned int type)
12297 : {
12298 1326 : unsigned int min;
12299 1326 : unsigned int max;
12300 :
12301 1326 : if (SymbolTable_IsSubrange (type))
12302 : {
12303 306 : min = SymbolTable_MakeTemporary (tok, SymbolTable_ImmediateValue);
12304 306 : SymbolTable_PutVar (min, type);
12305 612 : GenQuad (M2Quads_SubrangeLowOp, min, SymbolTable_NulSym, type);
12306 306 : return min;
12307 : }
12308 1020 : else if (SymbolTable_IsSet (SymbolTable_SkipType (type)))
12309 : {
12310 : /* avoid dangling else. */
12311 60 : return GetTypeMin (tok, func, SymbolTable_GetSType (SymbolTable_SkipType (type)));
12312 : }
12313 960 : else if ((M2Base_IsBaseType (type)) || (SymbolTable_IsEnumeration (type)))
12314 : {
12315 : /* avoid dangling else. */
12316 758 : M2Base_GetBaseTypeMinMax (type, &min, &max);
12317 758 : min = CheckBaseTypeValue (tok, type, min, func);
12318 758 : return min;
12319 : }
12320 202 : else if (M2System_IsSystemType (type))
12321 : {
12322 : /* avoid dangling else. */
12323 186 : M2System_GetSystemTypeMinMax (type, &min, &max);
12324 186 : return min;
12325 : }
12326 16 : else if ((SymbolTable_GetSType (type)) == SymbolTable_NulSym)
12327 : {
12328 : /* avoid dangling else. */
12329 : return SymbolTable_NulSym;
12330 : }
12331 : else
12332 : {
12333 : /* avoid dangling else. */
12334 16 : return GetTypeMin (tok, func, SymbolTable_GetSType (type));
12335 : }
12336 : /* static analysis guarentees a RETURN statement will be used before here. */
12337 : __builtin_unreachable ();
12338 : }
12339 :
12340 :
12341 : /*
12342 : GetTypeMax - returns the maximum value of type and generate an error
12343 : if this is unavailable.
12344 : */
12345 :
12346 2258 : static unsigned int GetTypeMax (unsigned int tok, unsigned int func, unsigned int type)
12347 : {
12348 2258 : unsigned int max;
12349 :
12350 2258 : max = GetTypeMaxLower (tok, func, type);
12351 2258 : if (max == SymbolTable_NulSym)
12352 : {
12353 0 : M2MetaError_MetaErrorT1 (tok, (const char *) "unable to obtain the {%AkMAX} value for type {%1ad}", 51, type);
12354 : }
12355 2258 : return max;
12356 : /* static analysis guarentees a RETURN statement will be used before here. */
12357 : __builtin_unreachable ();
12358 : }
12359 :
12360 :
12361 : /*
12362 : GetTypeMaxLower - obtain the maximum value for type.
12363 : */
12364 :
12365 2258 : static unsigned int GetTypeMaxLower (unsigned int tok, unsigned int func, unsigned int type)
12366 : {
12367 2258 : unsigned int min;
12368 2258 : unsigned int max;
12369 :
12370 2258 : if (SymbolTable_IsSubrange (type))
12371 : {
12372 562 : max = SymbolTable_MakeTemporary (tok, SymbolTable_ImmediateValue);
12373 562 : SymbolTable_PutVar (max, type);
12374 1124 : GenQuad (M2Quads_SubrangeHighOp, max, SymbolTable_NulSym, type);
12375 562 : return max;
12376 : }
12377 1696 : else if (SymbolTable_IsSet (SymbolTable_SkipType (type)))
12378 : {
12379 : /* avoid dangling else. */
12380 210 : return GetTypeMax (tok, func, SymbolTable_GetSType (SymbolTable_SkipType (type)));
12381 : }
12382 1486 : else if ((M2Base_IsBaseType (type)) || (SymbolTable_IsEnumeration (type)))
12383 : {
12384 : /* avoid dangling else. */
12385 1268 : M2Base_GetBaseTypeMinMax (type, &min, &max);
12386 1268 : min = CheckBaseTypeValue (tok, type, min, func);
12387 1268 : return max;
12388 : }
12389 218 : else if (M2System_IsSystemType (type))
12390 : {
12391 : /* avoid dangling else. */
12392 202 : M2System_GetSystemTypeMinMax (type, &min, &max);
12393 202 : return max;
12394 : }
12395 16 : else if ((SymbolTable_GetSType (type)) == SymbolTable_NulSym)
12396 : {
12397 : /* avoid dangling else. */
12398 : return SymbolTable_NulSym;
12399 : }
12400 : else
12401 : {
12402 : /* avoid dangling else. */
12403 16 : return GetTypeMax (tok, func, SymbolTable_GetSType (type));
12404 : }
12405 : /* static analysis guarentees a RETURN statement will be used before here. */
12406 : __builtin_unreachable ();
12407 : }
12408 :
12409 :
12410 : /*
12411 : BuildMinFunction - builds the pseudo function call Min.
12412 :
12413 : The Stack:
12414 :
12415 : Entry Exit
12416 :
12417 : Ptr ->
12418 : +----------------+
12419 : | NoOfParam=1 |
12420 : |----------------|
12421 : | Param 1 |
12422 : |----------------|
12423 : | ProcSym | Type | Empty
12424 : |----------------|
12425 : */
12426 :
12427 1250 : static void BuildMinFunction (void)
12428 : {
12429 1250 : unsigned int combinedtok;
12430 1250 : unsigned int functok;
12431 1250 : unsigned int vartok;
12432 1250 : unsigned int func;
12433 1250 : unsigned int min;
12434 1250 : unsigned int NoOfParam;
12435 1250 : unsigned int Var;
12436 :
12437 1250 : M2Quads_PopT (&NoOfParam);
12438 1250 : func = static_cast<unsigned int> (M2Quads_OperandT (NoOfParam+1));
12439 1250 : functok = OperandTtok (NoOfParam+1);
12440 1250 : if (NoOfParam == 1)
12441 : {
12442 1250 : Var = static_cast<unsigned int> (M2Quads_OperandT (1));
12443 1250 : vartok = static_cast<unsigned int> (M2Quads_OperandTok (1));
12444 1250 : M2Quads_PopN (NoOfParam+1); /* destroy arguments to this function */
12445 1250 : combinedtok = M2LexBuf_MakeVirtualTok (functok, functok, vartok); /* destroy arguments to this function */
12446 1250 : if (SymbolTable_IsAModula2Type (Var))
12447 : {
12448 1226 : min = GetTypeMin (vartok, func, Var);
12449 1226 : M2Quads_PushTFtok (min, SymbolTable_GetSType (min), combinedtok);
12450 : }
12451 24 : else if (SymbolTable_IsVar (Var))
12452 : {
12453 : /* avoid dangling else. */
12454 24 : min = GetTypeMin (vartok, func, SymbolTable_GetSType (Var));
12455 24 : M2Quads_PushTFtok (min, SymbolTable_GetSType (Var), combinedtok);
12456 : }
12457 : else
12458 : {
12459 : /* avoid dangling else. */
12460 : /* non recoverable error. */
12461 0 : M2MetaError_MetaErrorT1 (vartok, (const char *) "parameter to {%AkMIN} must be a type or a variable, seen {%1ad} {%1&s}", 70, Var);
12462 : }
12463 : }
12464 : else
12465 : {
12466 : /* non recoverable error. */
12467 0 : M2MetaError_MetaErrorT1 (functok, (const char *) "the pseudo builtin procedure function {%AkMIN} only has one parameter, seen {%1n}", 82, NoOfParam);
12468 : }
12469 1250 : }
12470 :
12471 :
12472 : /*
12473 : BuildMaxFunction - builds the pseudo function call Max.
12474 :
12475 : The Stack:
12476 :
12477 : Entry Exit
12478 :
12479 : Ptr ->
12480 : +----------------+
12481 : | NoOfParam=1 |
12482 : |----------------|
12483 : | Param 1 |
12484 : |----------------|
12485 : | ProcSym | Type | Empty
12486 : |----------------|
12487 : */
12488 :
12489 2032 : static void BuildMaxFunction (void)
12490 : {
12491 2032 : unsigned int combinedtok;
12492 2032 : unsigned int functok;
12493 2032 : unsigned int vartok;
12494 2032 : unsigned int func;
12495 2032 : unsigned int max;
12496 2032 : unsigned int NoOfParam;
12497 2032 : unsigned int Var;
12498 :
12499 2032 : M2Quads_PopT (&NoOfParam);
12500 2032 : func = static_cast<unsigned int> (M2Quads_OperandT (NoOfParam+1));
12501 2032 : functok = OperandTtok (NoOfParam+1);
12502 2032 : if (NoOfParam == 1)
12503 : {
12504 2032 : Var = static_cast<unsigned int> (M2Quads_OperandT (1));
12505 2032 : vartok = static_cast<unsigned int> (M2Quads_OperandTok (1));
12506 2032 : M2Quads_PopN (NoOfParam+1); /* destroy arguments to this function */
12507 2032 : combinedtok = M2LexBuf_MakeVirtualTok (functok, functok, vartok); /* destroy arguments to this function */
12508 2032 : if (SymbolTable_IsAModula2Type (Var))
12509 : {
12510 2032 : max = GetTypeMax (vartok, func, Var);
12511 2032 : M2Quads_PushTFtok (max, SymbolTable_GetSType (max), combinedtok);
12512 : }
12513 0 : else if (SymbolTable_IsVar (Var))
12514 : {
12515 : /* avoid dangling else. */
12516 0 : max = GetTypeMax (vartok, func, SymbolTable_GetSType (Var));
12517 0 : M2Quads_PushTFtok (max, SymbolTable_GetSType (Var), combinedtok);
12518 : }
12519 : else
12520 : {
12521 : /* avoid dangling else. */
12522 : /* non recoverable error. */
12523 0 : M2MetaError_MetaErrorT1 (vartok, (const char *) "parameter to {%AkMAX} must be a type or a variable, seen {%1ad} {%1&s}", 70, Var);
12524 : }
12525 : }
12526 : else
12527 : {
12528 : /* non recoverable error. */
12529 0 : M2MetaError_MetaErrorT1 (functok, (const char *) "the pseudo builtin procedure function {%AkMAX} only has one parameter, seen {%1n}", 81, NoOfParam);
12530 : }
12531 2032 : }
12532 :
12533 :
12534 : /*
12535 : BuildTruncFunction - builds the pseudo procedure call TRUNC.
12536 : This procedure is actually a "macro" for
12537 : TRUNC(x) --> CONVERT(INTEGER, x)
12538 : However we cannot push tokens back onto the input stack
12539 : because the compiler is currently building a function
12540 : call and expecting a ReturnVar on the stack.
12541 : Hence we manipulate the stack and call
12542 : BuildConvertFunction.
12543 :
12544 : The Stack:
12545 :
12546 :
12547 : Entry Exit
12548 :
12549 : Ptr ->
12550 : +----------------+
12551 : | NoOfParam |
12552 : |----------------|
12553 : | Param 1 |
12554 : |----------------|
12555 : | Param 2 |
12556 : |----------------|
12557 : . .
12558 : . .
12559 : . .
12560 : |----------------|
12561 : | Param # |
12562 : |----------------|
12563 : | ProcSym | Type | Empty
12564 : |----------------|
12565 : */
12566 :
12567 60 : static void BuildTruncFunction (unsigned int Sym, bool ConstExpr)
12568 : {
12569 60 : unsigned int combinedtok;
12570 60 : unsigned int vartok;
12571 60 : unsigned int functok;
12572 60 : unsigned int NoOfParam;
12573 60 : unsigned int ReturnVar;
12574 60 : unsigned int ProcSym;
12575 60 : unsigned int Type;
12576 60 : unsigned int Var;
12577 :
12578 60 : M2Quads_PopT (&NoOfParam);
12579 60 : M2Debug_Assert (M2Base_IsTrunc (M2Quads_OperandT (NoOfParam+1)));
12580 60 : functok = OperandTtok (NoOfParam+1);
12581 60 : if (NoOfParam == 1)
12582 : {
12583 60 : ProcSym = SymbolTable_RequestSym (functok, NameKey_MakeKey ((const char *) "CONVERT", 7));
12584 60 : if ((ProcSym != SymbolTable_NulSym) && (SymbolTable_IsProcedure (ProcSym)))
12585 : {
12586 60 : Var = static_cast<unsigned int> (M2Quads_OperandT (1));
12587 60 : vartok = OperandTtok (1);
12588 60 : Type = SymbolTable_GetSType (Sym);
12589 60 : M2Quads_PopN (NoOfParam+1); /* destroy arguments to this function */
12590 60 : if (ConstExprError (Sym, Var, vartok, ConstExpr))
12591 : {
12592 : /* Generate fake result. */
12593 6 : combinedtok = M2LexBuf_MakeVirtual2Tok (functok, vartok);
12594 12 : ReturnVar = SymbolTable_MakeTemporary (combinedtok, AreConstant (SymbolTable_IsConst (Var)));
12595 6 : SymbolTable_PutVar (ReturnVar, Type);
12596 6 : M2Quads_PushTFtok (ReturnVar, Type, combinedtok);
12597 : }
12598 54 : else if ((SymbolTable_IsVar (Var)) || (SymbolTable_IsConst (Var)))
12599 : {
12600 : /* avoid dangling else. */
12601 54 : if (M2Base_IsRealType (SymbolTable_GetSType (Var)))
12602 : {
12603 : /* build macro: CONVERT( INTEGER, Var ). */
12604 54 : M2Quads_PushTFtok (ProcSym, static_cast<unsigned int> (SymbolTable_NulSym), functok);
12605 54 : M2Quads_PushTtok (Type, functok);
12606 54 : M2Quads_PushTtok (Var, vartok);
12607 54 : M2Quads_PushT (static_cast<unsigned int> (2)); /* two parameters */
12608 54 : BuildConvertFunction (M2Base_Convert, ConstExpr); /* two parameters */
12609 : }
12610 : else
12611 : {
12612 0 : M2MetaError_MetaErrorT1 (functok, (const char *) "argument to {%1Ead} must be a float point type", 46, Sym);
12613 0 : M2Quads_PushTFtok (SymbolTable_MakeConstLit (functok, NameKey_MakeKey ((const char *) "0", 1), Type), Type, functok);
12614 : }
12615 : }
12616 : else
12617 : {
12618 : /* avoid dangling else. */
12619 0 : M2MetaError_MetaErrorT2 (vartok, (const char *) "argument to {%1Ead} must be a variable or constant, seen {%2ad} {%2&s}", 70, Sym, Var);
12620 0 : M2Quads_PushTFtok (SymbolTable_MakeConstLit (functok, NameKey_MakeKey ((const char *) "0", 1), Type), Type, functok);
12621 : }
12622 : }
12623 : else
12624 : {
12625 0 : M2Error_InternalError ((const char *) "CONVERT procedure not found for TRUNC substitution", 50);
12626 : }
12627 : }
12628 : else
12629 : {
12630 : /* non recoverable error. */
12631 0 : M2MetaError_MetaErrorT1 (functok, (const char *) "the pseudo builtin procedure function {%AkTRUNC} only has one parameter, seen {%1n}", 84, NoOfParam);
12632 : }
12633 60 : }
12634 :
12635 :
12636 : /*
12637 : BuildFloatFunction - builds the pseudo procedure call FLOAT.
12638 : This procedure is actually a "macro" for
12639 : FLOAT(x) --> CONVERT(REAL, x)
12640 : However we cannot push tokens back onto the input stack
12641 : because the compiler is currently building a function
12642 : call and expecting a ReturnVar on the stack.
12643 : Hence we manipulate the stack and call
12644 : BuildConvertFunction.
12645 :
12646 : The Stack:
12647 :
12648 :
12649 : Entry Exit
12650 :
12651 : Ptr ->
12652 : +----------------+
12653 : | NoOfParam |
12654 : |----------------|
12655 : | Param 1 |
12656 : |----------------|
12657 : | Param 2 |
12658 : |----------------|
12659 : . .
12660 : . .
12661 : . .
12662 : |----------------|
12663 : | Param # |
12664 : |----------------|
12665 : | ProcSym | Type | Empty
12666 : |----------------|
12667 : */
12668 :
12669 88 : static void BuildFloatFunction (unsigned int Sym, bool ConstExpr)
12670 : {
12671 88 : unsigned int combinedtok;
12672 88 : unsigned int vartok;
12673 88 : unsigned int functok;
12674 88 : unsigned int NoOfParam;
12675 88 : unsigned int ReturnVar;
12676 88 : unsigned int Type;
12677 88 : unsigned int Var;
12678 88 : unsigned int ProcSym;
12679 :
12680 88 : M2Quads_PopT (&NoOfParam);
12681 88 : functok = OperandTtok (NoOfParam+1);
12682 88 : Type = SymbolTable_GetSType (Sym);
12683 88 : if (NoOfParam == 1)
12684 : {
12685 88 : ProcSym = SymbolTable_RequestSym (functok, NameKey_MakeKey ((const char *) "CONVERT", 7));
12686 88 : if ((ProcSym != SymbolTable_NulSym) && (SymbolTable_IsProcedure (ProcSym)))
12687 : {
12688 88 : Var = static_cast<unsigned int> (M2Quads_OperandT (1));
12689 88 : vartok = OperandTtok (1);
12690 88 : M2Quads_PopN (NoOfParam+1); /* destroy arguments to this function. */
12691 88 : if (ConstExprError (Sym, Var, vartok, ConstExpr))
12692 : {
12693 : /* Generate fake result. */
12694 6 : combinedtok = M2LexBuf_MakeVirtual2Tok (functok, vartok);
12695 12 : ReturnVar = SymbolTable_MakeTemporary (combinedtok, AreConstant (SymbolTable_IsConst (Var)));
12696 6 : SymbolTable_PutVar (ReturnVar, Type);
12697 6 : M2Quads_PushTFtok (ReturnVar, Type, combinedtok);
12698 : }
12699 82 : else if ((SymbolTable_IsVar (Var)) || (SymbolTable_IsConst (Var)))
12700 : {
12701 : /* avoid dangling else. */
12702 : /* build macro: CONVERT (REAL, Var). */
12703 82 : M2Quads_PushTFtok (ProcSym, static_cast<unsigned int> (SymbolTable_NulSym), functok);
12704 82 : M2Quads_PushTtok (Type, functok);
12705 82 : M2Quads_PushTtok (Var, vartok);
12706 82 : M2Quads_PushT (static_cast<unsigned int> (2)); /* two parameters. */
12707 82 : BuildConvertFunction (ProcSym, ConstExpr); /* two parameters. */
12708 : }
12709 : else
12710 : {
12711 : /* avoid dangling else. */
12712 0 : M2MetaError_MetaErrorT1 (vartok, (const char *) "argument to {%1Ead} must be a variable or constant", 50, ProcSym);
12713 0 : M2Quads_PushTFtok (SymbolTable_MakeConstLit (functok, NameKey_MakeKey ((const char *) "0.0", 3), Type), Type, functok);
12714 : }
12715 : }
12716 : else
12717 : {
12718 0 : M2Error_InternalError ((const char *) "CONVERT procedure not found for FLOAT substitution", 50);
12719 : }
12720 : }
12721 : else
12722 : {
12723 0 : M2Quads_PopN (NoOfParam+1); /* destroy arguments to this function. */
12724 0 : M2MetaError_MetaErrorT1 (functok, (const char *) "the builtin procedure function {%1Ead} only has one parameter", 61, Sym); /* destroy arguments to this function. */
12725 0 : M2Quads_PushTFtok (SymbolTable_MakeConstLit (functok, NameKey_MakeKey ((const char *) "0.0", 3), Type), Type, functok);
12726 : }
12727 88 : }
12728 :
12729 :
12730 : /*
12731 : BuildReFunction - builds the pseudo procedure call RE.
12732 :
12733 : The Stack:
12734 :
12735 :
12736 : Entry Exit
12737 :
12738 : Ptr ->
12739 : +----------------+
12740 : | NoOfParam |
12741 : |----------------|
12742 : | Param 1 |
12743 : |----------------|
12744 : | Param 2 |
12745 : |----------------|
12746 : . .
12747 : . .
12748 : . .
12749 : |----------------|
12750 : | Param # |
12751 : |----------------|
12752 : | ProcSym | Type | Empty
12753 : |----------------|
12754 : */
12755 :
12756 60 : static void BuildReFunction (unsigned int Sym, bool ConstExpr)
12757 : {
12758 60 : unsigned int func;
12759 60 : unsigned int combinedtok;
12760 60 : unsigned int vartok;
12761 60 : unsigned int functok;
12762 60 : unsigned int NoOfParam;
12763 60 : unsigned int ReturnVar;
12764 60 : unsigned int Type;
12765 60 : unsigned int Var;
12766 :
12767 60 : M2Quads_PopT (&NoOfParam);
12768 60 : functok = OperandTtok (NoOfParam+1);
12769 60 : func = static_cast<unsigned int> (M2Quads_OperandT (NoOfParam+1));
12770 60 : if (NoOfParam == 1)
12771 : {
12772 60 : Var = static_cast<unsigned int> (M2Quads_OperandT (1));
12773 60 : vartok = static_cast<unsigned int> (M2Quads_OperandTok (1));
12774 60 : combinedtok = M2LexBuf_MakeVirtualTok (functok, functok, vartok);
12775 60 : Type = M2Base_ComplexToScalar (SymbolTable_GetDType (Var));
12776 60 : M2Quads_PopN (NoOfParam+1); /* destroy arguments to this function */
12777 60 : if (ConstExprError (Sym, Var, vartok, ConstExpr))
12778 : {
12779 : /* Generate fake result. */
12780 6 : combinedtok = M2LexBuf_MakeVirtual2Tok (functok, vartok);
12781 12 : ReturnVar = SymbolTable_MakeTemporary (combinedtok, AreConstant (SymbolTable_IsConst (Var)));
12782 6 : SymbolTable_PutVar (ReturnVar, Type);
12783 6 : M2Quads_PushTFtok (ReturnVar, Type, combinedtok);
12784 : }
12785 54 : else if ((SymbolTable_IsVar (Var)) || (SymbolTable_IsConst (Var)))
12786 : {
12787 : /* avoid dangling else. */
12788 108 : ReturnVar = SymbolTable_MakeTemporary (combinedtok, AreConstant (SymbolTable_IsConst (Var)));
12789 54 : SymbolTable_PutVar (ReturnVar, Type);
12790 108 : GenQuadO (combinedtok, M2Quads_StandardFunctionOp, ReturnVar, M2Base_Re, Var, false);
12791 54 : M2Quads_PushTFtok (ReturnVar, Type, combinedtok);
12792 : }
12793 : else
12794 : {
12795 : /* avoid dangling else. */
12796 0 : M2Quads_PushTFtok (SymbolTable_MakeConstLit (combinedtok, NameKey_MakeKey ((const char *) "1.0", 3), M2Base_RType), M2Base_RType, combinedtok);
12797 0 : M2MetaError_MetaErrorT2 (vartok, (const char *) "the parameter to the builtin procedure function {%1Ead} must be a constant or a variable, seen {%2ad} {%2&s}", 108, func, Var);
12798 : }
12799 : }
12800 : else
12801 : {
12802 0 : M2Quads_PopN (NoOfParam+1); /* destroy arguments to this function */
12803 0 : M2Quads_PushTFtok (SymbolTable_MakeConstLit (functok, NameKey_MakeKey ((const char *) "1.0", 3), M2Base_RType), M2Base_RType, functok); /* destroy arguments to this function */
12804 0 : M2MetaError_MetaErrorT2 (functok, (const char *) "the builtin procedure function {%1Ead} only has one parameter, seen {%2n}", 73, func, NoOfParam);
12805 : }
12806 60 : }
12807 :
12808 :
12809 : /*
12810 : BuildImFunction - builds the pseudo procedure call IM.
12811 :
12812 : The Stack:
12813 :
12814 :
12815 : Entry Exit
12816 :
12817 : Ptr ->
12818 : +----------------+
12819 : | NoOfParam |
12820 : |----------------|
12821 : | Param 1 |
12822 : |----------------|
12823 : | Param 2 |
12824 : |----------------|
12825 : . .
12826 : . .
12827 : . .
12828 : |----------------|
12829 : | Param # |
12830 : |----------------|
12831 : | ProcSym | Type | Empty
12832 : |----------------|
12833 : */
12834 :
12835 60 : static void BuildImFunction (unsigned int Sym, bool ConstExpr)
12836 : {
12837 60 : unsigned int func;
12838 60 : unsigned int combinedtok;
12839 60 : unsigned int vartok;
12840 60 : unsigned int functok;
12841 60 : unsigned int NoOfParam;
12842 60 : unsigned int ReturnVar;
12843 60 : unsigned int Type;
12844 60 : unsigned int Var;
12845 :
12846 60 : M2Quads_PopT (&NoOfParam);
12847 60 : functok = OperandTtok (NoOfParam+1);
12848 60 : func = static_cast<unsigned int> (M2Quads_OperandT (NoOfParam+1));
12849 60 : if (NoOfParam == 1)
12850 : {
12851 60 : Var = static_cast<unsigned int> (M2Quads_OperandT (1));
12852 60 : vartok = static_cast<unsigned int> (M2Quads_OperandTok (1));
12853 60 : Type = M2Base_ComplexToScalar (SymbolTable_GetDType (Var));
12854 60 : combinedtok = M2LexBuf_MakeVirtualTok (functok, functok, vartok);
12855 60 : M2Quads_PopN (NoOfParam+1); /* destroy arguments to this function */
12856 60 : if (ConstExprError (Sym, Var, vartok, ConstExpr))
12857 : {
12858 : /* Generate fake result. */
12859 6 : combinedtok = M2LexBuf_MakeVirtual2Tok (functok, vartok);
12860 12 : ReturnVar = SymbolTable_MakeTemporary (combinedtok, AreConstant (SymbolTable_IsConst (Var)));
12861 6 : SymbolTable_PutVar (ReturnVar, Type);
12862 6 : M2Quads_PushTFtok (ReturnVar, Type, combinedtok);
12863 : }
12864 54 : else if ((SymbolTable_IsVar (Var)) || (SymbolTable_IsConst (Var)))
12865 : {
12866 : /* avoid dangling else. */
12867 108 : ReturnVar = SymbolTable_MakeTemporary (combinedtok, AreConstant (SymbolTable_IsConst (Var)));
12868 54 : SymbolTable_PutVar (ReturnVar, M2Base_ComplexToScalar (SymbolTable_GetDType (Var)));
12869 108 : GenQuadO (combinedtok, M2Quads_StandardFunctionOp, ReturnVar, M2Base_Im, Var, false);
12870 54 : M2Quads_PushTFtok (ReturnVar, SymbolTable_GetSType (ReturnVar), combinedtok);
12871 : }
12872 : else
12873 : {
12874 : /* avoid dangling else. */
12875 0 : M2Quads_PushTFtok (SymbolTable_MakeConstLit (combinedtok, NameKey_MakeKey ((const char *) "1.0", 3), M2Base_RType), M2Base_RType, combinedtok);
12876 0 : M2MetaError_MetaErrorT2 (vartok, (const char *) "the parameter to the builtin procedure function {%1Ead} must be a constant or a variable, seen {%2ad} {%2&s}", 108, func, Var);
12877 : }
12878 : }
12879 : else
12880 : {
12881 0 : M2Quads_PopN (NoOfParam+1); /* destroy arguments to this function */
12882 0 : M2Quads_PushTFtok (SymbolTable_MakeConstLit (functok, NameKey_MakeKey ((const char *) "1.0", 3), M2Base_RType), M2Base_RType, functok); /* destroy arguments to this function */
12883 0 : M2MetaError_MetaErrorT2 (functok, (const char *) "the builtin procedure function {%1Ead} only has one parameter, seen {%2n}", 73, func, NoOfParam);
12884 : }
12885 60 : }
12886 :
12887 :
12888 : /*
12889 : BuildCmplxFunction - builds the pseudo procedure call CMPLX.
12890 :
12891 : The Stack:
12892 :
12893 :
12894 : Entry Exit
12895 :
12896 : Ptr ->
12897 : +----------------+
12898 : | NoOfParam |
12899 : |----------------|
12900 : | Param 1 |
12901 : |----------------|
12902 : | Param 2 |
12903 : |----------------|
12904 : . .
12905 : . .
12906 : . .
12907 : |----------------|
12908 : | Param # |
12909 : |----------------|
12910 : | ProcSym | Type | Empty
12911 : |----------------|
12912 : */
12913 :
12914 492 : static void BuildCmplxFunction (unsigned int func, bool ConstExpr)
12915 : {
12916 492 : bool failure;
12917 492 : unsigned int functok;
12918 492 : unsigned int rtok;
12919 492 : unsigned int ltok;
12920 492 : unsigned int combinedtok;
12921 492 : unsigned int NoOfParam;
12922 492 : unsigned int type;
12923 492 : unsigned int ReturnVar;
12924 492 : unsigned int l;
12925 492 : unsigned int r;
12926 :
12927 492 : M2Quads_PopT (&NoOfParam);
12928 492 : functok = OperandTtok (NoOfParam+1);
12929 492 : if (NoOfParam == 2)
12930 : {
12931 492 : l = static_cast<unsigned int> (M2Quads_OperandT (2));
12932 492 : ltok = OperandTtok (2);
12933 492 : r = static_cast<unsigned int> (M2Quads_OperandT (1));
12934 492 : rtok = OperandTtok (1);
12935 492 : combinedtok = M2LexBuf_MakeVirtual2Tok (functok, rtok);
12936 492 : M2Quads_PopN (NoOfParam+1); /* Destroy arguments to this function. */
12937 492 : type = M2Base_GetCmplxReturnType (SymbolTable_GetDType (l), SymbolTable_GetDType (r)); /* Destroy arguments to this function. */
12938 570 : ReturnVar = SymbolTable_MakeTemporary (combinedtok, AreConstant ((SymbolTable_IsConst (l)) && (SymbolTable_IsConst (r))));
12939 492 : SymbolTable_PutVar (ReturnVar, type);
12940 492 : failure = false;
12941 492 : if (ConstExprError (func, l, ltok, ConstExpr))
12942 : {
12943 : /* ConstExprError has generated an error message we will fall through
12944 : and check the right operand. */
12945 : failure = true;
12946 : }
12947 492 : if (ConstExprError (func, r, rtok, ConstExpr))
12948 : {
12949 : /* Right operand is in error as a variable. */
12950 : failure = true;
12951 : }
12952 486 : if (failure)
12953 : {
12954 : /* Generate a fake result if either operand was a variable (and we
12955 : are in a const expression). */
12956 6 : M2Quads_PushTFtok (ReturnVar, type, combinedtok);
12957 : }
12958 486 : else if (((SymbolTable_IsVar (l)) || (SymbolTable_IsConst (l))) && ((SymbolTable_IsVar (r)) || (SymbolTable_IsConst (r))))
12959 : {
12960 : /* avoid dangling else. */
12961 486 : M2Base_CheckExpressionCompatible (combinedtok, SymbolTable_GetSType (l), SymbolTable_GetSType (r));
12962 486 : GenQuadO (combinedtok, M2Quads_StandardFunctionOp, ReturnVar, M2Base_Cmplx, SymbolTable_Make2Tuple (l, r), true);
12963 486 : M2Quads_PushTFtok (ReturnVar, type, combinedtok);
12964 : }
12965 : else
12966 : {
12967 : /* avoid dangling else. */
12968 0 : if ((SymbolTable_IsVar (l)) || (SymbolTable_IsConst (l)))
12969 : {
12970 0 : M2MetaError_MetaErrorT2 (functok, (const char *) "the builtin procedure {%1Ead} requires two parameters, both must be variables or constants but the second parameter is {%2d}", 124, func, r);
12971 : }
12972 : else
12973 : {
12974 0 : M2MetaError_MetaErrorT2 (functok, (const char *) "the builtin procedure {%1Ead} requires two parameters, both must be variables or constants but the first parameter is {%2d}", 123, func, l);
12975 : }
12976 0 : M2Quads_PushTFtok (SymbolTable_MakeConstLit (combinedtok, NameKey_MakeKey ((const char *) "1.0", 3), M2Base_CType), M2Base_CType, combinedtok);
12977 : }
12978 : }
12979 : else
12980 : {
12981 0 : M2MetaError_MetaErrorT2 (functok, (const char *) "the builtin procedure {%1Ead} requires two parameters, seen {%2n}", 65, func, NoOfParam);
12982 0 : M2Quads_PopN (NoOfParam+1); /* destroy arguments to this function */
12983 0 : M2Quads_PushTFtok (SymbolTable_MakeConstLit (functok, NameKey_MakeKey ((const char *) "1.0", 3), M2Base_CType), M2Base_CType, functok); /* destroy arguments to this function */
12984 : }
12985 492 : }
12986 :
12987 :
12988 : /*
12989 : BuildAdrFunction - builds the pseudo function ADR
12990 : The Stack:
12991 :
12992 :
12993 : Entry Exit
12994 :
12995 : Ptr ->
12996 : +----------------+
12997 : | NoOfParam |
12998 : |----------------|
12999 : | Param 1 |
13000 : |----------------|
13001 : | Param 2 |
13002 : |----------------|
13003 : . .
13004 : . .
13005 : . .
13006 : |----------------|
13007 : | Param # | <- Ptr
13008 : |----------------| +------------+
13009 : | ProcSym | Type | | ReturnVar |
13010 : |----------------| |------------|
13011 :
13012 : */
13013 :
13014 180150 : static void BuildAdrFunction (void)
13015 : {
13016 180150 : unsigned int param;
13017 180150 : unsigned int paramTok;
13018 180150 : unsigned int combinedTok;
13019 180150 : unsigned int procTok;
13020 180150 : unsigned int t;
13021 180150 : unsigned int UnboundedSym;
13022 180150 : unsigned int Dim;
13023 180150 : unsigned int Field;
13024 180150 : unsigned int noOfParameters;
13025 180150 : unsigned int procSym;
13026 180150 : unsigned int returnVar;
13027 180150 : unsigned int Type;
13028 180150 : unsigned int rw;
13029 :
13030 180150 : M2Quads_DisplayStack ();
13031 180150 : M2Quads_PopT (&noOfParameters);
13032 180150 : procSym = static_cast<unsigned int> (M2Quads_OperandT (noOfParameters+1));
13033 180150 : procTok = static_cast<unsigned int> (M2Quads_OperandTok (noOfParameters+1)); /* token of procedure ADR. */
13034 180150 : paramTok = static_cast<unsigned int> (M2Quads_OperandTok (1)); /* last parameter. */
13035 180150 : param = static_cast<unsigned int> (M2Quads_OperandT (1)); /* last parameter. */
13036 180150 : combinedTok = M2LexBuf_MakeVirtualTok (procTok, procTok, static_cast<unsigned int> (M2Reserved_endtok));
13037 180150 : if (noOfParameters != 1)
13038 : {
13039 0 : M2MetaError_MetaErrorNT0 (combinedTok, (const char *) "SYSTEM procedure ADR expects 1 parameter", 40);
13040 0 : M2Quads_PopN (noOfParameters+1); /* destroy the arguments and function */
13041 0 : M2Quads_PushTF (M2Base_Nil, M2System_Address); /* destroy the arguments and function */
13042 : }
13043 180150 : else if (SymbolTable_IsConstString (param))
13044 : {
13045 : /* avoid dangling else. */
13046 172339 : returnVar = MakeLeftValue (combinedTok, param, SymbolTable_RightValue, SymbolTable_GetSType (procSym));
13047 172339 : M2Quads_PopN (noOfParameters+1); /* destroy the arguments and function */
13048 172339 : M2Quads_PushTFtok (returnVar, SymbolTable_GetSType (returnVar), combinedTok); /* destroy the arguments and function */
13049 : }
13050 7811 : else if ((! (SymbolTable_IsVar (param))) && (! (SymbolTable_IsProcedure (param))))
13051 : {
13052 : /* avoid dangling else. */
13053 1 : M2MetaError_MetaErrorT1 (paramTok, (const char *) "SYSTEM procedure ADR expects a variable, procedure or a constant string as its parameter, seen {%1Ed} {%1&s}", 108, param);
13054 1 : M2Quads_PopN (noOfParameters+1); /* destroy the arguments and function */
13055 1 : M2Quads_PushTFtok (M2Base_Nil, M2System_Address, combinedTok); /* destroy the arguments and function */
13056 : }
13057 7810 : else if (SymbolTable_IsProcedure (param))
13058 : {
13059 : /* avoid dangling else. */
13060 24 : returnVar = MakeLeftValue (combinedTok, param, SymbolTable_RightValue, SymbolTable_GetSType (procSym));
13061 24 : M2Quads_PopN (noOfParameters+1); /* destroy the arguments and function */
13062 24 : M2Quads_PushTFtok (returnVar, SymbolTable_GetSType (returnVar), combinedTok); /* destroy the arguments and function */
13063 : }
13064 : else
13065 : {
13066 : /* avoid dangling else. */
13067 7786 : Type = SymbolTable_GetSType (param);
13068 7786 : Dim = static_cast<unsigned int> (OperandD (1));
13069 7786 : MarkArrayWritten (param);
13070 7786 : MarkArrayWritten (M2Quads_OperandA (1));
13071 : /* if the operand is an unbounded which has not been indexed
13072 : then we will lookup its address from the unbounded record.
13073 : Otherwise we obtain the address of the operand.
13074 : */
13075 7786 : if ((SymbolTable_IsUnbounded (Type)) && (Dim == 0))
13076 : {
13077 : /* we will reference the address field of the unbounded structure */
13078 2370 : UnboundedSym = param;
13079 2370 : rw = static_cast<unsigned int> (OperandRW (1));
13080 2370 : PushTFrw (UnboundedSym, SymbolTable_GetSType (UnboundedSym), rw);
13081 2370 : Field = SymbolTable_GetUnboundedAddressOffset (SymbolTable_GetSType (UnboundedSym));
13082 2370 : M2Quads_PushTF (Field, SymbolTable_GetSType (Field));
13083 2370 : M2Quads_PushT (static_cast<unsigned int> (1));
13084 2370 : M2Quads_BuildDesignatorRecord (combinedTok);
13085 2370 : PopTrw (&returnVar, &rw);
13086 2370 : if ((SymbolTable_GetMode (returnVar)) == SymbolTable_LeftValue)
13087 : {
13088 0 : t = SymbolTable_MakeTemporary (combinedTok, SymbolTable_RightValue);
13089 0 : SymbolTable_PutVar (t, SymbolTable_GetSType (procSym));
13090 0 : doIndrX (combinedTok, t, returnVar);
13091 0 : returnVar = t;
13092 : }
13093 : else
13094 : {
13095 : /* we need to cast returnVar into ADDRESS */
13096 2370 : t = SymbolTable_MakeTemporary (combinedTok, SymbolTable_RightValue);
13097 2370 : SymbolTable_PutVar (t, SymbolTable_GetSType (procSym));
13098 2370 : GenQuadO (combinedTok, M2Quads_ConvertOp, t, SymbolTable_GetSType (procSym), returnVar, false);
13099 2370 : returnVar = t;
13100 : }
13101 : }
13102 : else
13103 : {
13104 5416 : returnVar = SymbolTable_MakeTemporary (combinedTok, SymbolTable_RightValue);
13105 5416 : SymbolTable_PutVar (returnVar, SymbolTable_GetSType (procSym));
13106 5416 : if ((SymbolTable_GetMode (param)) == SymbolTable_LeftValue)
13107 : {
13108 440 : SymbolTable_PutVar (returnVar, SymbolTable_GetSType (procSym));
13109 440 : GenQuadO (combinedTok, M2Quads_ConvertOp, returnVar, SymbolTable_GetSType (procSym), param, false);
13110 : }
13111 : else
13112 : {
13113 4976 : GenQuadO (combinedTok, M2Quads_AddrOp, returnVar, SymbolTable_NulSym, param, false);
13114 : }
13115 5416 : SymbolTable_PutWriteQuad (param, SymbolTable_GetMode (param), NextQuad-1);
13116 5416 : rw = static_cast<unsigned int> (OperandMergeRW (1));
13117 5416 : M2Debug_Assert (SymbolTable_IsLegal (rw));
13118 : }
13119 7786 : M2Quads_PopN (noOfParameters+1); /* destroy the arguments and function */
13120 7786 : PushTFrwtok (returnVar, SymbolTable_GetSType (returnVar), rw, combinedTok); /* destroy the arguments and function */
13121 : }
13122 180150 : }
13123 :
13124 :
13125 : /*
13126 : BuildSizeFunction - builds the pseudo function SIZE
13127 : The Stack:
13128 :
13129 :
13130 : Entry Exit
13131 :
13132 : Ptr ->
13133 : +----------------+
13134 : | NoOfParam |
13135 : |----------------|
13136 : | Param 1 |
13137 : |----------------|
13138 : | Param 2 |
13139 : |----------------|
13140 : . .
13141 : . .
13142 : . .
13143 : |----------------|
13144 : | Param # | <- Ptr
13145 : |----------------| +------------+
13146 : | ProcSym | Type | | ReturnVar |
13147 : |----------------| |------------|
13148 : */
13149 :
13150 2099 : static void BuildSizeFunction (void)
13151 : {
13152 2099 : unsigned int resulttok;
13153 2099 : unsigned int paramtok;
13154 2099 : unsigned int functok;
13155 2099 : unsigned int dim;
13156 2099 : unsigned int Type;
13157 2099 : unsigned int NoOfParam;
13158 2099 : unsigned int ProcSym;
13159 2099 : unsigned int ReturnVar;
13160 :
13161 2099 : M2Quads_PopT (&NoOfParam);
13162 2099 : ProcSym = static_cast<unsigned int> (M2Quads_OperandT (NoOfParam+1));
13163 2099 : functok = OperandTtok (NoOfParam+1);
13164 2099 : if (NoOfParam != 1)
13165 : {
13166 0 : M2MetaError_MetaErrorT1 (functok, (const char *) "{%E} SYSTEM procedure function {%kSIZE} requires one parameter, seen {%1n}", 74, NoOfParam);
13167 0 : resulttok = functok;
13168 0 : ReturnVar = SymbolTable_MakeConstLit (resulttok, NameKey_MakeKey ((const char *) "0", 1), M2Base_Cardinal);
13169 : }
13170 : else
13171 : {
13172 2099 : paramtok = static_cast<unsigned int> (M2Quads_OperandTok (1));
13173 2099 : resulttok = M2LexBuf_MakeVirtualTok (functok, functok, paramtok);
13174 2099 : if (SymbolTable_IsAModula2Type (M2Quads_OperandT (1)))
13175 : {
13176 992 : BuildSizeCheckEnd (ProcSym); /* Quadruple generation now on. */
13177 992 : ReturnVar = SymbolTable_MakeTemporary (resulttok, SymbolTable_ImmediateValue); /* Quadruple generation now on. */
13178 992 : GenQuadO (resulttok, M2Quads_SizeOp, ReturnVar, SymbolTable_NulSym, M2Quads_OperandT (1), true);
13179 : }
13180 1107 : else if (SymbolTable_IsVar (M2Quads_OperandT (1)))
13181 : {
13182 : /* avoid dangling else. */
13183 1100 : BuildSizeCheckEnd (ProcSym); /* Quadruple generation now on. */
13184 1100 : Type = SymbolTable_GetSType (M2Quads_OperandT (1)); /* Quadruple generation now on. */
13185 1100 : if (SymbolTable_IsUnbounded (Type))
13186 : {
13187 : /* Eg. SIZE(a) ; where a is unbounded dereference HIGH and multiply by the TYPE. */
13188 168 : dim = static_cast<unsigned int> (OperandD (1));
13189 168 : if (dim == 0)
13190 : {
13191 72 : ReturnVar = calculateMultipicand (resulttok, M2Quads_OperandT (1), Type, dim);
13192 : }
13193 : else
13194 : {
13195 96 : ReturnVar = calculateMultipicand (resulttok, M2Quads_OperandA (1), Type, dim);
13196 : }
13197 : }
13198 : else
13199 : {
13200 932 : ReturnVar = SymbolTable_MakeTemporary (resulttok, SymbolTable_ImmediateValue);
13201 932 : if (Type == SymbolTable_NulSym)
13202 : {
13203 0 : M2MetaError_MetaErrorT1 (resulttok, (const char *) "cannot get the type and size of {%1Ead}", 39, M2Quads_OperandT (1));
13204 : }
13205 932 : GenQuadO (resulttok, M2Quads_SizeOp, ReturnVar, SymbolTable_NulSym, Type, true);
13206 : }
13207 : }
13208 : else
13209 : {
13210 : /* avoid dangling else. */
13211 7 : M2MetaError_MetaErrorT1 (paramtok, (const char *) "{%E}SYSTEM procedure {%kSIZE} expects a variable or type as its parameter, seen {%1Ed} {%1&s}", 93, M2Quads_OperandT (1));
13212 7 : ReturnVar = SymbolTable_MakeConstLit (paramtok, NameKey_MakeKey ((const char *) "0", 1), M2Base_Cardinal);
13213 : }
13214 : }
13215 2099 : M2Quads_PopN (NoOfParam+1); /* Destroy the arguments and function. */
13216 2099 : M2Quads_PushTFtok (ReturnVar, SymbolTable_GetSType (ProcSym), resulttok); /* Destroy the arguments and function. */
13217 2099 : }
13218 :
13219 :
13220 : /*
13221 : BuildTSizeFunction - builds the pseudo function TSIZE
13222 : The Stack:
13223 :
13224 :
13225 : Entry Exit
13226 :
13227 : Ptr ->
13228 : +----------------+
13229 : | NoOfParam |
13230 : |----------------|
13231 : | Param 1 |
13232 : |----------------|
13233 : | Param 2 |
13234 : |----------------|
13235 : . .
13236 : . .
13237 : . .
13238 : |----------------|
13239 : | Param # | <- Ptr
13240 : |----------------| +------------+
13241 : | ProcSym | Type | | ReturnVar |
13242 : |----------------| |------------|
13243 :
13244 : */
13245 :
13246 4774 : static void BuildTSizeFunction (void)
13247 : {
13248 4774 : unsigned int resulttok;
13249 4774 : unsigned int paramtok;
13250 4774 : unsigned int functok;
13251 4774 : unsigned int NoOfParam;
13252 4774 : unsigned int ProcSym;
13253 4774 : unsigned int Record;
13254 4774 : unsigned int ReturnVar;
13255 :
13256 4774 : M2Quads_PopT (&NoOfParam);
13257 4774 : ProcSym = static_cast<unsigned int> (M2Quads_OperandT (NoOfParam+1));
13258 4774 : functok = OperandTtok (NoOfParam);
13259 4774 : BuildSizeCheckEnd (ProcSym); /* quadruple generation now on */
13260 4774 : if (NoOfParam == 1) /* quadruple generation now on */
13261 : {
13262 4774 : paramtok = OperandTtok (1);
13263 4774 : resulttok = M2LexBuf_MakeVirtualTok (functok, functok, paramtok);
13264 4774 : if (SymbolTable_IsAModula2Type (M2Quads_OperandT (1)))
13265 : {
13266 4740 : ReturnVar = SymbolTable_MakeTemporary (resulttok, SymbolTable_ImmediateValue);
13267 4740 : SymbolTable_PutVar (ReturnVar, M2Base_Cardinal);
13268 4740 : GenQuadO (resulttok, M2Quads_SizeOp, ReturnVar, SymbolTable_NulSym, M2Quads_OperandT (1), false);
13269 : }
13270 34 : else if (SymbolTable_IsVar (M2Quads_OperandT (1)))
13271 : {
13272 : /* avoid dangling else. */
13273 28 : ReturnVar = SymbolTable_MakeTemporary (resulttok, SymbolTable_ImmediateValue);
13274 28 : SymbolTable_PutVar (ReturnVar, M2Base_Cardinal);
13275 28 : GenQuadO (resulttok, M2Quads_SizeOp, ReturnVar, SymbolTable_NulSym, SymbolTable_GetSType (M2Quads_OperandT (1)), false);
13276 : }
13277 : else
13278 : {
13279 : /* avoid dangling else. */
13280 : /* Spellcheck. */
13281 6 : M2MetaError_MetaErrorT1 (resulttok, (const char *) "{%E}SYSTEM procedure function {%kTSIZE} expects a variable or type as its first parameter, seen {%1Ed} {%1&s}", 109, M2Quads_OperandT (1));
13282 6 : ReturnVar = SymbolTable_MakeConstLit (resulttok, NameKey_MakeKey ((const char *) "0", 1), M2Base_Cardinal);
13283 : }
13284 : }
13285 0 : else if (NoOfParam == 0)
13286 : {
13287 : /* avoid dangling else. */
13288 0 : resulttok = functok;
13289 0 : M2MetaError_MetaErrorT0 (resulttok, (const char *) "{%E}SYSTEM procedure function {%kTSIZE} expects either one or two parameters, seen none", 87);
13290 0 : ReturnVar = SymbolTable_MakeConstLit (resulttok, NameKey_MakeKey ((const char *) "0", 1), M2Base_Cardinal);
13291 : }
13292 : else
13293 : {
13294 : /* avoid dangling else. */
13295 0 : Record = static_cast<unsigned int> (M2Quads_OperandT (NoOfParam));
13296 0 : paramtok = OperandTtok (1);
13297 0 : resulttok = OperandTtok (NoOfParam);
13298 0 : if (SymbolTable_IsRecord (Record))
13299 : {
13300 0 : paramtok = OperandTtok (1);
13301 0 : resulttok = M2LexBuf_MakeVirtualTok (functok, functok, paramtok);
13302 0 : ReturnVar = SymbolTable_MakeTemporary (resulttok, SymbolTable_ImmediateValue);
13303 0 : SymbolTable_PutVar (ReturnVar, M2Base_Cardinal);
13304 0 : GenQuadO (resulttok, M2Quads_SizeOp, ReturnVar, SymbolTable_NulSym, Record, false);
13305 : }
13306 : else
13307 : {
13308 0 : resulttok = M2LexBuf_MakeVirtualTok (functok, functok, paramtok);
13309 0 : M2MetaError_MetaErrorT1 (resulttok, (const char *) "{%E}SYSTEM procedure function {%kTSIZE} expects the first parameter to be a record type, seen {%1d} {%1&s}", 106, Record);
13310 0 : ReturnVar = SymbolTable_MakeConstLit (resulttok, NameKey_MakeKey ((const char *) "0", 1), M2Base_Cardinal);
13311 : }
13312 : }
13313 4774 : M2Quads_PopN (NoOfParam+1); /* destroy the arguments and function */
13314 4774 : M2Quads_PushTFtok (ReturnVar, SymbolTable_GetSType (ProcSym), resulttok); /* destroy the arguments and function */
13315 4774 : }
13316 :
13317 :
13318 : /*
13319 : BuildTBitSizeFunction - builds the pseudo function TBITSIZE
13320 : The Stack:
13321 :
13322 :
13323 : Entry Exit
13324 :
13325 : Ptr ->
13326 : +----------------+
13327 : | NoOfParam |
13328 : |----------------|
13329 : | Param 1 |
13330 : |----------------|
13331 : | Param 2 |
13332 : |----------------|
13333 : . .
13334 : . .
13335 : . .
13336 : |----------------|
13337 : | Param # | <- Ptr
13338 : |----------------| +------------+
13339 : | ProcSym | Type | | ReturnVar |
13340 : |----------------| |------------|
13341 :
13342 : */
13343 :
13344 6496 : static void BuildTBitSizeFunction (void)
13345 : {
13346 6496 : unsigned int resulttok;
13347 6496 : unsigned int paramtok;
13348 6496 : unsigned int functok;
13349 6496 : unsigned int NoOfParam;
13350 6496 : unsigned int ProcSym;
13351 6496 : unsigned int Record;
13352 6496 : unsigned int ReturnVar;
13353 :
13354 6496 : M2Quads_PopT (&NoOfParam);
13355 6496 : ProcSym = static_cast<unsigned int> (M2Quads_OperandT (NoOfParam+1));
13356 6496 : functok = OperandTtok (NoOfParam);
13357 6496 : BuildSizeCheckEnd (ProcSym); /* quadruple generation now on */
13358 6496 : if (NoOfParam == 1) /* quadruple generation now on */
13359 : {
13360 6496 : paramtok = OperandTtok (1);
13361 6496 : resulttok = M2LexBuf_MakeVirtualTok (functok, functok, paramtok);
13362 6496 : if (SymbolTable_IsAModula2Type (M2Quads_OperandT (1)))
13363 : {
13364 6424 : ReturnVar = SymbolTable_MakeTemporary (resulttok, SymbolTable_ImmediateValue);
13365 6424 : GenQuadO (resulttok, M2Quads_StandardFunctionOp, ReturnVar, ProcSym, M2Quads_OperandT (1), false);
13366 : }
13367 72 : else if (SymbolTable_IsVar (M2Quads_OperandT (1)))
13368 : {
13369 : /* avoid dangling else. */
13370 72 : ReturnVar = SymbolTable_MakeTemporary (resulttok, SymbolTable_ImmediateValue);
13371 72 : GenQuadO (resulttok, M2Quads_StandardFunctionOp, ReturnVar, ProcSym, M2Quads_OperandT (1), false);
13372 : }
13373 : else
13374 : {
13375 : /* avoid dangling else. */
13376 0 : M2MetaError_MetaErrorT1 (resulttok, (const char *) "{%E}SYSTEM procedure function {%kTBITSIZE} expects a variable as its first parameter, seen {%1d} {%1&s}", 103, M2Quads_OperandT (1));
13377 0 : ReturnVar = SymbolTable_MakeConstLit (resulttok, NameKey_MakeKey ((const char *) "0", 1), M2Base_Cardinal);
13378 : }
13379 : }
13380 0 : else if (NoOfParam == 0)
13381 : {
13382 : /* avoid dangling else. */
13383 0 : resulttok = functok;
13384 0 : M2MetaError_MetaErrorT0 (functok, (const char *) "{%E}SYSTEM procedure function {%kTBITSIZE} expects either one or two parameters, seen none", 90);
13385 0 : ReturnVar = SymbolTable_MakeConstLit (functok, NameKey_MakeKey ((const char *) "0", 1), M2Base_Cardinal);
13386 : }
13387 : else
13388 : {
13389 : /* avoid dangling else. */
13390 0 : Record = static_cast<unsigned int> (M2Quads_OperandT (NoOfParam));
13391 0 : paramtok = OperandTtok (1);
13392 0 : resulttok = OperandTtok (NoOfParam);
13393 0 : if (SymbolTable_IsRecord (Record))
13394 : {
13395 0 : paramtok = OperandTtok (1);
13396 0 : resulttok = M2LexBuf_MakeVirtualTok (functok, functok, paramtok);
13397 0 : ReturnVar = SymbolTable_MakeTemporary (resulttok, SymbolTable_ImmediateValue);
13398 0 : GenQuad (M2Quads_StandardFunctionOp, ReturnVar, ProcSym, M2Quads_OperandT (1));
13399 : }
13400 : else
13401 : {
13402 0 : resulttok = M2LexBuf_MakeVirtualTok (functok, functok, paramtok);
13403 0 : M2MetaError_MetaErrorT1 (resulttok, (const char *) "{%E}SYSTEM procedure function {%kTBITSIZE} expects the first parameter to be a record type, seen {%1d} {%1&s}", 109, Record);
13404 0 : ReturnVar = SymbolTable_MakeConstLit (resulttok, NameKey_MakeKey ((const char *) "0", 1), M2Base_Cardinal);
13405 : }
13406 : }
13407 6496 : M2Quads_PopN (NoOfParam+1); /* destroy the arguments and function */
13408 6496 : M2Quads_PushTFtok (ReturnVar, SymbolTable_GetSType (ProcSym), resulttok); /* destroy the arguments and function */
13409 6496 : }
13410 :
13411 :
13412 : /*
13413 : ExpectingParameterType -
13414 : */
13415 :
13416 91878 : static void ExpectingParameterType (unsigned int BlockSym, unsigned int Type)
13417 : {
13418 91878 : if (! (SymbolTable_IsAModula2Type (Type)))
13419 : {
13420 : /* avoid gcc warning by using compound statement even if not strictly necessary. */
13421 6 : if (((Type == SymbolTable_NulSym) || (SymbolTable_IsPartialUnbounded (Type))) || (SymbolTable_IsUnknown (Type)))
13422 : {
13423 0 : if (SymbolTable_IsUnknown (Type))
13424 : {
13425 : /* Spellcheck. */
13426 0 : M2MetaError_MetaError2 ((const char *) "the type used in the formal parameter declaration in {%1Md} {%1a} is unknown {%2&s}", 83, BlockSym, Type);
13427 0 : SymbolTable_UnknownReported (Type);
13428 : }
13429 : else
13430 : {
13431 0 : M2MetaError_MetaError1 ((const char *) "the type used in the formal parameter declaration in {%1Md} {%1a} is unknown", 76, BlockSym);
13432 : }
13433 : }
13434 : else
13435 : {
13436 : /* --fixme-- filter spellcheck on type. */
13437 6 : M2MetaError_MetaError2 ((const char *) "the type {%1Ead} used in the formal parameter declaration in {%2Md} {%2a} was not declared as a type", 100, Type, BlockSym);
13438 : }
13439 : }
13440 91878 : }
13441 :
13442 :
13443 : /*
13444 : ExpectingVariableType -
13445 : */
13446 :
13447 83281 : static void ExpectingVariableType (unsigned int BlockSym, unsigned int Type)
13448 : {
13449 83281 : if (! (SymbolTable_IsAModula2Type (Type)))
13450 : {
13451 : /* avoid gcc warning by using compound statement even if not strictly necessary. */
13452 0 : if (Type == SymbolTable_NulSym)
13453 : {
13454 0 : M2MetaError_MetaError1 ((const char *) "the type used during the variable declaration section in procedure {%1EMad} is unknown", 86, BlockSym);
13455 0 : M2MetaError_MetaError1 ((const char *) "the type used during the variable declaration section in procedure {%1Ead} is unknown", 85, BlockSym);
13456 : }
13457 0 : else if ((SymbolTable_IsPartialUnbounded (Type)) || (SymbolTable_IsUnknown (Type)))
13458 : {
13459 : /* avoid dangling else. */
13460 : /* Spellcheck. */
13461 0 : M2MetaError_MetaError2 ((const char *) "the type {%1EMad} used during variable declaration section in procedure {%2ad} is unknown {%1&s}", 96, Type, BlockSym);
13462 0 : M2MetaError_MetaError2 ((const char *) "the type {%1Ead} used during variable declaration section in procedure {%2Mad} is unknown", 89, Type, BlockSym);
13463 0 : SymbolTable_UnknownReported (Type);
13464 : }
13465 : else
13466 : {
13467 : /* avoid dangling else. */
13468 0 : M2MetaError_MetaError2 ((const char *) "the {%1d} {%1Ea} is not a type and therefore cannot be used to declare a variable in {%2d} {%2a}", 96, Type, BlockSym);
13469 : }
13470 : }
13471 83281 : }
13472 :
13473 :
13474 : /*
13475 : CheckVariablesAndParameterTypesInBlock - checks to make sure that block, BlockSym, has
13476 : parameters types and variable types which are legal.
13477 : */
13478 :
13479 182486 : static void CheckVariablesAndParameterTypesInBlock (unsigned int BlockSym)
13480 : {
13481 182486 : unsigned int i;
13482 182486 : unsigned int n;
13483 182486 : unsigned int ParamNo;
13484 :
13485 182486 : if (SymbolTable_IsProcedure (BlockSym))
13486 : {
13487 81768 : ParamNo = SymbolTable_NoOfParamAny (BlockSym);
13488 : }
13489 : else
13490 : {
13491 : ParamNo = 0;
13492 : }
13493 182486 : i = 1;
13494 1319702 : do {
13495 1319702 : n = SymbolTable_GetNth (BlockSym, i);
13496 1319702 : if (((n != SymbolTable_NulSym) && (! (SymbolTable_IsTemporary (n)))) && ((SymbolTable_IsProcedure (BlockSym)) || (((SymbolTable_IsDefImp (BlockSym)) && ((SymbolTable_GetMainModule ()) == BlockSym)) || (SymbolTable_IsModule (BlockSym)))))
13497 : {
13498 : /* avoid gcc warning by using compound statement even if not strictly necessary. */
13499 175159 : if (i <= ParamNo)
13500 : {
13501 : /* n is a parameter */
13502 91878 : ExpectingParameterType (BlockSym, SymbolTable_GetSType (n));
13503 : }
13504 : else
13505 : {
13506 : /* n is a local variable */
13507 83281 : ExpectingVariableType (BlockSym, SymbolTable_GetSType (n));
13508 : }
13509 : }
13510 1319702 : i += 1;
13511 1319702 : } while (! (n == SymbolTable_NulSym));
13512 182486 : }
13513 :
13514 :
13515 : /*
13516 : IsNeverAltered - returns TRUE if variable, sym, is never altered
13517 : between quadruples: Start..End
13518 : */
13519 :
13520 30 : static bool IsNeverAltered (unsigned int sym, unsigned int Start, unsigned int End)
13521 : {
13522 30 : unsigned int WriteStart;
13523 30 : unsigned int WriteEnd;
13524 :
13525 30 : SymbolTable_GetWriteLimitQuads (sym, SymbolTable_GetMode (sym), Start, End, &WriteStart, &WriteEnd);
13526 30 : return (WriteStart == 0) && (WriteEnd == 0);
13527 : /* static analysis guarentees a RETURN statement will be used before here. */
13528 : __builtin_unreachable ();
13529 : }
13530 :
13531 :
13532 : /*
13533 : IsConditionVariable - returns TRUE if the condition at quadruple, q, is variable.
13534 : */
13535 :
13536 24 : static bool IsConditionVariable (unsigned int q, unsigned int Start, unsigned int End)
13537 : {
13538 24 : M2Quads_QuadOperator op;
13539 24 : unsigned int op1;
13540 24 : unsigned int op2;
13541 24 : unsigned int op3;
13542 24 : bool LeftFixed;
13543 24 : bool RightFixed;
13544 :
13545 24 : M2Quads_GetQuad (q, &op, &op1, &op2, &op3);
13546 24 : if (op == M2Quads_GotoOp)
13547 : {
13548 : return false;
13549 : }
13550 : else
13551 : {
13552 24 : LeftFixed = SymbolTable_IsConst (op1);
13553 24 : RightFixed = SymbolTable_IsConst (op2);
13554 24 : if (! LeftFixed)
13555 : {
13556 24 : LeftFixed = IsNeverAltered (op1, Start, End);
13557 : }
13558 24 : if (! RightFixed)
13559 : {
13560 6 : RightFixed = IsNeverAltered (op2, Start, End);
13561 : }
13562 24 : return ! (LeftFixed && RightFixed);
13563 : }
13564 : /* static analysis guarentees a RETURN statement will be used before here. */
13565 : __builtin_unreachable ();
13566 : }
13567 :
13568 :
13569 : /*
13570 : IsInfiniteLoop - returns TRUE if an infinite loop is found.
13571 : Given a backwards jump at, End, it returns a BOOLEAN which depends on
13572 : whether a jump is found to jump beyond, End. If a conditonal jump is found
13573 : to pass over, End, the condition is tested for global variables, procedure variables and
13574 : constants.
13575 :
13576 : constant - ignored
13577 : variables - tested to see whether they are altered inside the loop
13578 : global variable - the procedure tests to see whether it is altered as above
13579 : but will also test to see whether this loop calls a procedure
13580 : in which case it believes the loop NOT to be infinite
13581 : (as this procedure call might alter the global variable)
13582 :
13583 : Note that this procedure can easily be fooled by the user altering variables
13584 : with pointers.
13585 : */
13586 :
13587 24 : static bool IsInfiniteLoop (unsigned int End)
13588 : {
13589 24 : bool SeenCall;
13590 24 : bool IsGlobal;
13591 24 : unsigned int Current;
13592 24 : unsigned int Start;
13593 24 : M2Quads_QuadOperator op;
13594 24 : unsigned int op1;
13595 24 : unsigned int op2;
13596 24 : unsigned int op3;
13597 :
13598 24 : SeenCall = false;
13599 24 : IsGlobal = false;
13600 24 : M2Quads_GetQuad (End, &op, &op1, &op2, &Start);
13601 24 : Current = Start;
13602 216 : while (Current != End)
13603 : {
13604 216 : M2Quads_GetQuad (Current, &op, &op1, &op2, &op3);
13605 : /* remember that this function is only called once we have optimized the redundant gotos and conditionals */
13606 216 : if ((M2Quads_IsConditional (Current)) && ! IsGlobal)
13607 : {
13608 24 : IsGlobal = ((SymbolTable_IsVar (op1)) && (! (SymbolTable_IsProcedure (SymbolTable_GetVarScope (op1))))) || ((SymbolTable_IsVar (op2)) && (! (SymbolTable_IsProcedure (SymbolTable_GetVarScope (op2)))));
13609 : }
13610 216 : if (op == M2Quads_CallOp)
13611 : {
13612 12 : SeenCall = true;
13613 : }
13614 216 : if ((op == M2Quads_GotoOp) || ((M2Quads_IsConditional (Current)) && (IsConditionVariable (Current, Start, End))))
13615 : {
13616 24 : if ((op3 > End) || (op3 < Start))
13617 : {
13618 : return false; /* may jump out of this loop, good */
13619 : }
13620 : }
13621 192 : Current = M2Quads_GetNextQuad (Current);
13622 : }
13623 0 : M2Quads_GetQuad (End, &op, &op1, &op2, &op3);
13624 0 : if (M2Quads_IsConditional (End))
13625 : {
13626 : /* avoid gcc warning by using compound statement even if not strictly necessary. */
13627 0 : if (IsConditionVariable (End, Start, End))
13628 : {
13629 : return false;
13630 : }
13631 : else
13632 : {
13633 0 : if (! IsGlobal)
13634 : {
13635 0 : IsGlobal = ((SymbolTable_IsVar (op1)) && (! (SymbolTable_IsProcedure (SymbolTable_GetVarScope (op1))))) || ((SymbolTable_IsVar (op2)) && (! (SymbolTable_IsProcedure (SymbolTable_GetVarScope (op2)))));
13636 : }
13637 : }
13638 : }
13639 : /* we have found a likely infinite loop if no conditional uses a global and no procedure call was seen */
13640 0 : return ! (IsGlobal && SeenCall);
13641 : /* static analysis guarentees a RETURN statement will be used before here. */
13642 : __builtin_unreachable ();
13643 : }
13644 :
13645 :
13646 : /*
13647 : CheckVariablesInBlock - given a block, BlockSym, check whether all variables are used.
13648 : */
13649 :
13650 182486 : static void CheckVariablesInBlock (unsigned int BlockSym)
13651 : {
13652 0 : CheckVariablesAndParameterTypesInBlock (BlockSym);
13653 0 : }
13654 :
13655 :
13656 : /*
13657 : CheckFunctionReturn - checks to see that a RETURN statement was present in a function.
13658 : */
13659 :
13660 81768 : static void CheckFunctionReturn (unsigned int ProcSym)
13661 : {
13662 81768 : M2Quads_QuadOperator Op;
13663 81768 : unsigned int Op1;
13664 81768 : unsigned int Op2;
13665 81768 : unsigned int Op3;
13666 81768 : unsigned int Scope;
13667 81768 : unsigned int Start;
13668 81768 : unsigned int End;
13669 :
13670 81768 : if ((SymbolTable_GetSType (ProcSym)) != SymbolTable_NulSym)
13671 : {
13672 : /* yes it is a function */
13673 19166 : SymbolTable_GetProcedureQuads (ProcSym, &Scope, &Start, &End);
13674 19166 : M2Quads_GetQuad (Start, &Op, &Op1, &Op2, &Op3);
13675 19166 : if (Start == 0)
13676 : {
13677 0 : M2Error_InternalError ((const char *) "incorrect start quad", 20);
13678 : }
13679 778172 : while (((Start != End) && (Op != M2Quads_ReturnValueOp)) && (Op != M2Quads_InlineOp))
13680 : {
13681 759006 : Start = M2Quads_GetNextQuad (Start);
13682 759006 : M2Quads_GetQuad (Start, &Op, &Op1, &Op2, &Op3);
13683 : }
13684 19166 : if ((Op != M2Quads_ReturnValueOp) && (Op != M2Quads_InlineOp))
13685 : {
13686 : /* an InlineOp can always be used to emulate a RETURN */
13687 6 : M2MetaError_MetaError1 ((const char *) "procedure function {%1Ea} does not RETURN a value", 49, ProcSym);
13688 : }
13689 : }
13690 81768 : }
13691 :
13692 :
13693 : /*
13694 : CheckReturnType - checks to see that the return type from currentProc is
13695 : assignment compatible with actualType.
13696 : */
13697 :
13698 28111 : static void CheckReturnType (unsigned int tokno, unsigned int currentProc, unsigned int actualVal, unsigned int actualType)
13699 : {
13700 28111 : unsigned int procType;
13701 28111 : DynamicStrings_String s1;
13702 28111 : DynamicStrings_String s2;
13703 28111 : NameKey_Name n1;
13704 28111 : NameKey_Name n2;
13705 :
13706 28111 : procType = SymbolTable_GetSType (currentProc);
13707 28111 : if (procType == SymbolTable_NulSym)
13708 : {
13709 0 : M2MetaError_MetaError1 ((const char *) "attempting to RETURN a value from procedure {%1Ea} which was not a declared as a procedure function", 99, currentProc);
13710 : }
13711 28111 : else if (M2Base_AssignmentRequiresWarning (actualType, SymbolTable_GetSType (currentProc)))
13712 : {
13713 : /* avoid dangling else. */
13714 0 : M2MetaError_MetaError2 ((const char *) "attempting to RETURN a value {%1Wa} with an incompatible type {%1Wtsa} from a procedure function {%1a} which returns {%1tsa}", 124, actualVal, currentProc);
13715 : }
13716 28111 : else if (! (M2Base_IsAssignmentCompatible (actualType, procType)))
13717 : {
13718 : /* avoid dangling else. */
13719 0 : n1 = SymbolTable_GetSymName (actualType);
13720 0 : n2 = SymbolTable_GetSymName (procType);
13721 0 : M2Error_WriteFormat2 ((const char *) "attempting to RETURN a value with an incompatible type (%a) from a function which returns (%a)", 94, (const unsigned char *) &n1, (sizeof (n1)-1), (const unsigned char *) &n2, (sizeof (n2)-1));
13722 : }
13723 28111 : else if ((SymbolTable_IsProcedure (actualVal)) && (! (M2Base_IsAssignmentCompatible (actualVal, procType))))
13724 : {
13725 : /* avoid dangling else. */
13726 : /*
13727 : MetaWarnings2('attempting to RETURN a value with an incompatible type {%1ad} from function {%2a} which returns {%2ta}',
13728 : actualVal, currentProc)
13729 :
13730 : --fixme-- introduce MetaWarning, MetaWarning2, MetaWarning3 into M2MetaError
13731 : */
13732 0 : s1 = DynamicStrings_InitStringCharStar (NameKey_KeyToCharStar (SymbolTable_GetSymName (actualVal)));
13733 0 : s2 = DynamicStrings_InitStringCharStar (NameKey_KeyToCharStar (SymbolTable_GetSymName (procType)));
13734 0 : M2Error_ErrorString (M2Error_NewWarning (M2LexBuf_GetTokenNo ()), FormatStrings_Sprintf2 (DynamicStrings_Mark (DynamicStrings_InitString ((const char *) "attempting to RETURN a value with a (possibly on other targets) incompatible type (%s) from a function which returns (%s)", 121)), (const unsigned char *) &s1, (sizeof (s1)-1), (const unsigned char *) &s2, (sizeof (s2)-1)));
13735 : }
13736 28111 : else if ((SymbolTable_IsProcedure (actualVal)) && (! (M2Base_IsAssignmentCompatible (actualVal, SymbolTable_GetSType (CurrentProc)))))
13737 : {
13738 : /* avoid dangling else. */
13739 0 : n1 = SymbolTable_GetSymName (actualVal);
13740 0 : n2 = SymbolTable_GetSymName (SymbolTable_GetSType (currentProc));
13741 0 : M2Error_WriteFormat2 ((const char *) "attempting to RETURN a value with an incompatible type (%a) from a function which returns (%a)", 94, (const unsigned char *) &n1, (sizeof (n1)-1), (const unsigned char *) &n2, (sizeof (n2)-1));
13742 : }
13743 : else
13744 : {
13745 : /* avoid dangling else. */
13746 : /* this checks the types are compatible, not the data contents. */
13747 28111 : BuildRange (M2Range_InitTypesReturnTypeCheck (tokno, currentProc, actualVal));
13748 : }
13749 28111 : }
13750 :
13751 :
13752 : /*
13753 : BuildReturnLower - check the return type and value to ensure type
13754 : compatibility and no range overflow will occur.
13755 : */
13756 :
13757 28111 : static void BuildReturnLower (unsigned int tokcombined, unsigned int tokexpr, unsigned int e1, unsigned int t1)
13758 : {
13759 28111 : unsigned int e2;
13760 28111 : unsigned int t2;
13761 :
13762 : /* This will check that the type returned is compatible with
13763 : the formal return type of the procedure. */
13764 28111 : CheckReturnType (tokcombined, CurrentProc, e1, t1);
13765 : /* Dereference LeftValue if necessary. */
13766 28111 : if ((SymbolTable_GetMode (e1)) == SymbolTable_LeftValue)
13767 : {
13768 172 : t2 = SymbolTable_GetSType (CurrentProc);
13769 172 : e2 = SymbolTable_MakeTemporary (tokexpr, SymbolTable_RightValue);
13770 172 : SymbolTable_PutVar (e2, t2);
13771 172 : CheckPointerThroughNil (tokexpr, e1);
13772 172 : doIndrX (tokexpr, e2, e1);
13773 172 : e1 = e2;
13774 : }
13775 : /* Here we check the data contents to ensure no overflow. */
13776 28111 : BuildRange (M2Range_InitReturnRangeCheck (tokcombined, CurrentProc, e1));
13777 28111 : GenQuadOtok (tokcombined, M2Quads_ReturnValueOp, e1, SymbolTable_NulSym, CurrentProc, false, tokcombined, M2LexBuf_UnknownTokenNo, SymbolTable_GetDeclaredMod (CurrentProc));
13778 28111 : }
13779 :
13780 :
13781 : /*
13782 : IsReadOnly - a helper procedure function to detect constants.
13783 : */
13784 :
13785 276474 : static bool IsReadOnly (unsigned int sym)
13786 : {
13787 276474 : return (SymbolTable_IsConst (sym)) || ((SymbolTable_IsVar (sym)) && (SymbolTable_IsVarConst (sym)));
13788 : /* static analysis guarentees a RETURN statement will be used before here. */
13789 : __builtin_unreachable ();
13790 : }
13791 :
13792 :
13793 : /*
13794 : BuildDesignatorError - removes the designator from the stack and replaces
13795 : it with an error symbol.
13796 : */
13797 :
13798 54 : static void BuildDesignatorError (const char *message_, unsigned int _message_high)
13799 : {
13800 54 : unsigned int combinedTok;
13801 54 : unsigned int arrayTok;
13802 54 : unsigned int exprTok;
13803 54 : unsigned int e;
13804 54 : unsigned int d;
13805 54 : unsigned int error;
13806 54 : unsigned int Sym;
13807 54 : unsigned int Type;
13808 54 : char message[_message_high+1];
13809 :
13810 : /* make a local copy of each unbounded array. */
13811 54 : memcpy (message, message_, _message_high+1);
13812 :
13813 54 : M2Quads_PopTtok (&e, &exprTok);
13814 54 : PopTFDtok (&Sym, &Type, &d, &arrayTok);
13815 54 : combinedTok = M2LexBuf_MakeVirtualTok (arrayTok, arrayTok, exprTok);
13816 54 : error = SymbolTable_MakeError (combinedTok, NameKey_MakeKey ((const char *) message, _message_high));
13817 54 : PushTFDtok (error, Type, d, arrayTok);
13818 54 : }
13819 :
13820 :
13821 : /*
13822 : BuildDesignatorPointerError - removes the designator from the stack and replaces
13823 : it with an error symbol.
13824 : */
13825 :
13826 2 : static void BuildDesignatorPointerError (unsigned int type, unsigned int rw, unsigned int tokpos, const char *message_, unsigned int _message_high)
13827 : {
13828 2 : unsigned int error;
13829 2 : char message[_message_high+1];
13830 :
13831 : /* make a local copy of each unbounded array. */
13832 2 : memcpy (message, message_, _message_high+1);
13833 :
13834 2 : error = SymbolTable_MakeError (tokpos, NameKey_MakeKey ((const char *) message, _message_high));
13835 2 : if ((SymbolTable_GetSType (type)) != SymbolTable_NulSym)
13836 : {
13837 2 : type = SymbolTable_GetSType (type);
13838 : }
13839 2 : PushTFrwtok (error, type, rw, tokpos);
13840 2 : }
13841 :
13842 :
13843 : /*
13844 : BuildDesignatorArrayStaticDynamic - Builds the array referencing.
13845 : The purpose of this procedure is to work out
13846 : whether the DesignatorArray is a static or
13847 : dynamic array and to call the appropriate
13848 : BuildRoutine.
13849 :
13850 : The Stack is expected to contain:
13851 :
13852 :
13853 : Entry Exit
13854 : ===== ====
13855 :
13856 : Ptr ->
13857 : +--------------+
13858 : | e | <- Ptr
13859 : |--------------| +------------+
13860 : | Sym | Type | | S | T |
13861 : |--------------| |------------|
13862 : */
13863 :
13864 57020 : static void BuildDesignatorArrayStaticDynamic (void)
13865 : {
13866 57020 : unsigned int combinedTok;
13867 57020 : unsigned int arrayTok;
13868 57020 : unsigned int exprTok;
13869 57020 : unsigned int e;
13870 57020 : unsigned int type;
13871 57020 : unsigned int dim;
13872 57020 : unsigned int result;
13873 57020 : unsigned int Sym;
13874 57020 : unsigned int Type;
13875 :
13876 57020 : if (SymbolTable_IsConst (M2Quads_OperandT (2)))
13877 : {
13878 204 : type = SymbolTable_GetDType (M2Quads_OperandT (2));
13879 204 : if ((type != SymbolTable_NulSym) && (SymbolTable_IsArray (type)))
13880 : {
13881 204 : M2Quads_PopTtok (&e, &exprTok);
13882 204 : PopTFDtok (&Sym, &Type, &dim, &arrayTok);
13883 204 : result = SymbolTable_MakeTemporary (exprTok, SymbolTable_RightValue);
13884 204 : SymbolTable_PutVar (result, Type);
13885 204 : M2Quads_PushTFtok (result, SymbolTable_GetSType (result), exprTok);
13886 204 : M2Quads_PushTtok (Sym, arrayTok);
13887 204 : combinedTok = M2LexBuf_MakeVirtualTok (arrayTok, arrayTok, exprTok);
13888 204 : SymbolTable_PutVarConst (result, true);
13889 204 : M2Quads_BuildAssignConstant (combinedTok);
13890 204 : PushTFDtok (result, SymbolTable_GetDType (result), dim, arrayTok);
13891 204 : M2Quads_PushTtok (e, exprTok);
13892 : }
13893 : }
13894 57020 : if ((! (SymbolTable_IsVar (M2Quads_OperandT (2)))) && (! (SymbolTable_IsTemporary (M2Quads_OperandT (2)))))
13895 : {
13896 18 : M2MetaError_MetaErrorT1 (OperandTtok (2), (const char *) "can only access arrays using constants, variables or formal parameters not {%1Ead}", 82, M2Quads_OperandT (2));
13897 18 : BuildDesignatorError ((const char *) "bad array access", 16);
13898 : }
13899 57020 : Sym = static_cast<unsigned int> (M2Quads_OperandT (2));
13900 57020 : Type = SymbolTable_GetDType (Sym);
13901 57020 : arrayTok = OperandTtok (2);
13902 57020 : if (Type == SymbolTable_NulSym)
13903 : {
13904 0 : if ((arrayTok == M2LexBuf_UnknownTokenNo) || (arrayTok == M2LexBuf_BuiltinTokenNo))
13905 : {
13906 0 : arrayTok = M2LexBuf_GetTokenNo ();
13907 : }
13908 0 : M2MetaError_MetaErrorT0 (arrayTok, (const char *) "type of array is undefined", 26);
13909 0 : BuildDesignatorError ((const char *) "bad array access", 16);
13910 : }
13911 57020 : else if (SymbolTable_IsUnbounded (Type))
13912 : {
13913 : /* avoid dangling else. */
13914 8994 : BuildDynamicArray ();
13915 : }
13916 48026 : else if (SymbolTable_IsArray (Type))
13917 : {
13918 : /* avoid dangling else. */
13919 47996 : BuildStaticArray ();
13920 : }
13921 : else
13922 : {
13923 : /* avoid dangling else. */
13924 30 : M2MetaError_MetaErrorT1 (arrayTok, (const char *) "can only index static or dynamic arrays, {%1Ead} is not an array but a {%tadv}", 78, Sym);
13925 30 : BuildDesignatorError ((const char *) "bad array access", 16);
13926 : }
13927 57014 : }
13928 :
13929 :
13930 : /*
13931 : BuildStaticArray - Builds the array referencing for static arrays.
13932 : The Stack is expected to contain:
13933 :
13934 :
13935 : Entry Exit
13936 : ===== ====
13937 :
13938 : Ptr ->
13939 : +--------------+
13940 : | e | <- Ptr
13941 : |--------------| +------------+
13942 : | Sym | Type | | S | T |
13943 : |--------------| |------------|
13944 : */
13945 :
13946 47996 : static void BuildStaticArray (void)
13947 : {
13948 47996 : unsigned int combinedTok;
13949 47996 : unsigned int indexTok;
13950 47996 : unsigned int arrayTok;
13951 47996 : unsigned int rw;
13952 47996 : unsigned int Dim;
13953 47996 : unsigned int Array;
13954 47996 : unsigned int Index;
13955 47996 : unsigned int BackEndType;
13956 47996 : unsigned int Type;
13957 47996 : unsigned int Adr;
13958 :
13959 47996 : Index = static_cast<unsigned int> (M2Quads_OperandT (1));
13960 47996 : indexTok = OperandTtok (1);
13961 47996 : Array = static_cast<unsigned int> (M2Quads_OperandT (2));
13962 47996 : arrayTok = OperandTtok (2);
13963 47996 : Type = SymbolTable_SkipType (M2Quads_OperandF (2));
13964 47996 : rw = static_cast<unsigned int> (OperandMergeRW (2));
13965 47996 : M2Debug_Assert (SymbolTable_IsLegal (rw));
13966 47996 : Dim = static_cast<unsigned int> (OperandD (2));
13967 47996 : Dim += 1;
13968 47996 : if ((SymbolTable_GetMode (Index)) == SymbolTable_LeftValue)
13969 : {
13970 176 : Index = MakeRightValue (indexTok, Index, SymbolTable_GetSType (Index));
13971 : }
13972 47990 : BuildRange (M2Range_InitStaticArraySubscriptRangeCheck (SymbolTable_GetArraySubscript (Type), Index, Dim));
13973 : /* now make Adr point to the address of the indexed element */
13974 47990 : combinedTok = M2LexBuf_MakeVirtualTok (arrayTok, arrayTok, indexTok);
13975 47990 : Adr = SymbolTable_MakeTemporary (combinedTok, SymbolTable_LeftValue);
13976 47990 : if (SymbolTable_IsVar (Array))
13977 : {
13978 : /* BuildDesignatorArray may have detected des is a constant. */
13979 47990 : SymbolTable_PutVarConst (Adr, SymbolTable_IsVarConst (Array));
13980 : }
13981 47990 : SymbolTable_PutVarArrayRef (Adr, true);
13982 : /*
13983 : From now on it must reference the array element by its lvalue
13984 : - so we create the type of the referenced entity
13985 : */
13986 47990 : BackEndType = SymbolTable_MakePointer (combinedTok, NameKey_NulName);
13987 47990 : SymbolTable_PutPointer (BackEndType, SymbolTable_GetDType (Type));
13988 : /* PutVar(Adr, BackEndType) ; */
13989 47990 : SymbolTable_PutLeftValueFrontBackType (Adr, SymbolTable_GetDType (Type), BackEndType);
13990 95980 : GenQuadO (combinedTok, M2Quads_ArrayOp, Adr, Index, Array, true);
13991 47990 : M2Quads_PopN (2); /* remove all parameters to this procedure */
13992 47990 : PushTFDrwtok (Adr, SymbolTable_GetSType (Adr), Dim, rw, combinedTok); /* remove all parameters to this procedure */
13993 47990 : }
13994 :
13995 :
13996 : /*
13997 : calculateMultipicand - generates quadruples which calculate the
13998 : multiplicand for the array at dimension, dim.
13999 : */
14000 :
14001 12052 : static unsigned int calculateMultipicand (unsigned int tok, unsigned int arraySym, unsigned int arrayType, unsigned int dim)
14002 : {
14003 12052 : unsigned int ti;
14004 12052 : unsigned int tj;
14005 12052 : unsigned int tk;
14006 12052 : unsigned int tl;
14007 :
14008 12052 : if (dim == (SymbolTable_GetDimension (arrayType)))
14009 : {
14010 : /* ti has no type since constant */
14011 10268 : ti = SymbolTable_MakeTemporary (tok, SymbolTable_ImmediateValue);
14012 10268 : SymbolTable_PutVar (ti, M2Base_Cardinal);
14013 10268 : GenQuadO (tok, M2Quads_ElementSizeOp, ti, arrayType, 1, true);
14014 : }
14015 : else
14016 : {
14017 1784 : dim += 1;
14018 1784 : tk = SymbolTable_MakeTemporary (tok, SymbolTable_RightValue);
14019 1784 : SymbolTable_PutVar (tk, M2Base_Cardinal);
14020 1784 : GenHigh (tok, tk, dim, arraySym);
14021 1784 : tl = SymbolTable_MakeTemporary (tok, SymbolTable_RightValue);
14022 1784 : SymbolTable_PutVar (tl, M2Base_Cardinal);
14023 1784 : GenQuadOtok (tok, M2Quads_AddOp, tl, tk, SymbolTable_MakeConstLit (tok, NameKey_MakeKey ((const char *) "1", 1), M2Base_Cardinal), true, tok, tok, tok);
14024 1784 : tj = calculateMultipicand (tok, arraySym, arrayType, dim);
14025 1784 : ti = SymbolTable_MakeTemporary (tok, SymbolTable_RightValue);
14026 1784 : SymbolTable_PutVar (ti, M2Base_Cardinal);
14027 1784 : GenQuadO (tok, M2Quads_MultOp, ti, tj, tl, true);
14028 : }
14029 12052 : return ti;
14030 : /* static analysis guarentees a RETURN statement will be used before here. */
14031 : __builtin_unreachable ();
14032 : }
14033 :
14034 :
14035 : /*
14036 : ConvertToAddress - convert sym to an address.
14037 : */
14038 :
14039 9078 : static unsigned int ConvertToAddress (unsigned int tokpos, unsigned int sym)
14040 : {
14041 9078 : unsigned int adr;
14042 :
14043 9078 : if ((SymbolTable_GetSType (sym)) == M2System_Address)
14044 : {
14045 : return sym;
14046 : }
14047 : else
14048 : {
14049 9066 : M2Quads_PushTF (SymbolTable_RequestSym (tokpos, NameKey_MakeKey ((const char *) "CONVERT", 7)), static_cast<unsigned int> (SymbolTable_NulSym));
14050 9066 : M2Quads_PushT (M2System_Address);
14051 9066 : M2Quads_PushTtok (sym, tokpos);
14052 9066 : M2Quads_PushT (static_cast<unsigned int> (2)); /* Two parameters */
14053 9066 : BuildConvertFunction (M2Base_Convert, false); /* Two parameters */
14054 9066 : M2Quads_PopT (&adr);
14055 9066 : return adr;
14056 : }
14057 : /* static analysis guarentees a RETURN statement will be used before here. */
14058 : __builtin_unreachable ();
14059 : }
14060 :
14061 :
14062 : /*
14063 : BuildDynamicArray - Builds the array referencing for dynamic arrays.
14064 : The Stack is expected to contain:
14065 :
14066 :
14067 : Entry Exit
14068 : ===== ====
14069 :
14070 : Ptr ->
14071 : +-----------------------+
14072 : | Index | <- Ptr
14073 : |-----------------------| +---------------------------+
14074 : | ArraySym | Type | Dim | | S | T | ArraySym | Dim+1 |
14075 : |-----------------------| |---------------------------|
14076 :
14077 :
14078 : if Dim=1
14079 : then
14080 : S := base of ArraySym + TSIZE(Type)*Index
14081 : else
14082 : S := S + TSIZE(Type)*Index
14083 : fi
14084 : */
14085 :
14086 8994 : static void BuildDynamicArray (void)
14087 : {
14088 8994 : unsigned int combinedTok;
14089 8994 : unsigned int arrayTok;
14090 8994 : unsigned int indexTok;
14091 8994 : unsigned int Sym;
14092 8994 : unsigned int idx;
14093 8994 : unsigned int Type;
14094 8994 : unsigned int Adr;
14095 8994 : unsigned int ArraySym;
14096 8994 : unsigned int BackEndType;
14097 8994 : unsigned int UnboundedType;
14098 8994 : unsigned int PtrToBase;
14099 8994 : unsigned int Base;
14100 8994 : unsigned int Dim;
14101 8994 : unsigned int rw;
14102 8994 : unsigned int ti;
14103 8994 : unsigned int tj;
14104 8994 : unsigned int tk;
14105 8994 : unsigned int tka;
14106 :
14107 8994 : M2Quads_DisplayStack ();
14108 8994 : Sym = static_cast<unsigned int> (M2Quads_OperandT (2));
14109 8994 : Type = SymbolTable_SkipType (M2Quads_OperandF (2));
14110 8994 : arrayTok = static_cast<unsigned int> (M2Quads_OperandTok (2));
14111 8994 : indexTok = static_cast<unsigned int> (M2Quads_OperandTok (1));
14112 8994 : combinedTok = M2LexBuf_MakeVirtualTok (arrayTok, arrayTok, indexTok);
14113 8994 : Dim = static_cast<unsigned int> (OperandD (2));
14114 8994 : rw = static_cast<unsigned int> (OperandMergeRW (2));
14115 8994 : M2Debug_Assert (SymbolTable_IsLegal (rw));
14116 8994 : Dim += 1;
14117 8994 : if (Dim == 1)
14118 : {
14119 : /*
14120 : Base has type address since
14121 : BuildDesignatorRecord references by address.
14122 :
14123 : Build a record for retrieving the address of dynamic array.
14124 : BuildDesignatorRecord will generate the required quadruples,
14125 : therefore build sets up the stack for BuildDesignatorRecord
14126 : which will generate the quads to access the record.
14127 : */
14128 8856 : ArraySym = Sym;
14129 8856 : UnboundedType = SymbolTable_GetUnboundedRecordType (SymbolTable_GetSType (Sym));
14130 8856 : PushTFrwtok (Sym, UnboundedType, rw, arrayTok);
14131 8856 : M2Quads_PushTF (SymbolTable_GetUnboundedAddressOffset (SymbolTable_GetSType (Sym)), SymbolTable_GetSType (SymbolTable_GetUnboundedAddressOffset (SymbolTable_GetSType (Sym))));
14132 8856 : M2Quads_PushT (static_cast<unsigned int> (1)); /* One record field to dereference */
14133 8856 : M2Quads_BuildDesignatorRecord (combinedTok); /* One record field to dereference */
14134 8856 : M2Quads_PopT (&PtrToBase);
14135 8856 : M2Quads_DisplayStack ();
14136 : /* Now actually copy Unbounded.ArrayAddress into base */
14137 8856 : if ((SymbolTable_GetMode (PtrToBase)) == SymbolTable_LeftValue)
14138 : {
14139 0 : Base = SymbolTable_MakeTemporary (arrayTok, SymbolTable_RightValue);
14140 0 : SymbolTable_PutVar (Base, M2System_Address); /* has type ADDRESS */
14141 0 : CheckPointerThroughNil (arrayTok, PtrToBase); /* has type ADDRESS */
14142 0 : GenQuad (M2Quads_IndrXOp, Base, M2System_Address, PtrToBase); /* Base = *PtrToBase */
14143 : }
14144 : else
14145 : {
14146 8856 : M2Debug_Assert ((SymbolTable_GetMode (PtrToBase)) != SymbolTable_ImmediateValue);
14147 8856 : Base = PtrToBase;
14148 : }
14149 : }
14150 : else
14151 : {
14152 : /* Base already calculated previously and pushed to stack */
14153 138 : UnboundedType = SymbolTable_SkipType (M2Quads_OperandF (2));
14154 138 : Base = Sym;
14155 138 : ArraySym = static_cast<unsigned int> (M2Quads_OperandA (2));
14156 : }
14157 8994 : M2Debug_Assert ((SymbolTable_GetSType (Sym)) == Type);
14158 8994 : ti = calculateMultipicand (indexTok, Sym, Type, Dim);
14159 8994 : idx = static_cast<unsigned int> (M2Quads_OperandT (1));
14160 8994 : if ((SymbolTable_IsConst (idx)) && (SymbolTable_IsConst (ti)))
14161 : {
14162 : /* tj has no type since constant */
14163 460 : tj = SymbolTable_MakeTemporary (indexTok, SymbolTable_ImmediateValue);
14164 460 : tk = SymbolTable_MakeTemporary (indexTok, SymbolTable_ImmediateValue);
14165 460 : SymbolTable_PutVar (tj, M2Base_Cardinal);
14166 460 : SymbolTable_PutVar (tk, M2Base_Cardinal);
14167 : }
14168 : else
14169 : {
14170 : /* tj has Cardinal type since we have multiplied array indices */
14171 8534 : tj = SymbolTable_MakeTemporary (indexTok, SymbolTable_RightValue);
14172 8534 : if ((SymbolTable_GetSType (idx)) != M2Base_Cardinal)
14173 : {
14174 270 : M2Quads_PushTF (SymbolTable_RequestSym (indexTok, NameKey_MakeKey ((const char *) "CONVERT", 7)), static_cast<unsigned int> (SymbolTable_NulSym));
14175 270 : M2Quads_PushT (M2Base_Cardinal);
14176 270 : M2Quads_PushTtok (idx, indexTok);
14177 270 : M2Quads_PushT (static_cast<unsigned int> (2)); /* Two parameters */
14178 270 : BuildConvertFunction (M2Base_Convert, false); /* Two parameters */
14179 270 : M2Quads_PopT (&idx);
14180 : }
14181 8534 : SymbolTable_PutVar (tj, M2Base_Cardinal);
14182 8534 : tk = SymbolTable_MakeTemporary (indexTok, SymbolTable_RightValue);
14183 8534 : SymbolTable_PutVar (tk, M2Base_Cardinal);
14184 : }
14185 8994 : BuildRange (M2Range_InitDynamicArraySubscriptRangeCheck (ArraySym, idx, Dim));
14186 8994 : M2Quads_PushTtok (tj, indexTok);
14187 8994 : M2Quads_PushTtok (idx, indexTok);
14188 8994 : BuildAssignmentWithoutBounds (indexTok, false, true);
14189 17988 : GenQuad (M2Quads_MultOp, tk, ti, tj);
14190 17988 : Adr = SymbolTable_MakeTemporary (combinedTok, SymbolTable_LeftValue);
14191 8994 : SymbolTable_PutVarArrayRef (Adr, true);
14192 : /*
14193 : Ok must reference by address
14194 : - but we contain the type of the referenced entity
14195 : */
14196 8994 : BackEndType = SymbolTable_MakePointer (combinedTok, NameKey_NulName);
14197 8994 : SymbolTable_PutPointer (BackEndType, SymbolTable_GetSType (Type));
14198 : /* Create a temporary pointer for addition. */
14199 8994 : tka = ConvertToAddress (combinedTok, tk);
14200 8994 : if (Dim == (SymbolTable_GetDimension (Type)))
14201 : {
14202 8676 : SymbolTable_PutLeftValueFrontBackType (Adr, SymbolTable_GetSType (Type), BackEndType);
14203 17352 : GenQuadOtok (combinedTok, M2Quads_AddOp, Adr, Base, tka, false, combinedTok, combinedTok, combinedTok);
14204 8676 : M2Quads_PopN (2);
14205 8676 : PushTFADrwtok (Adr, SymbolTable_GetSType (Adr), ArraySym, Dim, rw, combinedTok);
14206 : }
14207 : else
14208 : {
14209 : /* more to index */
14210 318 : SymbolTable_PutLeftValueFrontBackType (Adr, Type, BackEndType);
14211 636 : GenQuadOtok (combinedTok, M2Quads_AddOp, Adr, Base, tka, false, combinedTok, combinedTok, combinedTok);
14212 318 : M2Quads_PopN (2);
14213 318 : PushTFADrwtok (Adr, SymbolTable_GetSType (Adr), ArraySym, Dim, rw, combinedTok);
14214 : }
14215 8994 : }
14216 :
14217 :
14218 : /*
14219 : DebugLocation -
14220 : */
14221 :
14222 58792 : static void DebugLocation (unsigned int tok, const char *message_, unsigned int _message_high)
14223 : {
14224 58792 : char message[_message_high+1];
14225 :
14226 : /* make a local copy of each unbounded array. */
14227 58792 : memcpy (message, message_, _message_high+1);
14228 :
14229 58792 : if (DebugTokPos)
14230 : {
14231 : M2Error_WarnStringAt (DynamicStrings_InitString ((const char *) message, _message_high), tok);
14232 : }
14233 58792 : }
14234 :
14235 :
14236 : /*
14237 : PushWith - pushes sym and type onto the with stack. It checks for
14238 : previous declaration of this record type.
14239 : */
14240 :
14241 6190 : static void PushWith (unsigned int Sym, unsigned int Type, unsigned int Ref, unsigned int Tok)
14242 : {
14243 6190 : unsigned int i;
14244 6190 : unsigned int n;
14245 6190 : M2Quads_WithFrame f;
14246 :
14247 6190 : if (M2Options_Pedantic)
14248 : {
14249 0 : n = M2StackAddress_NoOfItemsInStackAddress (WithStack);
14250 0 : i = 1; /* Top of the stack. */
14251 : /* Search for other declarations of the with using Type. */
14252 0 : while (i <= n)
14253 : {
14254 0 : f = static_cast<M2Quads_WithFrame> (M2StackAddress_PeepAddress (WithStack, i));
14255 0 : if (f->RecordSym == Type)
14256 : {
14257 0 : M2MetaError_MetaErrorT1 (Tok, (const char *) "cannot have nested {%kWITH} statements referencing the same {%kRECORD} {%1Ead}", 78, Sym);
14258 0 : M2MetaError_MetaErrorT1 (f->RecordTokPos, (const char *) "cannot have nested {%kWITH} statements referencing the same {%kRECORD} {%1Ead}", 78, f->RecordSym);
14259 : }
14260 0 : i += 1;
14261 : }
14262 : }
14263 6190 : Storage_ALLOCATE ((void **) &f, sizeof (M2Quads__T4));
14264 6190 : f->RecordSym = Sym;
14265 6190 : f->RecordType = Type;
14266 6190 : f->RecordRef = Ref;
14267 6190 : f->rw = Sym;
14268 6190 : f->RecordTokPos = Tok;
14269 6190 : M2StackAddress_PushAddress (WithStack, reinterpret_cast <void *> (f));
14270 6190 : }
14271 :
14272 6190 : static void PopWith (void)
14273 : {
14274 6190 : M2Quads_WithFrame f;
14275 :
14276 6190 : f = static_cast<M2Quads_WithFrame> (M2StackAddress_PopAddress (WithStack));
14277 6190 : Storage_DEALLOCATE ((void **) &f, sizeof (M2Quads__T4));
14278 6190 : }
14279 :
14280 :
14281 : /*
14282 : BuildAccessWithField - similar to BuildDesignatorRecord except it
14283 : does not perform the address operation.
14284 : The address will have been computed at the
14285 : beginning of the WITH statement.
14286 : It also stops the GenQuad procedure from examining the
14287 : with stack.
14288 :
14289 : The Stack
14290 :
14291 : Entry
14292 :
14293 : Ptr ->
14294 : +--------------+
14295 : | Field | Type1| <- Ptr
14296 : |-------|------| +-------------+
14297 : | Adr | Type2| | Sym | Type1|
14298 : |--------------| |-------------|
14299 : */
14300 :
14301 31040 : static void BuildAccessWithField (void)
14302 : {
14303 31040 : unsigned int rectok;
14304 31040 : unsigned int fieldtok;
14305 31040 : bool OldSuppressWith;
14306 31040 : unsigned int rw;
14307 31040 : unsigned int Field;
14308 31040 : unsigned int FieldType;
14309 31040 : unsigned int Record;
14310 31040 : unsigned int RecordType;
14311 31040 : unsigned int Ref;
14312 :
14313 31040 : OldSuppressWith = SuppressWith;
14314 31040 : SuppressWith = true;
14315 : /*
14316 : now the WITH cannot look at the stack of outstanding WITH records.
14317 : */
14318 31040 : M2Quads_PopTFtok (&Field, &FieldType, &fieldtok);
14319 31040 : PopTFrwtok (&Record, &RecordType, &rw, &rectok);
14320 31040 : Ref = SymbolTable_MakeComponentRef (SymbolTable_MakeComponentRecord (fieldtok, SymbolTable_RightValue, Record), Field);
14321 31040 : SymbolTable_PutVarConst (Ref, IsReadOnly (Record));
14322 62080 : GenQuadO (fieldtok, M2Quads_RecordFieldOp, Ref, Record, Field, true);
14323 31040 : PushTFrwtok (Ref, FieldType, rw, fieldtok);
14324 31040 : SuppressWith = OldSuppressWith;
14325 31040 : }
14326 :
14327 :
14328 : /*
14329 : SafeCheckWithField - only call CheckWithReference if the top of stack
14330 : contains a record field.
14331 : */
14332 :
14333 12100 : static void SafeCheckWithField (void)
14334 : {
14335 12100 : if (SymbolTable_IsRecordField (M2Quads_OperandT (1)))
14336 : {
14337 24 : M2Quads_CheckWithReference ();
14338 : }
14339 12100 : }
14340 :
14341 :
14342 : /*
14343 : PushConstructor -
14344 : */
14345 :
14346 48360 : static void PushConstructor (unsigned int sym)
14347 : {
14348 48360 : M2Quads_ConstructorFrame c;
14349 :
14350 48360 : Storage_ALLOCATE ((void **) &c, sizeof (M2Quads__T1));
14351 48360 : c->type = SymbolTable_SkipType (sym);
14352 48360 : c->index = 1;
14353 48360 : M2StackAddress_PushAddress (ConstructorStack, reinterpret_cast <void *> (c));
14354 48360 : }
14355 :
14356 :
14357 : /*
14358 : AddFieldTo - adds field to value.
14359 : */
14360 :
14361 25842 : static unsigned int AddFieldTo (unsigned int value, unsigned int field, unsigned int valuetok, unsigned int fieldtok)
14362 : {
14363 25842 : if (SymbolTable_IsSet (SymbolTable_GetDType (value)))
14364 : {
14365 12100 : SymbolTable_PutConstSet (value);
14366 12100 : M2Quads_PushTtok (value, valuetok);
14367 12100 : M2Quads_PushTtok (field, fieldtok);
14368 12100 : M2Quads_BuildInclBit ();
14369 12100 : M2Quads_PopT (&value);
14370 : }
14371 : else
14372 : {
14373 13742 : SymbolTable_PushValue (value);
14374 13742 : M2ALU_AddField (fieldtok, field);
14375 13742 : SymbolTable_PopValue (value);
14376 : }
14377 25842 : return value;
14378 : /* static analysis guarentees a RETURN statement will be used before here. */
14379 : __builtin_unreachable ();
14380 : }
14381 :
14382 :
14383 : /*
14384 : CheckLogicalOperator - returns a logical operator if the operands imply
14385 : a logical operation should be performed.
14386 : */
14387 :
14388 79026 : static NameKey_Name CheckLogicalOperator (NameKey_Name Tok, unsigned int left, unsigned int lefttype)
14389 : {
14390 79026 : if ((((Tok == M2Reserved_PlusTok) || (Tok == M2Reserved_TimesTok)) || (Tok == M2Reserved_DivideTok)) || (Tok == M2Reserved_MinusTok))
14391 : {
14392 : /* --fixme-- when we add complex arithmetic, we must check constructor is not a complex constant. */
14393 69763 : if ((((lefttype != SymbolTable_NulSym) && (SymbolTable_IsSet (SymbolTable_SkipType (lefttype)))) || (SymbolTable_IsConstSet (left))) || (SymbolTable_IsConstructor (left)))
14394 : {
14395 : /* avoid gcc warning by using compound statement even if not strictly necessary. */
14396 1482 : if (Tok == M2Reserved_PlusTok)
14397 : {
14398 1008 : return LogicalOrTok;
14399 : }
14400 474 : else if (Tok == M2Reserved_DivideTok)
14401 : {
14402 : /* avoid dangling else. */
14403 124 : return LogicalXorTok;
14404 : }
14405 350 : else if (Tok == M2Reserved_TimesTok)
14406 : {
14407 : /* avoid dangling else. */
14408 284 : return LogicalAndTok;
14409 : }
14410 66 : else if (Tok == M2Reserved_MinusTok)
14411 : {
14412 : /* avoid dangling else. */
14413 66 : return LogicalDifferenceTok;
14414 : }
14415 : }
14416 : }
14417 : return Tok;
14418 : /* static analysis guarentees a RETURN statement will be used before here. */
14419 : __builtin_unreachable ();
14420 : }
14421 :
14422 :
14423 : /*
14424 : CheckDivModRem - initiates calls to check the divisor for DIV, MOD, REM
14425 : expressions.
14426 : */
14427 :
14428 78426 : static void CheckDivModRem (unsigned int TokPos, NameKey_Name tok, unsigned int d, unsigned int e)
14429 : {
14430 78426 : if (tok == M2Reserved_DivTok)
14431 : {
14432 6789 : BuildRange (M2Range_InitWholeZeroDivisionCheck (TokPos, d, e));
14433 : }
14434 71637 : else if (tok == M2Reserved_ModTok)
14435 : {
14436 : /* avoid dangling else. */
14437 2378 : BuildRange (M2Range_InitWholeZeroDivisionCheck (TokPos, d, e));
14438 : }
14439 69259 : else if (tok == M2Reserved_RemTok)
14440 : {
14441 : /* avoid dangling else. */
14442 96 : BuildRange (M2Range_InitWholeZeroRemainderCheck (TokPos, d, e));
14443 : }
14444 78426 : }
14445 :
14446 :
14447 : /*
14448 : doConvert - convert, sym, to a new symbol with, type.
14449 : Return the new symbol.
14450 : */
14451 :
14452 5220 : static unsigned int doConvert (unsigned int type, unsigned int sym)
14453 : {
14454 5220 : if ((SymbolTable_GetSType (sym)) != type)
14455 : {
14456 1086 : M2Quads_PushTF (M2Base_Convert, static_cast<unsigned int> (SymbolTable_NulSym));
14457 1086 : M2Quads_PushT (type);
14458 1086 : M2Quads_PushT (sym);
14459 1086 : M2Quads_PushT (static_cast<unsigned int> (2)); /* Two parameters */
14460 1086 : BuildConvertFunction (M2Base_Convert, false); /* Two parameters */
14461 1080 : M2Quads_PopT (&sym);
14462 : }
14463 5214 : return sym;
14464 : /* static analysis guarentees a RETURN statement will be used before here. */
14465 : __builtin_unreachable ();
14466 : }
14467 :
14468 :
14469 : /*
14470 : doBuildBinaryOp - build the binary op, with or without type
14471 : checking.
14472 : */
14473 :
14474 92464 : static void doBuildBinaryOp (bool checkTypes, bool checkOverflow)
14475 : {
14476 92464 : DynamicStrings_String s;
14477 92464 : NameKey_Name NewOp;
14478 92464 : NameKey_Name Operator;
14479 92464 : unsigned int OperatorPos;
14480 92464 : unsigned int OldPos;
14481 92464 : unsigned int leftrw;
14482 92464 : unsigned int rightrw;
14483 92464 : unsigned int t1;
14484 92464 : unsigned int f1;
14485 92464 : unsigned int t2;
14486 92464 : unsigned int f2;
14487 92464 : unsigned int lefttype;
14488 92464 : unsigned int righttype;
14489 92464 : unsigned int left;
14490 92464 : unsigned int right;
14491 92464 : unsigned int leftpos;
14492 92464 : unsigned int rightpos;
14493 92464 : unsigned int value;
14494 :
14495 92464 : Operator = static_cast<NameKey_Name> (M2Quads_OperandT (2));
14496 92464 : if (Operator == M2Reserved_OrTok)
14497 : {
14498 3630 : CheckBooleanId ();
14499 3630 : PopBooltok (&t1, &f1, &rightpos);
14500 3630 : M2Quads_PopTtok (&Operator, &OperatorPos);
14501 3630 : PopBooltok (&t2, &f2, &leftpos);
14502 3630 : M2Debug_Assert (f2 == 0);
14503 3630 : OperatorPos = M2LexBuf_MakeVirtualTok (OperatorPos, leftpos, rightpos);
14504 3630 : PushBooltok (Merge (t1, t2), f1, OperatorPos);
14505 : }
14506 88834 : else if ((Operator == M2Reserved_AndTok) || (Operator == M2Reserved_AmbersandTok))
14507 : {
14508 : /* avoid dangling else. */
14509 9808 : CheckBooleanId ();
14510 9808 : PopBooltok (&t1, &f1, &rightpos);
14511 9808 : M2Quads_PopTtok (&Operator, &OperatorPos);
14512 9808 : PopBooltok (&t2, &f2, &leftpos);
14513 9808 : M2Debug_Assert (t2 == 0);
14514 9808 : OperatorPos = M2LexBuf_MakeVirtualTok (OperatorPos, leftpos, rightpos);
14515 9808 : PushBooltok (t1, Merge (f1, f2), OperatorPos);
14516 : }
14517 : else
14518 : {
14519 : /* avoid dangling else. */
14520 79026 : PopTFrwtok (&right, &righttype, &rightrw, &rightpos);
14521 79026 : M2Quads_PopTtok (&Operator, &OperatorPos);
14522 79026 : PopTFrwtok (&left, &lefttype, &leftrw, &leftpos);
14523 79026 : MarkAsRead (rightrw);
14524 79026 : MarkAsRead (leftrw);
14525 79026 : NewOp = CheckLogicalOperator (Operator, left, lefttype); /* right, righttype, */
14526 79026 : if (NewOp == Operator)
14527 : {
14528 : /* avoid dangling else. */
14529 : /*
14530 : BinaryOps and UnaryOps only work with immediate and
14531 : offset addressing. This is fine for calculating
14532 : array and record offsets but we need to get the real
14533 : values to perform normal arithmetic. Not address
14534 : arithmetic.
14535 :
14536 : However the set operators will dereference LValues
14537 : (to optimize large set arithemetic)
14538 : */
14539 77544 : if ((SymbolTable_GetMode (right)) == SymbolTable_LeftValue)
14540 : {
14541 298 : value = SymbolTable_MakeTemporary (rightpos, SymbolTable_RightValue);
14542 298 : SymbolTable_PutVar (value, righttype);
14543 298 : CheckPointerThroughNil (rightpos, right);
14544 298 : doIndrX (rightpos, value, right);
14545 298 : right = value;
14546 : }
14547 77544 : if ((SymbolTable_GetMode (left)) == SymbolTable_LeftValue)
14548 : {
14549 852 : value = SymbolTable_MakeTemporary (leftpos, SymbolTable_RightValue);
14550 852 : SymbolTable_PutVar (value, lefttype);
14551 852 : CheckPointerThroughNil (leftpos, left);
14552 852 : doIndrX (leftpos, value, left);
14553 852 : left = value;
14554 : }
14555 : }
14556 : /* CheckForGenericNulSet(e1, e2, t1, t2) */
14557 79026 : OldPos = OperatorPos;
14558 79026 : OperatorPos = M2LexBuf_MakeVirtualTok (OperatorPos, leftpos, rightpos);
14559 79026 : if (((Operator == M2Reserved_PlusTok) && (SymbolTable_IsConstString (left))) && (SymbolTable_IsConstString (right)))
14560 : {
14561 492 : value = SymbolTable_MakeConstString (OperatorPos, NameKey_NulName);
14562 492 : SymbolTable_PutConstStringKnown (OperatorPos, value, NameKey_NulName, false, false);
14563 492 : GenQuadOtok (OperatorPos, MakeOp (M2Reserved_PlusTok), value, left, right, false, OperatorPos, leftpos, rightpos);
14564 : }
14565 : else
14566 : {
14567 78534 : if (checkTypes)
14568 : {
14569 60212 : BuildRange (M2Range_InitTypesExpressionCheck (OperatorPos, left, right, false, false));
14570 : }
14571 121899 : value = SymbolTable_MakeTemporaryFromExpressions (OperatorPos, right, left, AreConstant ((SymbolTable_IsConst (left)) && (SymbolTable_IsConst (right))));
14572 78426 : CheckDivModRem (OperatorPos, NewOp, value, right);
14573 78426 : if (DebugTokPos)
14574 : {
14575 : s = DynamicStrings_InitStringCharStar (NameKey_KeyToCharStar (M2LexBuf_GetTokenName (Operator)));
14576 : M2Error_WarnStringAt (s, OldPos);
14577 : s = DynamicStrings_InitString ((const char *) "left", 4);
14578 : M2Error_WarnStringAt (s, leftpos);
14579 : s = DynamicStrings_InitString ((const char *) "right", 5);
14580 : M2Error_WarnStringAt (s, rightpos);
14581 : s = DynamicStrings_InitString ((const char *) "caret", 5);
14582 : M2Error_WarnStringAt (s, OldPos);
14583 : s = DynamicStrings_InitString ((const char *) "combined", 8);
14584 : M2Error_WarnStringAt (s, OperatorPos);
14585 : }
14586 : /* MetaErrorT1 (GetDeclaredMod (t), 'in binary with a {%1av}', t) */
14587 78426 : GenQuadOtok (OperatorPos, MakeOp (NewOp), value, left, right, checkOverflow, OperatorPos, leftpos, rightpos);
14588 : }
14589 78918 : M2Quads_PushTFtok (value, SymbolTable_GetSType (value), OperatorPos);
14590 : }
14591 92356 : }
14592 :
14593 :
14594 : /*
14595 : AreConstant - returns immediate addressing mode if b is true else
14596 : offset mode is returned. b determines whether the
14597 : operands are all constant - in which case we can use
14598 : a constant temporary variable.
14599 : */
14600 :
14601 159958 : static SymbolTable_ModeOfAddr AreConstant (bool b)
14602 : {
14603 159958 : if (b)
14604 : {
14605 : return SymbolTable_ImmediateValue;
14606 : }
14607 : else
14608 : {
14609 60083 : return SymbolTable_RightValue;
14610 : }
14611 : /* static analysis guarentees a RETURN statement will be used before here. */
14612 : __builtin_unreachable ();
14613 : }
14614 :
14615 :
14616 : /*
14617 : ConvertBooleanToVariable - converts a BoolStack(i) from a Boolean True|False
14618 : exit pair into a variable containing the value TRUE or
14619 : FALSE. The parameter i is relative to the top
14620 : of the stack.
14621 : */
14622 :
14623 7378 : static void ConvertBooleanToVariable (unsigned int tok, unsigned int i)
14624 : {
14625 7378 : unsigned int Des;
14626 7378 : M2Quads_BoolFrame f;
14627 :
14628 7378 : M2Debug_Assert (IsBoolean (i));
14629 : /* We need to convert the boolean top of stack into a variable or
14630 : constant boolean. */
14631 14756 : Des = SymbolTable_MakeTemporary (tok, AreConstant (M2Quads_IsInConstExpression ()));
14632 7378 : SymbolTable_PutVar (Des, M2Base_Boolean);
14633 7378 : SymbolTable_PutVarConditional (Des, true);
14634 7378 : M2Quads_PushTtok (Des, tok); /* we have just increased the stack so we must use i+1 */
14635 7378 : f = static_cast<M2Quads_BoolFrame> (M2StackAddress_PeepAddress (BoolStack, i+1)); /* we have just increased the stack so we must use i+1 */
14636 14756 : PushBool (f->TrueExit, f->FalseExit);
14637 7378 : BuildAssignmentWithoutBounds (tok, false, true);
14638 : /* Restored stack after the BuildAssign... above. */
14639 7378 : f = static_cast<M2Quads_BoolFrame> (M2StackAddress_PeepAddress (BoolStack, i));
14640 7378 : f->TrueExit = Des; /* Alter Stack(i) to contain the variable. */
14641 7378 : f->FalseExit = M2Base_Boolean; /* Alter Stack(i) to contain the variable. */
14642 7378 : f->BooleanOp = false; /* No longer a Boolean True|False pair. */
14643 7378 : f->Unbounded = SymbolTable_NulSym; /* No longer a Boolean True|False pair. */
14644 7378 : f->Dimension = 0;
14645 7378 : f->ReadWrite = SymbolTable_NulSym;
14646 7378 : f->tokenno = tok;
14647 7378 : f->Annotation = DynamicStrings_KillString (f->Annotation);
14648 7378 : f->Annotation = DynamicStrings_InitString ((const char *) "%1s(%1d)|%2s(%2d)||boolean var|type", 35);
14649 7378 : f->RangeDep = 0;
14650 7378 : }
14651 :
14652 :
14653 : /*
14654 : DumpQuadSummary -
14655 : */
14656 :
14657 0 : static void DumpQuadSummary (unsigned int quad)
14658 : {
14659 0 : M2Quads_QuadFrame f;
14660 :
14661 0 : if (quad != 0)
14662 : {
14663 0 : f = GetQF (quad);
14664 0 : M2Printf_printf2 ((const char *) "%d op3 = %d\\n", 14, (const unsigned char *) &quad, (sizeof (quad)-1), (const unsigned char *) &f->Operand3, (sizeof (f->Operand3)-1));
14665 : }
14666 0 : }
14667 :
14668 :
14669 : /*
14670 : BuildRelOpFromBoolean - builds a relational operator sequence of quadruples
14671 : instead of using a temporary boolean variable.
14672 : This function can only be used when we perform
14673 : the following translation:
14674 :
14675 : (a=b) # (c=d) alternatively (a=b) = (c=d)
14676 : ^ ^
14677 :
14678 : it only allows # = to be used as >= <= > < all
14679 : assume a particular value for TRUE and FALSE.
14680 : (In which case the user should specify ORD)
14681 :
14682 :
14683 : before
14684 :
14685 : q if r1 op1 op2 t2
14686 : q+1 Goto f2
14687 : ...
14688 : q+n if r2 op3 op4 t1
14689 : q+n+1 Goto f1
14690 :
14691 : after (in case of =)
14692 :
14693 : q if r1 op1 op2 q+2
14694 : q+1 Goto q+4
14695 : q+2 if r2 op3 op4 t
14696 : q+3 Goto f
14697 : q+4 if r2 op3 op4 f
14698 : q+5 Goto t
14699 :
14700 : after (in case of #)
14701 :
14702 : q if r1 op1 op2 q+2
14703 : q+1 Goto q+n+2
14704 : q+2 ...
14705 : ... ...
14706 : q+n if r2 op3 op4 f
14707 : q+n+1 Goto t
14708 : q+n+2 if r2 op3 op4 t
14709 : q+n+3 Goto f
14710 :
14711 : The Stack is expected to contain:
14712 :
14713 :
14714 : Entry Exit
14715 : ===== ====
14716 :
14717 : Ptr ->
14718 : +------------+
14719 : | t1 | f1 |
14720 : |------------|
14721 : | Operator | <- Ptr
14722 : |------------| +------------+
14723 : | t2 | f2 | | t | f |
14724 : |------------| |------------|
14725 :
14726 :
14727 : */
14728 :
14729 0 : static void BuildRelOpFromBoolean (unsigned int tokpos)
14730 : {
14731 0 : unsigned int Tok;
14732 0 : unsigned int t1;
14733 0 : unsigned int f1;
14734 0 : unsigned int t2;
14735 0 : unsigned int f2;
14736 0 : M2Quads_QuadFrame f;
14737 :
14738 0 : M2Debug_Assert ((IsBoolean (1)) && (IsBoolean (3)));
14739 0 : if ((M2Quads_OperandT (2)) == M2Reserved_EqualTok)
14740 : {
14741 : /* Are the two boolean expressions the same? */
14742 0 : PopBool (&t1, &f1);
14743 0 : M2Quads_PopT (&Tok);
14744 0 : PopBool (&t2, &f2);
14745 : /* Give the false exit a second chance. */
14746 0 : BackPatch (t2, t1); /* q if _ _ q+2 */
14747 0 : BackPatch (f2, NextQuad); /* q+1 if _ _ q+4 */
14748 0 : M2Debug_Assert (NextQuad == (f1+1)); /* q+1 if _ _ q+4 */
14749 0 : f = GetQF (t1);
14750 0 : GenQuadO (tokpos, f->Operator, f->Operand1, f->Operand2, 0, false);
14751 0 : GenQuadO (tokpos, M2Quads_GotoOp, SymbolTable_NulSym, SymbolTable_NulSym, 0, false);
14752 0 : PushBooltok (Merge (NextQuad-1, t1), Merge (NextQuad-2, f1), tokpos);
14753 : }
14754 0 : else if (((M2Quads_OperandT (2)) == M2Reserved_HashTok) || ((M2Quads_OperandT (2)) == M2Reserved_LessGreaterTok))
14755 : {
14756 : /* avoid dangling else. */
14757 0 : if (M2Options_CompilerDebugging)
14758 : {
14759 0 : M2Printf_printf0 ((const char *) "BuildRelOpFromBoolean (NotEqualTok)\\n", 37);
14760 0 : M2Quads_DisplayStack ();
14761 : }
14762 : /* Are the two boolean expressions different? */
14763 0 : PopBool (&t1, &f1);
14764 0 : M2Quads_PopT (&Tok);
14765 0 : PopBool (&t2, &f2);
14766 0 : if (M2Options_CompilerDebugging)
14767 : {
14768 0 : M2Printf_printf2 ((const char *) "t1 = %d, f1 = %d\\n", 18, (const unsigned char *) &t1, (sizeof (t1)-1), (const unsigned char *) &f1, (sizeof (f1)-1));
14769 0 : M2Printf_printf2 ((const char *) "t2 = %d, f2 = %d\\n", 18, (const unsigned char *) &t2, (sizeof (t2)-1), (const unsigned char *) &f2, (sizeof (f2)-1));
14770 0 : DumpQuadSummary (t1);
14771 0 : DumpQuadSummary (f1);
14772 0 : DumpQuadSummary (t2);
14773 0 : DumpQuadSummary (f2);
14774 : }
14775 : /* Give the false exit a second chance. */
14776 0 : BackPatch (t2, t1); /* q if _ _ q+2 */
14777 0 : BackPatch (f2, NextQuad); /* q+1 if _ _ q+4 */
14778 0 : M2Debug_Assert (NextQuad == (f1+1)); /* q+1 if _ _ q+4 */
14779 0 : f = GetQF (t1);
14780 0 : GenQuadO (tokpos, f->Operator, f->Operand1, f->Operand2, 0, false);
14781 0 : GenQuadO (tokpos, M2Quads_GotoOp, SymbolTable_NulSym, SymbolTable_NulSym, 0, false);
14782 0 : PushBooltok (Merge (NextQuad-2, f1), Merge (NextQuad-1, t1), tokpos);
14783 : }
14784 : else
14785 : {
14786 : /* avoid dangling else. */
14787 0 : M2MetaError_MetaError0 ((const char *) "only allowed to use the relation operators {%Ek=} {%Ek#} rather than {%Ek<} or {%Ek>} on {%EkBOOLEAN} expressions as these do not imply an ordinal value for {%kTRUE} or {%kFALSE}", 178);
14788 : }
14789 0 : }
14790 :
14791 :
14792 : /*
14793 : CheckVariableOrConstantOrProcedure - checks to make sure sym is a variable, constant or procedure.
14794 : */
14795 :
14796 184592 : static void CheckVariableOrConstantOrProcedure (unsigned int tokpos, unsigned int sym)
14797 : {
14798 184592 : unsigned int type;
14799 :
14800 184592 : type = SymbolTable_GetSType (sym);
14801 184592 : if (SymbolTable_IsUnknown (sym))
14802 : {
14803 : /* Spellcheck. */
14804 12 : M2MetaError_MetaErrorT1 (tokpos, (const char *) "{%1EUad} has not been declared {%1&s}", 37, sym);
14805 12 : SymbolTable_UnknownReported (sym);
14806 : }
14807 184580 : else if ((M2System_IsPseudoSystemFunction (sym)) || (M2Base_IsPseudoBaseFunction (sym)))
14808 : {
14809 : /* avoid dangling else. */
14810 6 : M2MetaError_MetaErrorT1 (tokpos, (const char *) "{%1Ead} expected a variable, procedure, constant or expression, not an intrinsic procedure function", 99, sym);
14811 : }
14812 184574 : else if (((((! (SymbolTable_IsConst (sym))) && (! (SymbolTable_IsVar (sym)))) && (! (SymbolTable_IsProcedure (sym)))) && (! (SymbolTable_IsTemporary (sym)))) && ! MustNotCheckBounds)
14813 : {
14814 : /* avoid dangling else. */
14815 0 : M2MetaError_MetaErrorsT1 (tokpos, (const char *) "{%1Ead} expected a variable, procedure, constant or expression", 62, (const char *) "and it was declared as a {%1Ddv}", 32, sym);
14816 : }
14817 184574 : else if ((type != SymbolTable_NulSym) && (SymbolTable_IsArray (type)))
14818 : {
14819 : /* avoid dangling else. */
14820 0 : M2MetaError_MetaErrorsT1 (tokpos, (const char *) "{%1EU} not expecting an array variable as an operand for either comparison or binary operation", 94, (const char *) "it was declared as a {%1Ddv}", 28, sym);
14821 : }
14822 184574 : else if (((SymbolTable_IsConstString (sym)) && (SymbolTable_IsConstStringKnown (sym))) && ((SymbolTable_GetStringLength (tokpos, sym)) > 1))
14823 : {
14824 : /* avoid dangling else. */
14825 0 : M2MetaError_MetaErrorT1 (tokpos, (const char *) "{%1EU} not expecting a string constant as an operand for either comparison or binary operation", 94, sym);
14826 : }
14827 184592 : }
14828 :
14829 :
14830 : /*
14831 : MakeOp - returns the equalent quadruple operator to a token, t.
14832 : */
14833 :
14834 171214 : static M2Quads_QuadOperator MakeOp (NameKey_Name t)
14835 : {
14836 171214 : if (t == ArithPlusTok)
14837 : {
14838 : return M2Quads_ArithAddOp;
14839 : }
14840 171214 : else if (t == M2Reserved_PlusTok)
14841 : {
14842 : /* avoid dangling else. */
14843 : return M2Quads_AddOp;
14844 : }
14845 146255 : else if (t == M2Reserved_MinusTok)
14846 : {
14847 : /* avoid dangling else. */
14848 : return M2Quads_SubOp;
14849 : }
14850 123331 : else if (t == M2Reserved_DivTok)
14851 : {
14852 : /* avoid dangling else. */
14853 : return M2Quads_DivM2Op;
14854 : }
14855 116542 : else if (t == M2Reserved_DivideTok)
14856 : {
14857 : /* avoid dangling else. */
14858 : return M2Quads_DivTruncOp;
14859 : }
14860 114084 : else if (t == M2Reserved_RemTok)
14861 : {
14862 : /* avoid dangling else. */
14863 : return M2Quads_ModTruncOp;
14864 : }
14865 113988 : else if (t == M2Reserved_ModTok)
14866 : {
14867 : /* avoid dangling else. */
14868 : return M2Quads_ModM2Op;
14869 : }
14870 111610 : else if (t == M2Reserved_TimesTok)
14871 : {
14872 : /* avoid dangling else. */
14873 : return M2Quads_MultOp;
14874 : }
14875 93760 : else if (t == M2Reserved_HashTok)
14876 : {
14877 : /* avoid dangling else. */
14878 : return M2Quads_IfNotEquOp;
14879 : }
14880 80972 : else if (t == M2Reserved_LessGreaterTok)
14881 : {
14882 : /* avoid dangling else. */
14883 : return M2Quads_IfNotEquOp;
14884 : }
14885 80888 : else if (t == M2Reserved_GreaterEqualTok)
14886 : {
14887 : /* avoid dangling else. */
14888 : return M2Quads_IfGreEquOp;
14889 : }
14890 70250 : else if (t == M2Reserved_LessEqualTok)
14891 : {
14892 : /* avoid dangling else. */
14893 : return M2Quads_IfLessEquOp;
14894 : }
14895 65398 : else if (t == M2Reserved_EqualTok)
14896 : {
14897 : /* avoid dangling else. */
14898 : return M2Quads_IfEquOp;
14899 : }
14900 17716 : else if (t == M2Reserved_LessTok)
14901 : {
14902 : /* avoid dangling else. */
14903 : return M2Quads_IfLessOp;
14904 : }
14905 10108 : else if (t == M2Reserved_GreaterTok)
14906 : {
14907 : /* avoid dangling else. */
14908 : return M2Quads_IfGreOp;
14909 : }
14910 3952 : else if (t == M2Reserved_InTok)
14911 : {
14912 : /* avoid dangling else. */
14913 : return M2Quads_IfInOp;
14914 : }
14915 1464 : else if (t == LogicalOrTok)
14916 : {
14917 : /* avoid dangling else. */
14918 : return M2Quads_LogicalOrOp;
14919 : }
14920 474 : else if (t == LogicalAndTok)
14921 : {
14922 : /* avoid dangling else. */
14923 : return M2Quads_LogicalAndOp;
14924 : }
14925 190 : else if (t == LogicalXorTok)
14926 : {
14927 : /* avoid dangling else. */
14928 : return M2Quads_LogicalXorOp;
14929 : }
14930 66 : else if (t == LogicalDifferenceTok)
14931 : {
14932 : /* avoid dangling else. */
14933 : return M2Quads_LogicalDiffOp;
14934 : }
14935 : else
14936 : {
14937 : /* avoid dangling else. */
14938 0 : M2Error_InternalError ((const char *) "binary operation not implemented yet", 36);
14939 : }
14940 : ReturnException ("/home/worker/buildworker/tiber-lcov/build/gcc/m2/gm2-compiler/M2Quads.def", 20, 1);
14941 : __builtin_unreachable ();
14942 : }
14943 :
14944 :
14945 : /*
14946 : GenQuadO - generate a quadruple with Operation, Op1, Op2, Op3, overflow.
14947 : */
14948 :
14949 5433301 : static void GenQuadO (unsigned int TokPos, M2Quads_QuadOperator Operation, unsigned int Op1, unsigned int Op2, unsigned int Op3, bool overflow)
14950 : {
14951 1209094 : GenQuadOTrash (TokPos, Operation, Op1, Op2, Op3, overflow, SymbolTable_NulSym);
14952 719435 : }
14953 :
14954 :
14955 : /*
14956 : GenQuadOTrash - generate a quadruple with Operation, Op1, Op2, Op3, overflow.
14957 : */
14958 :
14959 5435131 : static void GenQuadOTrash (unsigned int TokPos, M2Quads_QuadOperator Operation, unsigned int Op1, unsigned int Op2, unsigned int Op3, bool overflow, unsigned int trash)
14960 : {
14961 5435131 : M2Quads_QuadFrame f;
14962 :
14963 : /* WriteString('Potential Quad: ') ; */
14964 5435131 : if (QuadrupleGeneration)
14965 : {
14966 5432886 : if (NextQuad != Head)
14967 : {
14968 5417587 : f = GetQF (NextQuad-1);
14969 5417587 : f->Next = NextQuad;
14970 : }
14971 5432886 : PutQuadO (NextQuad, Operation, Op1, Op2, Op3, overflow);
14972 5432886 : f = GetQF (NextQuad);
14973 5432886 : f->Trash = trash;
14974 5432886 : f->Next = 0;
14975 5432886 : f->LineNo = M2LexBuf_GetLineNo ();
14976 5432886 : if (TokPos == M2LexBuf_UnknownTokenNo)
14977 : {
14978 3249145 : f->TokenNo = M2LexBuf_GetTokenNo ();
14979 : }
14980 : else
14981 : {
14982 2183741 : f->TokenNo = TokPos;
14983 : }
14984 5432886 : if (M2Options_GetDebugTraceQuad ())
14985 : {
14986 0 : M2Printf_printf0 ((const char *) "generating: ", 12);
14987 0 : M2Quads_DisplayQuad (NextQuad);
14988 : }
14989 : /* MetaErrorT1 (TokenNo, '{%1On}', NextQuad) */
14990 5432886 : CheckBreak (NextQuad);
14991 5432886 : NewQuad (&NextQuad);
14992 : }
14993 5435131 : }
14994 :
14995 :
14996 : /*
14997 : GenQuad - Generate a quadruple with Operation, Op1, Op2, Op3.
14998 : */
14999 :
15000 3178425 : static void GenQuad (M2Quads_QuadOperator Operation, unsigned int Op1, unsigned int Op2, unsigned int Op3)
15001 : {
15002 2193582 : GenQuadO (M2LexBuf_UnknownTokenNo, Operation, Op1, Op2, Op3, true);
15003 622185 : }
15004 :
15005 :
15006 : /*
15007 : GenQuadOtok - generate a quadruple with Operation, Op1, Op2, Op3, overflow.
15008 : */
15009 :
15010 577912 : static void GenQuadOtok (unsigned int TokPos, M2Quads_QuadOperator Operation, unsigned int Op1, unsigned int Op2, unsigned int Op3, bool overflow, unsigned int Op1Pos, unsigned int Op2Pos, unsigned int Op3Pos)
15011 : {
15012 485616 : GenQuadOTypetok (TokPos, Operation, Op1, Op2, Op3, overflow, true, Op1Pos, Op2Pos, Op3Pos);
15013 252807 : }
15014 :
15015 :
15016 : /*
15017 : GenQuadOTypetok - assigns the fields of the quadruple with
15018 : the parameters.
15019 : */
15020 :
15021 882387 : static void GenQuadOTypetok (unsigned int TokPos, M2Quads_QuadOperator Operation, unsigned int Op1, unsigned int Op2, unsigned int Op3, bool overflow, bool typecheck, unsigned int Op1Pos, unsigned int Op2Pos, unsigned int Op3Pos)
15022 : {
15023 882387 : M2Quads_QuadFrame f;
15024 :
15025 : /* WriteString('Potential Quad: ') ; */
15026 882387 : if (QuadrupleGeneration)
15027 : {
15028 881696 : if (NextQuad != Head)
15029 : {
15030 881696 : f = GetQF (NextQuad-1);
15031 881696 : f->Next = NextQuad;
15032 : }
15033 881696 : PutQuadOType (NextQuad, Operation, Op1, Op2, Op3, overflow, typecheck);
15034 881696 : f = GetQF (NextQuad);
15035 881696 : f->Next = 0;
15036 881696 : f->LineNo = M2LexBuf_GetLineNo ();
15037 881696 : if (TokPos == M2LexBuf_UnknownTokenNo)
15038 : {
15039 0 : f->TokenNo = M2LexBuf_GetTokenNo ();
15040 : }
15041 : else
15042 : {
15043 881696 : f->TokenNo = TokPos;
15044 : }
15045 881696 : f->op1pos = Op1Pos;
15046 881696 : f->op2pos = Op2Pos;
15047 881696 : f->op3pos = Op3Pos;
15048 881696 : if (M2Options_GetDebugTraceQuad ())
15049 : {
15050 0 : M2Printf_printf0 ((const char *) "generating: ", 12);
15051 0 : M2Quads_DisplayQuad (NextQuad);
15052 : }
15053 : /* MetaErrorT1 (TokenNo, '{%1On}', NextQuad) */
15054 881696 : CheckBreak (NextQuad);
15055 881696 : NewQuad (&NextQuad);
15056 : }
15057 882387 : }
15058 :
15059 :
15060 : /*
15061 : DumpUntil - dump all quadruples until we seen the ending quadruple
15062 : with procsym in the third operand.
15063 : Return the quad number containing the match.
15064 : */
15065 :
15066 0 : static unsigned int DumpUntil (M2Quads_QuadOperator ending, unsigned int procsym, unsigned int quad)
15067 : {
15068 0 : M2Quads_QuadOperator op;
15069 0 : unsigned int op1;
15070 0 : unsigned int op2;
15071 0 : unsigned int op3;
15072 0 : M2Quads_QuadFrame f;
15073 :
15074 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "\\n...\\n\\n", 9);
15075 0 : do {
15076 0 : M2Quads_GetQuad (quad, &op, &op1, &op2, &op3);
15077 0 : M2Quads_DisplayQuad (quad);
15078 0 : f = GetQF (quad);
15079 0 : quad = f->Next;
15080 0 : } while (! ((op == ending) && (op3 == procsym)));
15081 0 : return quad;
15082 : /* static analysis guarentees a RETURN statement will be used before here. */
15083 : __builtin_unreachable ();
15084 : }
15085 :
15086 :
15087 : /*
15088 : GetCtorInit - return the init procedure for the module.
15089 : */
15090 :
15091 0 : static unsigned int GetCtorInit (unsigned int sym)
15092 : {
15093 0 : unsigned int ctor;
15094 0 : unsigned int init;
15095 0 : unsigned int fini;
15096 0 : unsigned int dep;
15097 :
15098 0 : SymbolTable_GetModuleCtors (sym, &ctor, &init, &fini, &dep);
15099 0 : return init;
15100 : /* static analysis guarentees a RETURN statement will be used before here. */
15101 : __builtin_unreachable ();
15102 : }
15103 :
15104 :
15105 : /*
15106 : GetCtorFini - return the fini procedure for the module.
15107 : */
15108 :
15109 0 : static unsigned int GetCtorFini (unsigned int sym)
15110 : {
15111 0 : unsigned int ctor;
15112 0 : unsigned int init;
15113 0 : unsigned int fini;
15114 0 : unsigned int dep;
15115 :
15116 0 : SymbolTable_GetModuleCtors (sym, &ctor, &init, &fini, &dep);
15117 0 : return fini;
15118 : /* static analysis guarentees a RETURN statement will be used before here. */
15119 : __builtin_unreachable ();
15120 : }
15121 :
15122 :
15123 : /*
15124 : DumpQuadrupleFilter -
15125 : */
15126 :
15127 0 : static void DumpQuadrupleFilter (void)
15128 : {
15129 0 : M2Quads_QuadFrame f;
15130 0 : unsigned int i;
15131 0 : M2Quads_QuadOperator op;
15132 0 : unsigned int op1;
15133 0 : unsigned int op2;
15134 0 : unsigned int op3;
15135 :
15136 0 : i = Head;
15137 0 : while (i != 0)
15138 : {
15139 0 : M2Quads_GetQuad (i, &op, &op1, &op2, &op3);
15140 0 : if ((op == M2Quads_ProcedureScopeOp) && (M2LangDump_IsDumpRequired (op3, true)))
15141 : {
15142 0 : i = DumpUntil (M2Quads_KillLocalVarOp, op3, i);
15143 : }
15144 0 : else if ((op == M2Quads_InitStartOp) && (M2LangDump_IsDumpRequired (GetCtorInit (op3), true)))
15145 : {
15146 : /* avoid dangling else. */
15147 0 : i = DumpUntil (M2Quads_InitEndOp, op3, i);
15148 : }
15149 0 : else if ((op == M2Quads_FinallyStartOp) && (M2LangDump_IsDumpRequired (GetCtorFini (op3), true)))
15150 : {
15151 : /* avoid dangling else. */
15152 0 : i = DumpUntil (M2Quads_FinallyEndOp, op3, i);
15153 : }
15154 : else
15155 : {
15156 : /* avoid dangling else. */
15157 0 : f = GetQF (i);
15158 0 : i = f->Next;
15159 : }
15160 : }
15161 0 : }
15162 :
15163 :
15164 : /*
15165 : DumpQuadrupleAll - dump all quadruples.
15166 : */
15167 :
15168 0 : static void DumpQuadrupleAll (void)
15169 : {
15170 0 : M2Quads_QuadFrame f;
15171 0 : unsigned int i;
15172 :
15173 0 : i = Head;
15174 0 : while (i != 0)
15175 : {
15176 0 : M2Quads_DisplayQuad (i);
15177 0 : f = GetQF (i);
15178 0 : i = f->Next;
15179 : }
15180 0 : }
15181 :
15182 :
15183 : /*
15184 : BackPatch - Makes each of the quadruples on the list pointed to by
15185 : QuadNo take quadruple Value as a target.
15186 : */
15187 :
15188 419205 : static void BackPatch (unsigned int QuadNo, unsigned int Value)
15189 : {
15190 419205 : unsigned int i;
15191 419205 : M2Quads_QuadFrame f;
15192 :
15193 419205 : if (QuadrupleGeneration)
15194 : {
15195 666401 : while (QuadNo != 0)
15196 : {
15197 247213 : f = GetQF (QuadNo);
15198 247213 : i = f->Operand3; /* Next Link along the BackPatch */
15199 247213 : ManipulateReference (QuadNo, Value); /* Filling in the BackPatch. */
15200 247213 : QuadNo = i;
15201 : }
15202 : }
15203 419205 : }
15204 :
15205 :
15206 : /*
15207 : Merge - joins two quad lists, QuadList2 to the end of QuadList1.
15208 : A QuadList of value zero is a nul list.
15209 : */
15210 :
15211 54916 : static unsigned int Merge (unsigned int QuadList1, unsigned int QuadList2)
15212 : {
15213 54916 : unsigned int i;
15214 54916 : unsigned int j;
15215 54916 : M2Quads_QuadFrame f;
15216 :
15217 54916 : if (QuadList1 == 0)
15218 : {
15219 : return QuadList2;
15220 : }
15221 26970 : else if (QuadList2 == 0)
15222 : {
15223 : /* avoid dangling else. */
15224 : return QuadList1;
15225 : }
15226 : else
15227 : {
15228 : /* avoid dangling else. */
15229 : i = QuadList1;
15230 52842 : do {
15231 52842 : j = i;
15232 52842 : f = GetQF (i);
15233 52842 : i = f->Operand3;
15234 52842 : } while (! (i == 0));
15235 23690 : ManipulateReference (j, QuadList2);
15236 23690 : return QuadList1;
15237 : }
15238 : /* static analysis guarentees a RETURN statement will be used before here. */
15239 : __builtin_unreachable ();
15240 : }
15241 :
15242 :
15243 : /*
15244 : DisplayProcedureAttributes -
15245 : */
15246 :
15247 0 : static void DisplayProcedureAttributes (unsigned int proc)
15248 : {
15249 0 : if (SymbolTable_IsCtor (proc))
15250 : {
15251 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) " (ctor)", 7);
15252 : }
15253 0 : if (SymbolTable_IsPublic (proc))
15254 : {
15255 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) " (public)", 9);
15256 : }
15257 0 : if (SymbolTable_IsExtern (proc))
15258 : {
15259 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) " (extern)", 9);
15260 : }
15261 0 : if (SymbolTable_IsMonoName (proc))
15262 : {
15263 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) " (mononame)", 11);
15264 : }
15265 0 : }
15266 :
15267 :
15268 : /*
15269 : WriteQuad - Writes out the Quad BufferQuad.
15270 : */
15271 :
15272 0 : static void WriteQuad (unsigned int BufferQuad)
15273 : {
15274 0 : NameKey_Name n1;
15275 0 : NameKey_Name n2;
15276 0 : M2Quads_QuadFrame f;
15277 0 : NameKey_Name n;
15278 0 : unsigned int l;
15279 :
15280 0 : f = GetQF (BufferQuad);
15281 0 : M2Quads_WriteOperator (f->Operator);
15282 0 : M2Printf_fprintf1 (M2LangDump_GetDumpFile (), (const char *) " [%d]", 5, (const unsigned char *) &f->NoOfTimesReferenced, (sizeof (f->NoOfTimesReferenced)-1));
15283 0 : if (f->ConstExpr)
15284 : {
15285 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) " const ", 7);
15286 : }
15287 : else
15288 : {
15289 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) " ", 7);
15290 : }
15291 0 : switch (f->Operator)
15292 : {
15293 0 : case M2Quads_LastForIteratorOp:
15294 0 : M2Quads_WriteOperand (f->Operand1);
15295 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) " ", 2);
15296 0 : M2Quads_WriteOperand (f->Operand2);
15297 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) " ", 2);
15298 0 : M2Quads_WriteOperand (f->Operand3);
15299 0 : break;
15300 :
15301 0 : case M2Quads_HighOp:
15302 0 : M2Quads_WriteOperand (f->Operand1);
15303 0 : M2Printf_fprintf1 (M2LangDump_GetDumpFile (), (const char *) " %4d ", 7, (const unsigned char *) &f->Operand2, (sizeof (f->Operand2)-1));
15304 0 : M2Quads_WriteOperand (f->Operand3);
15305 0 : break;
15306 :
15307 0 : case M2Quads_InitAddressOp:
15308 0 : case M2Quads_SavePriorityOp:
15309 0 : case M2Quads_RestorePriorityOp:
15310 0 : case M2Quads_SubrangeLowOp:
15311 0 : case M2Quads_SubrangeHighOp:
15312 0 : case M2Quads_BecomesOp:
15313 0 : case M2Quads_InclOp:
15314 0 : case M2Quads_ExclOp:
15315 0 : case M2Quads_UnboundedOp:
15316 0 : case M2Quads_ReturnValueOp:
15317 0 : case M2Quads_FunctValueOp:
15318 0 : case M2Quads_NegateOp:
15319 0 : case M2Quads_AddrOp:
15320 0 : case M2Quads_StringConvertCnulOp:
15321 0 : case M2Quads_StringConvertM2nulOp:
15322 0 : case M2Quads_StringLengthOp:
15323 0 : M2Quads_WriteOperand (f->Operand1);
15324 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) " ", 2);
15325 0 : M2Quads_WriteOperand (f->Operand3);
15326 0 : break;
15327 :
15328 0 : case M2Quads_ElementSizeOp:
15329 0 : case M2Quads_IfInOp:
15330 0 : case M2Quads_IfNotInOp:
15331 0 : case M2Quads_IfNotEquOp:
15332 0 : case M2Quads_IfEquOp:
15333 0 : case M2Quads_IfLessOp:
15334 0 : case M2Quads_IfGreOp:
15335 0 : case M2Quads_IfLessEquOp:
15336 0 : case M2Quads_IfGreEquOp:
15337 0 : M2Quads_WriteOperand (f->Operand1);
15338 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) " ", 2);
15339 0 : M2Quads_WriteOperand (f->Operand2);
15340 0 : M2Printf_fprintf1 (M2LangDump_GetDumpFile (), (const char *) " %4d", 5, (const unsigned char *) &f->Operand3, (sizeof (f->Operand3)-1));
15341 0 : break;
15342 :
15343 0 : case M2Quads_InlineOp:
15344 0 : case M2Quads_RetryOp:
15345 0 : case M2Quads_TryOp:
15346 0 : case M2Quads_GotoOp:
15347 0 : M2Printf_fprintf1 (M2LangDump_GetDumpFile (), (const char *) "%4d", 3, (const unsigned char *) &f->Operand3, (sizeof (f->Operand3)-1));
15348 0 : break;
15349 :
15350 0 : case M2Quads_StatementNoteOp:
15351 0 : l = M2LexBuf_TokenToLineNo (f->Operand3, 0);
15352 0 : n = M2LexBuf_GetTokenName (f->Operand3);
15353 0 : M2Printf_fprintf4 (M2LangDump_GetDumpFile (), (const char *) "%a:%d:%a (tokenno %d)", 21, (const unsigned char *) &f->Operand1, (sizeof (f->Operand1)-1), (const unsigned char *) &l, (sizeof (l)-1), (const unsigned char *) &n, (sizeof (n)-1), (const unsigned char *) &f->Operand3, (sizeof (f->Operand3)-1));
15354 0 : break;
15355 :
15356 0 : case M2Quads_LineNumberOp:
15357 0 : M2Printf_fprintf2 (M2LangDump_GetDumpFile (), (const char *) "%a:%d", 5, (const unsigned char *) &f->Operand1, (sizeof (f->Operand1)-1), (const unsigned char *) &f->Operand3, (sizeof (f->Operand3)-1));
15358 0 : break;
15359 :
15360 0 : case M2Quads_EndFileOp:
15361 0 : n1 = SymbolTable_GetSymName (f->Operand3);
15362 0 : M2Printf_fprintf1 (M2LangDump_GetDumpFile (), (const char *) "%a", 2, (const unsigned char *) &n1, (sizeof (n1)-1));
15363 0 : break;
15364 :
15365 0 : case M2Quads_ThrowOp:
15366 0 : case M2Quads_ReturnOp:
15367 0 : case M2Quads_CallOp:
15368 0 : case M2Quads_KillLocalVarOp:
15369 0 : M2Quads_WriteOperand (f->Operand3);
15370 0 : break;
15371 :
15372 0 : case M2Quads_ProcedureScopeOp:
15373 0 : n1 = SymbolTable_GetSymName (f->Operand2);
15374 0 : n2 = SymbolTable_GetSymName (f->Operand3);
15375 0 : M2Printf_fprintf4 (M2LangDump_GetDumpFile (), (const char *) " %4d %a %a(%d)", 17, (const unsigned char *) &f->Operand1, (sizeof (f->Operand1)-1), (const unsigned char *) &n1, (sizeof (n1)-1), (const unsigned char *) &n2, (sizeof (n2)-1), (const unsigned char *) &f->Operand3, (sizeof (f->Operand3)-1));
15376 0 : DisplayProcedureAttributes (f->Operand3);
15377 0 : break;
15378 :
15379 0 : case M2Quads_NewLocalVarOp:
15380 0 : case M2Quads_FinallyStartOp:
15381 0 : case M2Quads_FinallyEndOp:
15382 0 : case M2Quads_InitEndOp:
15383 0 : case M2Quads_InitStartOp:
15384 0 : n1 = SymbolTable_GetSymName (f->Operand2);
15385 0 : n2 = SymbolTable_GetSymName (f->Operand3);
15386 0 : M2Printf_fprintf3 (M2LangDump_GetDumpFile (), (const char *) " %4d %a %a", 13, (const unsigned char *) &f->Operand1, (sizeof (f->Operand1)-1), (const unsigned char *) &n1, (sizeof (n1)-1), (const unsigned char *) &n2, (sizeof (n2)-1));
15387 0 : break;
15388 :
15389 0 : case M2Quads_ModuleScopeOp:
15390 0 : case M2Quads_StartModFileOp:
15391 0 : n1 = SymbolTable_GetSymName (f->Operand3);
15392 0 : M2Printf_fprintf4 (M2LangDump_GetDumpFile (), (const char *) "%a:%d %a(%d)", 13, (const unsigned char *) &f->Operand2, (sizeof (f->Operand2)-1), (const unsigned char *) &f->Operand1, (sizeof (f->Operand1)-1), (const unsigned char *) &n1, (sizeof (n1)-1), (const unsigned char *) &f->Operand3, (sizeof (f->Operand3)-1));
15393 0 : break;
15394 :
15395 0 : case M2Quads_StartDefFileOp:
15396 0 : n1 = SymbolTable_GetSymName (f->Operand3);
15397 0 : M2Printf_fprintf2 (M2LangDump_GetDumpFile (), (const char *) " %4d %a", 9, (const unsigned char *) &f->Operand1, (sizeof (f->Operand1)-1), (const unsigned char *) &n1, (sizeof (n1)-1));
15398 0 : break;
15399 :
15400 0 : case M2Quads_OptParamOp:
15401 0 : case M2Quads_ParamOp:
15402 0 : M2Printf_fprintf1 (M2LangDump_GetDumpFile (), (const char *) "%4d ", 5, (const unsigned char *) &f->Operand1, (sizeof (f->Operand1)-1));
15403 0 : M2Quads_WriteOperand (f->Operand2);
15404 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) " ", 2);
15405 0 : M2Quads_WriteOperand (f->Operand3);
15406 0 : break;
15407 :
15408 0 : case M2Quads_SizeOp:
15409 0 : case M2Quads_RecordFieldOp:
15410 0 : case M2Quads_IndrXOp:
15411 0 : case M2Quads_XIndrOp:
15412 0 : case M2Quads_ArrayOp:
15413 0 : case M2Quads_LogicalShiftOp:
15414 0 : case M2Quads_LogicalRotateOp:
15415 0 : case M2Quads_LogicalOrOp:
15416 0 : case M2Quads_LogicalAndOp:
15417 0 : case M2Quads_LogicalXorOp:
15418 0 : case M2Quads_LogicalDiffOp:
15419 0 : case M2Quads_ArithAddOp:
15420 0 : case M2Quads_CoerceOp:
15421 0 : case M2Quads_ConvertOp:
15422 0 : case M2Quads_CastOp:
15423 0 : case M2Quads_AddOp:
15424 0 : case M2Quads_SubOp:
15425 0 : case M2Quads_MultOp:
15426 0 : case M2Quads_DivM2Op:
15427 0 : case M2Quads_ModM2Op:
15428 0 : case M2Quads_ModFloorOp:
15429 0 : case M2Quads_DivCeilOp:
15430 0 : case M2Quads_ModCeilOp:
15431 0 : case M2Quads_DivFloorOp:
15432 0 : case M2Quads_ModTruncOp:
15433 0 : case M2Quads_DivTruncOp:
15434 0 : M2Quads_WriteOperand (f->Operand1);
15435 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) " ", 2);
15436 0 : M2Quads_WriteOperand (f->Operand2);
15437 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) " ", 2);
15438 0 : M2Quads_WriteOperand (f->Operand3);
15439 0 : break;
15440 :
15441 : case M2Quads_DummyOp:
15442 : case M2Quads_CodeOnOp:
15443 : case M2Quads_CodeOffOp:
15444 : case M2Quads_ProfileOnOp:
15445 : case M2Quads_ProfileOffOp:
15446 : case M2Quads_OptimizeOnOp:
15447 : case M2Quads_OptimizeOffOp:
15448 : break;
15449 :
15450 0 : case M2Quads_BuiltinConstOp:
15451 0 : M2Quads_WriteOperand (f->Operand1);
15452 0 : M2Printf_fprintf1 (M2LangDump_GetDumpFile (), (const char *) " %a", 5, (const unsigned char *) &f->Operand3, (sizeof (f->Operand3)-1));
15453 0 : break;
15454 :
15455 0 : case M2Quads_BuiltinTypeInfoOp:
15456 0 : M2Quads_WriteOperand (f->Operand1);
15457 0 : M2Printf_fprintf1 (M2LangDump_GetDumpFile (), (const char *) " %a", 5, (const unsigned char *) &f->Operand2, (sizeof (f->Operand2)-1));
15458 0 : M2Printf_fprintf1 (M2LangDump_GetDumpFile (), (const char *) " %a", 5, (const unsigned char *) &f->Operand3, (sizeof (f->Operand3)-1));
15459 0 : break;
15460 :
15461 0 : case M2Quads_StandardFunctionOp:
15462 0 : M2Quads_WriteOperand (f->Operand1);
15463 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) " ", 2);
15464 0 : M2Quads_WriteOperand (f->Operand2);
15465 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) " ", 2);
15466 0 : M2Quads_WriteOperand (f->Operand3);
15467 0 : break;
15468 :
15469 : case M2Quads_CatchBeginOp:
15470 : case M2Quads_CatchEndOp:
15471 : break;
15472 :
15473 0 : case M2Quads_RangeCheckOp:
15474 0 : case M2Quads_ErrorOp:
15475 0 : M2Range_WriteRangeCheck (f->Operand3);
15476 0 : break;
15477 :
15478 0 : case M2Quads_SaveExceptionOp:
15479 0 : case M2Quads_RestoreExceptionOp:
15480 0 : M2Quads_WriteOperand (f->Operand1);
15481 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) " ", 2);
15482 0 : M2Quads_WriteOperand (f->Operand3);
15483 0 : break;
15484 :
15485 :
15486 0 : default:
15487 0 : M2Error_InternalError ((const char *) "quadruple not recognised", 24);
15488 0 : break;
15489 : }
15490 0 : }
15491 :
15492 :
15493 : /*
15494 : WriteOperand - displays the operands name, symbol id and mode of addressing.
15495 : */
15496 :
15497 0 : static void WriteMode (SymbolTable_ModeOfAddr Mode)
15498 : {
15499 0 : switch (Mode)
15500 : {
15501 0 : case SymbolTable_ImmediateValue:
15502 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "i", 1);
15503 0 : break;
15504 :
15505 0 : case SymbolTable_NoValue:
15506 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "n", 1);
15507 0 : break;
15508 :
15509 0 : case SymbolTable_RightValue:
15510 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "r", 1);
15511 0 : break;
15512 :
15513 0 : case SymbolTable_LeftValue:
15514 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "l", 1);
15515 0 : break;
15516 :
15517 :
15518 0 : default:
15519 0 : M2Error_InternalError ((const char *) "unrecognised mode", 17);
15520 0 : break;
15521 : }
15522 0 : }
15523 :
15524 :
15525 : /*
15526 : PushExit - pushes the exit value onto the EXIT stack.
15527 : */
15528 :
15529 610 : static void PushExit (unsigned int Exit)
15530 : {
15531 0 : M2StackWord_PushWord (ExitStack, Exit);
15532 94 : }
15533 :
15534 :
15535 : /*
15536 : PopExit - pops the exit value from the EXIT stack.
15537 : */
15538 :
15539 610 : static unsigned int PopExit (void)
15540 : {
15541 0 : return M2StackWord_PopWord (ExitStack);
15542 : /* static analysis guarentees a RETURN statement will be used before here. */
15543 : __builtin_unreachable ();
15544 : }
15545 :
15546 :
15547 : /*
15548 : PushFor - pushes the exit value onto the FOR stack.
15549 : */
15550 :
15551 10422 : static void PushFor (unsigned int Exit)
15552 : {
15553 0 : M2StackWord_PushWord (ForStack, Exit);
15554 0 : }
15555 :
15556 :
15557 : /*
15558 : PopFor - pops the exit value from the FOR stack.
15559 : */
15560 :
15561 10416 : static unsigned int PopFor (void)
15562 : {
15563 0 : return M2StackWord_PopWord (ForStack);
15564 : /* static analysis guarentees a RETURN statement will be used before here. */
15565 : __builtin_unreachable ();
15566 : }
15567 :
15568 :
15569 : /*
15570 : OperandTno - returns the ident operand stored in the true position
15571 : on the boolean stack. This is exactly the same as
15572 : OperandT but it has no IsBoolean checking.
15573 : */
15574 :
15575 214541580 : static unsigned int OperandTno (unsigned int pos)
15576 : {
15577 214541580 : M2Quads_BoolFrame f;
15578 :
15579 214541580 : M2Debug_Assert (pos > 0);
15580 214541580 : f = static_cast<M2Quads_BoolFrame> (M2StackAddress_PeepAddress (BoolStack, pos));
15581 214541580 : return static_cast<unsigned int> (f->TrueExit);
15582 : /* static analysis guarentees a RETURN statement will be used before here. */
15583 : __builtin_unreachable ();
15584 : }
15585 :
15586 :
15587 : /*
15588 : OperandFno - returns the ident operand stored in the false position
15589 : on the boolean stack. This is exactly the same as
15590 : OperandF but it has no IsBoolean checking.
15591 : */
15592 :
15593 178228 : static unsigned int OperandFno (unsigned int pos)
15594 : {
15595 178228 : M2Quads_BoolFrame f;
15596 :
15597 178228 : M2Debug_Assert (pos > 0);
15598 178228 : f = static_cast<M2Quads_BoolFrame> (M2StackAddress_PeepAddress (BoolStack, pos));
15599 178228 : return static_cast<unsigned int> (f->FalseExit);
15600 : /* static analysis guarentees a RETURN statement will be used before here. */
15601 : __builtin_unreachable ();
15602 : }
15603 :
15604 :
15605 : /*
15606 : OperandTtok - returns the token associated with the position, pos
15607 : on the boolean stack.
15608 : */
15609 :
15610 58928138 : static unsigned int OperandTtok (unsigned int pos)
15611 : {
15612 58928138 : M2Quads_BoolFrame f;
15613 :
15614 58928138 : M2Debug_Assert (pos > 0);
15615 58928138 : f = static_cast<M2Quads_BoolFrame> (M2StackAddress_PeepAddress (BoolStack, pos));
15616 58928138 : return f->tokenno;
15617 : /* static analysis guarentees a RETURN statement will be used before here. */
15618 : __builtin_unreachable ();
15619 : }
15620 :
15621 :
15622 : /*
15623 : PopBooltok - Pops a True and a False exit quad number from the True/False
15624 : stack.
15625 : */
15626 :
15627 227356 : static void PopBooltok (unsigned int *True, unsigned int *False, unsigned int *tokno)
15628 : {
15629 227356 : M2Quads_BoolFrame f;
15630 :
15631 227356 : f = static_cast<M2Quads_BoolFrame> (M2StackAddress_PopAddress (BoolStack));
15632 227356 : (*True) = f->TrueExit;
15633 227356 : (*False) = f->FalseExit;
15634 227356 : (*tokno) = f->tokenno;
15635 227356 : M2Debug_Assert (f->BooleanOp);
15636 227356 : Storage_DEALLOCATE ((void **) &f, sizeof (M2Quads__T2));
15637 227356 : }
15638 :
15639 :
15640 : /*
15641 : PushBooltok - Push a True and a False exit quad numbers onto the
15642 : True/False stack.
15643 : */
15644 :
15645 234734 : static void PushBooltok (unsigned int True, unsigned int False, unsigned int tokno)
15646 : {
15647 234734 : M2Quads_BoolFrame f;
15648 :
15649 234734 : M2Debug_Assert (True <= NextQuad);
15650 234734 : M2Debug_Assert (False <= NextQuad);
15651 234734 : f = newBoolFrame ();
15652 234734 : f->TrueExit = True;
15653 234734 : f->FalseExit = False;
15654 234734 : f->BooleanOp = true;
15655 234734 : f->tokenno = tokno;
15656 234734 : f->Annotation = static_cast<DynamicStrings_String> (NULL);
15657 234734 : f->RangeDep = 0;
15658 234734 : M2StackAddress_PushAddress (BoolStack, reinterpret_cast <void *> (f));
15659 234734 : M2Quads_Annotate ((const char *) "<q%1d>|<q%2d>||true quad|false quad", 35);
15660 234734 : }
15661 :
15662 :
15663 : /*
15664 : PopBool - Pops a True and a False exit quad number from the True/False
15665 : stack.
15666 : */
15667 :
15668 193684 : static void PopBool (unsigned int *True, unsigned int *False)
15669 : {
15670 193684 : unsigned int tokno;
15671 :
15672 10044 : PopBooltok (True, False, &tokno);
15673 0 : }
15674 :
15675 :
15676 : /*
15677 : PushBool - Push a True and a False exit quad numbers onto the
15678 : True/False stack.
15679 : */
15680 :
15681 122204 : static void PushBool (unsigned int True, unsigned int False)
15682 : {
15683 7378 : PushBooltok (True, False, M2LexBuf_UnknownTokenNo);
15684 13438 : }
15685 :
15686 :
15687 : /*
15688 : IsBoolean - returns true is the Stack position pos contains a Boolean
15689 : Exit. False is returned if an Ident is stored.
15690 : */
15691 :
15692 277434681 : static bool IsBoolean (unsigned int pos)
15693 : {
15694 277434681 : M2Quads_BoolFrame f;
15695 :
15696 277434681 : M2Debug_Assert (pos > 0);
15697 277434681 : f = static_cast<M2Quads_BoolFrame> (M2StackAddress_PeepAddress (BoolStack, pos));
15698 277434681 : return f->BooleanOp;
15699 : /* static analysis guarentees a RETURN statement will be used before here. */
15700 : __builtin_unreachable ();
15701 : }
15702 :
15703 :
15704 : /*
15705 : OperandD - returns possible array dimension associated with the ident
15706 : operand stored on the boolean stack.
15707 : */
15708 :
15709 688559 : static unsigned int OperandD (unsigned int pos)
15710 : {
15711 688559 : M2Quads_BoolFrame f;
15712 :
15713 688559 : M2Debug_Assert (pos > 0);
15714 688559 : M2Debug_Assert (! (IsBoolean (pos)));
15715 688559 : f = static_cast<M2Quads_BoolFrame> (M2StackAddress_PeepAddress (BoolStack, pos));
15716 688559 : return static_cast<unsigned int> (f->Dimension);
15717 : /* static analysis guarentees a RETURN statement will be used before here. */
15718 : __builtin_unreachable ();
15719 : }
15720 :
15721 :
15722 : /*
15723 : OperandRW - returns the rw operand stored on the boolean stack.
15724 : */
15725 :
15726 751195 : static unsigned int OperandRW (unsigned int pos)
15727 : {
15728 751195 : M2Quads_BoolFrame f;
15729 :
15730 751195 : M2Debug_Assert (pos > 0);
15731 751195 : M2Debug_Assert (! (IsBoolean (pos)));
15732 751195 : f = static_cast<M2Quads_BoolFrame> (M2StackAddress_PeepAddress (BoolStack, pos));
15733 751195 : return static_cast<unsigned int> (f->ReadWrite);
15734 : /* static analysis guarentees a RETURN statement will be used before here. */
15735 : __builtin_unreachable ();
15736 : }
15737 :
15738 :
15739 : /*
15740 : OperandMergeRW - returns the rw operand if not NulSym else it
15741 : returns True.
15742 : */
15743 :
15744 727251 : static unsigned int OperandMergeRW (unsigned int pos)
15745 : {
15746 727251 : if ((OperandRW (pos)) == SymbolTable_NulSym)
15747 : {
15748 705677 : return M2Quads_OperandT (pos);
15749 : }
15750 : else
15751 : {
15752 21574 : return OperandRW (pos);
15753 : }
15754 : /* static analysis guarentees a RETURN statement will be used before here. */
15755 : __builtin_unreachable ();
15756 : }
15757 :
15758 :
15759 : /*
15760 : OperandRangeDep - return the range dependant associated with the quad stack.
15761 : */
15762 :
15763 142599 : static unsigned int OperandRangeDep (unsigned int pos)
15764 : {
15765 142599 : M2Quads_BoolFrame f;
15766 :
15767 142599 : M2Debug_Assert (! (IsBoolean (pos)));
15768 142599 : f = static_cast<M2Quads_BoolFrame> (M2StackAddress_PeepAddress (BoolStack, pos));
15769 142599 : return f->RangeDep;
15770 : /* static analysis guarentees a RETURN statement will be used before here. */
15771 : __builtin_unreachable ();
15772 : }
15773 :
15774 :
15775 : /*
15776 : PutRangeDep - assigns the quad stack pos RangeDep to dep.
15777 : */
15778 :
15779 539229 : static void PutRangeDep (unsigned int pos, unsigned int dep)
15780 : {
15781 539229 : M2Quads_BoolFrame f;
15782 :
15783 539229 : M2Debug_Assert (! (IsBoolean (pos)));
15784 539229 : f = static_cast<M2Quads_BoolFrame> (M2StackAddress_PeepAddress (BoolStack, pos));
15785 539229 : f->RangeDep = dep;
15786 539229 : }
15787 :
15788 :
15789 : /*
15790 : UseLineNote - uses the line note and returns it to the free list.
15791 : */
15792 :
15793 5220 : static void UseLineNote (M2Quads_LineNote l)
15794 : {
15795 5220 : M2Quads_QuadFrame f;
15796 :
15797 5220 : f = GetQF (NextQuad-1);
15798 5220 : if ((f->Operator == M2Quads_LineNumberOp) && (f->Operand1 == ((unsigned int ) (l->File))))
15799 : {} /* empty. */
15800 : else
15801 : {
15802 : /* do nothing */
15803 : if (false)
15804 : {
15805 : GenQuad (M2Quads_LineNumberOp, (unsigned int ) (l->File), SymbolTable_NulSym, (unsigned int ) (l->Line));
15806 : }
15807 : }
15808 5220 : l->Next = FreeLineList;
15809 5220 : FreeLineList = l;
15810 5220 : }
15811 :
15812 :
15813 : /*
15814 : PopLineNo - pops a line note from the line stack.
15815 : */
15816 :
15817 5220 : static M2Quads_LineNote PopLineNo (void)
15818 : {
15819 5220 : M2Quads_LineNote l;
15820 :
15821 5220 : l = static_cast<M2Quads_LineNote> (M2StackAddress_PopAddress (LineStack));
15822 5220 : if (l == NULL)
15823 : {
15824 0 : M2Error_InternalError ((const char *) "no line note available", 22);
15825 : }
15826 5220 : return l;
15827 : /* static analysis guarentees a RETURN statement will be used before here. */
15828 : __builtin_unreachable ();
15829 : }
15830 :
15831 :
15832 : /*
15833 : InitLineNote - creates a line note and initializes it to
15834 : contain, file, line.
15835 : */
15836 :
15837 5220 : static M2Quads_LineNote InitLineNote (NameKey_Name file, unsigned int line)
15838 : {
15839 5220 : M2Quads_LineNote l;
15840 :
15841 5220 : if (FreeLineList == NULL)
15842 : {
15843 2412 : Storage_ALLOCATE ((void **) &l, sizeof (M2Quads__T6));
15844 : }
15845 : else
15846 : {
15847 2808 : l = FreeLineList;
15848 2808 : FreeLineList = FreeLineList->Next;
15849 : }
15850 5220 : l->File = file;
15851 5220 : l->Line = line;
15852 5220 : return l;
15853 : /* static analysis guarentees a RETURN statement will be used before here. */
15854 : __builtin_unreachable ();
15855 : }
15856 :
15857 :
15858 : /*
15859 : PushLineNote -
15860 : */
15861 :
15862 5220 : static void PushLineNote (M2Quads_LineNote l)
15863 : {
15864 0 : M2StackAddress_PushAddress (LineStack, reinterpret_cast <void *> (l));
15865 0 : }
15866 :
15867 :
15868 : /*
15869 : BuildStmtNoteTok - adds a nop (with an assigned tokenno location) to the code.
15870 : */
15871 :
15872 551414 : static void BuildStmtNoteTok (unsigned int tokenno)
15873 : {
15874 551414 : NameKey_Name filename;
15875 551414 : M2Quads_QuadFrame f;
15876 :
15877 551414 : f = GetQF (NextQuad-1);
15878 : /* no need to have multiple notes at the same position. */
15879 551414 : if ((f->Operator != M2Quads_StatementNoteOp) || (f->Operand3 != tokenno))
15880 : {
15881 543982 : filename = NameKey_makekey (DynamicStrings_string (M2LexBuf_GetFileName ()));
15882 543982 : GenQuad (M2Quads_StatementNoteOp, (unsigned int ) (filename), SymbolTable_NulSym, tokenno);
15883 : }
15884 551414 : }
15885 :
15886 :
15887 : /*
15888 : GetRecordOrField -
15889 : */
15890 :
15891 12306 : static unsigned int GetRecordOrField (void)
15892 : {
15893 12306 : unsigned int f;
15894 :
15895 12306 : VarientFieldNo += 1;
15896 12306 : f = static_cast<unsigned int> (Lists_GetItemFromList (VarientFields, VarientFieldNo));
15897 12306 : if (DebugVarients)
15898 : {
15899 : /* avoid gcc warning by using compound statement even if not strictly necessary. */
15900 : if (SymbolTable_IsRecord (f))
15901 : {
15902 : M2Printf_printf2 ((const char *) "out list: record %d is %d\\n", 27, (const unsigned char *) &VarientFieldNo, (sizeof (VarientFieldNo)-1), (const unsigned char *) &f, (sizeof (f)-1));
15903 : }
15904 : else
15905 : {
15906 : M2Printf_printf2 ((const char *) "out list: varient field %d is %d\\n", 34, (const unsigned char *) &VarientFieldNo, (sizeof (VarientFieldNo)-1), (const unsigned char *) &f, (sizeof (f)-1));
15907 : }
15908 : }
15909 12306 : return f;
15910 : /* static analysis guarentees a RETURN statement will be used before here. */
15911 : __builtin_unreachable ();
15912 : }
15913 :
15914 :
15915 : /*
15916 : PushTFAD - Push True, False, Array, Dim, numbers onto the
15917 : True/False stack. True and False are assumed to
15918 : contain Symbols or Ident etc.
15919 : */
15920 :
15921 384 : static void PushTFAD (unsigned int True, unsigned int False, unsigned int Array, unsigned int Dim)
15922 : {
15923 384 : M2Quads_BoolFrame f;
15924 :
15925 384 : f = newBoolFrame ();
15926 384 : f->TrueExit = static_cast<unsigned int> (True);
15927 384 : f->FalseExit = static_cast<unsigned int> (False);
15928 384 : f->Unbounded = static_cast<unsigned int> (Array);
15929 384 : f->Dimension = static_cast<unsigned int> (Dim);
15930 384 : M2StackAddress_PushAddress (BoolStack, reinterpret_cast <void *> (f));
15931 384 : }
15932 :
15933 :
15934 : /*
15935 : PushTFADtok - Push True, False, Array, Dim, numbers onto the
15936 : True/False stack. True and False are assumed to
15937 : contain Symbols or Ident etc.
15938 : */
15939 :
15940 3024 : static void PushTFADtok (unsigned int True, unsigned int False, unsigned int Array, unsigned int Dim, unsigned int tokno)
15941 : {
15942 3024 : M2Quads_BoolFrame f;
15943 :
15944 3024 : f = newBoolFrame ();
15945 3024 : f->TrueExit = static_cast<unsigned int> (True);
15946 3024 : f->FalseExit = static_cast<unsigned int> (False);
15947 3024 : f->Unbounded = static_cast<unsigned int> (Array);
15948 3024 : f->Dimension = static_cast<unsigned int> (Dim);
15949 3024 : f->tokenno = tokno;
15950 3024 : M2StackAddress_PushAddress (BoolStack, reinterpret_cast <void *> (f));
15951 3024 : }
15952 :
15953 :
15954 : /*
15955 : PushTFADrwtok - Push True, False, Array, Dim, rw, numbers onto the
15956 : True/False stack. True and False are assumed to
15957 : contain Symbols or Ident etc.
15958 : */
15959 :
15960 8994 : static void PushTFADrwtok (unsigned int True, unsigned int False, unsigned int Array, unsigned int Dim, unsigned int rw, unsigned int Tok)
15961 : {
15962 8994 : M2Quads_BoolFrame f;
15963 :
15964 8994 : f = newBoolFrame ();
15965 8994 : f->TrueExit = static_cast<unsigned int> (True);
15966 8994 : f->FalseExit = static_cast<unsigned int> (False);
15967 8994 : f->Unbounded = static_cast<unsigned int> (Array);
15968 8994 : f->Dimension = static_cast<unsigned int> (Dim);
15969 8994 : f->ReadWrite = static_cast<unsigned int> (rw);
15970 8994 : f->tokenno = Tok;
15971 8994 : M2StackAddress_PushAddress (BoolStack, reinterpret_cast <void *> (f));
15972 8994 : }
15973 :
15974 :
15975 : /*
15976 : PopTFrwtok - Pop a True and False number from the True/False stack.
15977 : True and False are assumed to contain Symbols or Ident etc.
15978 : */
15979 :
15980 316404 : static void PopTFrwtok (unsigned int *True, unsigned int *False, unsigned int *rw, unsigned int *tokno)
15981 : {
15982 316404 : M2Quads_BoolFrame f;
15983 :
15984 316404 : f = static_cast<M2Quads_BoolFrame> (M2StackAddress_PopAddress (BoolStack));
15985 316404 : (*True) = static_cast<unsigned int> (f->TrueExit);
15986 316404 : (*False) = static_cast<unsigned int> (f->FalseExit);
15987 316404 : M2Debug_Assert (! f->BooleanOp);
15988 316404 : (*rw) = static_cast<unsigned int> (f->ReadWrite);
15989 316404 : (*tokno) = f->tokenno;
15990 316404 : Storage_DEALLOCATE ((void **) &f, sizeof (M2Quads__T2));
15991 316404 : }
15992 :
15993 :
15994 : /*
15995 : PushTFrwtok - Push an item onto the stack in the T (true) position,
15996 : it is assummed to be a token and its token location is recorded.
15997 : */
15998 :
15999 349382 : static void PushTFrwtok (unsigned int True, unsigned int False, unsigned int rw, unsigned int tokno)
16000 : {
16001 349382 : M2Quads_BoolFrame f;
16002 :
16003 349382 : f = newBoolFrame ();
16004 349382 : f->TrueExit = static_cast<unsigned int> (True);
16005 349382 : f->FalseExit = static_cast<unsigned int> (False);
16006 349382 : f->ReadWrite = static_cast<unsigned int> (rw);
16007 349382 : f->tokenno = tokno;
16008 349382 : M2StackAddress_PushAddress (BoolStack, reinterpret_cast <void *> (f));
16009 349382 : }
16010 :
16011 :
16012 : /*
16013 : PushTFDtok - Push True, False, Dim, numbers onto the
16014 : True/False stack. True and False are assumed to
16015 : contain Symbols or Ident etc.
16016 : */
16017 :
16018 258 : static void PushTFDtok (unsigned int True, unsigned int False, unsigned int Dim, unsigned int Tok)
16019 : {
16020 258 : M2Quads_BoolFrame f;
16021 :
16022 258 : f = newBoolFrame ();
16023 258 : f->TrueExit = static_cast<unsigned int> (True);
16024 258 : f->FalseExit = static_cast<unsigned int> (False);
16025 258 : f->Dimension = static_cast<unsigned int> (Dim);
16026 258 : f->tokenno = Tok;
16027 258 : M2StackAddress_PushAddress (BoolStack, reinterpret_cast <void *> (f));
16028 258 : }
16029 :
16030 :
16031 : /*
16032 : PopTFDtok - Pop a True, False, Dim number from the True/False stack.
16033 : True and False are assumed to contain Symbols or Ident etc.
16034 : */
16035 :
16036 258 : static void PopTFDtok (unsigned int *True, unsigned int *False, unsigned int *Dim, unsigned int *Tok)
16037 : {
16038 258 : M2Quads_BoolFrame f;
16039 :
16040 258 : f = static_cast<M2Quads_BoolFrame> (M2StackAddress_PopAddress (BoolStack));
16041 258 : (*True) = static_cast<unsigned int> (f->TrueExit);
16042 258 : (*False) = static_cast<unsigned int> (f->FalseExit);
16043 258 : (*Dim) = static_cast<unsigned int> (f->Dimension);
16044 258 : (*Tok) = f->tokenno;
16045 258 : M2Debug_Assert (! f->BooleanOp);
16046 258 : Storage_DEALLOCATE ((void **) &f, sizeof (M2Quads__T2));
16047 258 : }
16048 :
16049 :
16050 : /*
16051 : PushTFDrwtok - Push True, False, Dim, numbers onto the
16052 : True/False stack. True and False are assumed to
16053 : contain Symbols or Ident etc.
16054 : */
16055 :
16056 47990 : static void PushTFDrwtok (unsigned int True, unsigned int False, unsigned int Dim, unsigned int rw, unsigned int Tok)
16057 : {
16058 47990 : M2Quads_BoolFrame f;
16059 :
16060 47990 : f = newBoolFrame ();
16061 47990 : f->TrueExit = static_cast<unsigned int> (True);
16062 47990 : f->FalseExit = static_cast<unsigned int> (False);
16063 47990 : f->Dimension = static_cast<unsigned int> (Dim);
16064 47990 : f->ReadWrite = static_cast<unsigned int> (rw);
16065 47990 : f->tokenno = Tok;
16066 47990 : M2StackAddress_PushAddress (BoolStack, reinterpret_cast <void *> (f));
16067 47990 : }
16068 :
16069 :
16070 : /*
16071 : PushTFrw - Push a True and False numbers onto the True/False stack.
16072 : True and False are assumed to contain Symbols or Ident etc.
16073 : It also pushes the higher level symbol which is associated
16074 : with the True symbol. Eg record variable or array variable.
16075 : */
16076 :
16077 2370 : static void PushTFrw (unsigned int True, unsigned int False, unsigned int rw)
16078 : {
16079 2370 : M2Quads_BoolFrame f;
16080 :
16081 2370 : f = newBoolFrame ();
16082 2370 : f->TrueExit = static_cast<unsigned int> (True);
16083 2370 : f->FalseExit = static_cast<unsigned int> (False);
16084 2370 : f->ReadWrite = rw;
16085 2370 : M2StackAddress_PushAddress (BoolStack, reinterpret_cast <void *> (f));
16086 2370 : }
16087 :
16088 :
16089 : /*
16090 : PopTFrw - Pop a True and False number from the True/False stack.
16091 : True and False are assumed to contain Symbols or Ident etc.
16092 : */
16093 :
16094 31040 : static void PopTFrw (unsigned int *True, unsigned int *False, unsigned int *rw)
16095 : {
16096 31040 : M2Quads_BoolFrame f;
16097 :
16098 31040 : f = static_cast<M2Quads_BoolFrame> (M2StackAddress_PopAddress (BoolStack));
16099 31040 : (*True) = static_cast<unsigned int> (f->TrueExit);
16100 31040 : (*False) = static_cast<unsigned int> (f->FalseExit);
16101 31040 : M2Debug_Assert (! f->BooleanOp);
16102 31040 : (*rw) = static_cast<unsigned int> (f->ReadWrite);
16103 31040 : Storage_DEALLOCATE ((void **) &f, sizeof (M2Quads__T2));
16104 31040 : }
16105 :
16106 :
16107 : /*
16108 : newBoolFrame - creates a new BoolFrame with all fields initialised to their defaults.
16109 : */
16110 :
16111 352913180 : static M2Quads_BoolFrame newBoolFrame (void)
16112 : {
16113 352913180 : M2Quads_BoolFrame f;
16114 :
16115 352913180 : Storage_ALLOCATE ((void **) &f, sizeof (M2Quads__T2));
16116 352913180 : f->TrueExit = 0;
16117 352913180 : f->FalseExit = 0;
16118 352913180 : f->Unbounded = SymbolTable_NulSym;
16119 352913180 : f->BooleanOp = false;
16120 352913180 : f->Dimension = 0;
16121 352913180 : f->ReadWrite = SymbolTable_NulSym;
16122 352913180 : f->name = SymbolTable_NulSym;
16123 352913180 : f->Annotation = static_cast<DynamicStrings_String> (NULL);
16124 352913180 : f->tokenno = M2LexBuf_UnknownTokenNo;
16125 352913180 : return f;
16126 : /* static analysis guarentees a RETURN statement will be used before here. */
16127 : __builtin_unreachable ();
16128 : }
16129 :
16130 :
16131 : /*
16132 : PushTrwtok - Push an item onto the True/False stack. The False value will be zero.
16133 : */
16134 :
16135 156 : static void PushTrwtok (unsigned int True, unsigned int rw, unsigned int tok)
16136 : {
16137 156 : M2Quads_BoolFrame f;
16138 :
16139 156 : f = newBoolFrame ();
16140 156 : f->TrueExit = static_cast<unsigned int> (True);
16141 156 : f->ReadWrite = static_cast<unsigned int> (rw);
16142 156 : f->tokenno = tok;
16143 156 : M2StackAddress_PushAddress (BoolStack, reinterpret_cast <void *> (f));
16144 156 : }
16145 :
16146 :
16147 : /*
16148 : PopTrw - Pop a True field and rw symbol from the stack.
16149 : */
16150 :
16151 2370 : static void PopTrw (unsigned int *True, unsigned int *rw)
16152 : {
16153 2370 : M2Quads_BoolFrame f;
16154 :
16155 2370 : f = static_cast<M2Quads_BoolFrame> (M2StackAddress_PopAddress (BoolStack));
16156 2370 : (*True) = static_cast<unsigned int> (f->TrueExit);
16157 2370 : M2Debug_Assert (! f->BooleanOp);
16158 2370 : (*rw) = static_cast<unsigned int> (f->ReadWrite);
16159 2370 : Storage_DEALLOCATE ((void **) &f, sizeof (M2Quads__T2));
16160 2370 : }
16161 :
16162 :
16163 : /*
16164 : PopTrwtok - Pop a True field and rw symbol from the stack.
16165 : */
16166 :
16167 1091287 : static void PopTrwtok (unsigned int *True, unsigned int *rw, unsigned int *tok)
16168 : {
16169 1091287 : M2Quads_BoolFrame f;
16170 :
16171 1091287 : f = static_cast<M2Quads_BoolFrame> (M2StackAddress_PopAddress (BoolStack));
16172 1091287 : (*True) = static_cast<unsigned int> (f->TrueExit);
16173 1091287 : M2Debug_Assert (! f->BooleanOp);
16174 1091287 : (*rw) = static_cast<unsigned int> (f->ReadWrite);
16175 1091287 : (*tok) = f->tokenno;
16176 1091287 : Storage_DEALLOCATE ((void **) &f, sizeof (M2Quads__T2));
16177 1091287 : }
16178 :
16179 :
16180 : /*
16181 : gdbhook - a debugger convenience hook.
16182 : */
16183 :
16184 0 : static void gdbhook (void)
16185 : {
16186 0 : }
16187 :
16188 :
16189 : /*
16190 : BreakWhenQuadCreated - to be called interactively by gdb.
16191 : */
16192 :
16193 15674 : static void BreakWhenQuadCreated (unsigned int quad)
16194 : {
16195 15674 : BreakQuad = quad;
16196 0 : }
16197 :
16198 :
16199 : /*
16200 : CheckBreak - if quad = BreakQuad then call gdbhook.
16201 : */
16202 :
16203 0 : static void CheckBreak (unsigned int quad)
16204 : {
16205 0 : if (quad == BreakQuad)
16206 : {
16207 0 : gdbhook ();
16208 : }
16209 0 : }
16210 :
16211 :
16212 : /*
16213 : Init - initialize the M2Quads module, all the stacks, all the lists
16214 : and the quads list.
16215 : */
16216 :
16217 15674 : static void Init (void)
16218 : {
16219 15674 : BreakWhenQuadCreated (0); /* Disable the intereactive quad watch. */
16220 : /* To examine the quad table when a quad is created run cc1gm2 from gdb
16221 : and set a break point on gdbhook.
16222 : (gdb) break gdbhook
16223 : (gdb) run
16224 : Now below interactively call BreakWhenQuadCreated with the quad
16225 : under investigation. */
16226 15674 : gdbhook ();
16227 : /* Now is the time to interactively call gdb, for example:
16228 : (gdb) print BreakWhenQuadCreated (1234)
16229 : (gdb) cont
16230 : and you will arrive at gdbhook when this quad is created. */
16231 15674 : LogicalOrTok = NameKey_MakeKey ((const char *) "_LOR", 4);
16232 15674 : LogicalAndTok = NameKey_MakeKey ((const char *) "_LAND", 5);
16233 15674 : LogicalXorTok = NameKey_MakeKey ((const char *) "_LXOR", 5);
16234 15674 : LogicalDifferenceTok = NameKey_MakeKey ((const char *) "_LDIFF", 6);
16235 15674 : ArithPlusTok = NameKey_MakeKey ((const char *) "_ARITH_+", 8);
16236 15674 : QuadArray = Indexing_InitIndexTuned (1, (1024*1024) / 16, 16);
16237 15674 : FreeList = 1;
16238 15674 : NewQuad (&NextQuad);
16239 15674 : M2Debug_Assert (NextQuad == 1);
16240 15674 : BoolStack = M2StackAddress_InitStackAddress ();
16241 15674 : ExitStack = M2StackWord_InitStackWord ();
16242 15674 : RepeatStack = M2StackWord_InitStackWord ();
16243 15674 : WhileStack = M2StackWord_InitStackWord ();
16244 15674 : ForStack = M2StackWord_InitStackWord ();
16245 15674 : WithStack = M2StackAddress_InitStackAddress ();
16246 15674 : ReturnStack = M2StackWord_InitStackWord ();
16247 15674 : LineStack = M2StackAddress_InitStackAddress ();
16248 15674 : PriorityStack = M2StackWord_InitStackWord ();
16249 15674 : TryStack = M2StackWord_InitStackWord ();
16250 15674 : CatchStack = M2StackWord_InitStackWord ();
16251 15674 : ExceptStack = M2StackWord_InitStackWord ();
16252 15674 : ConstructorStack = M2StackAddress_InitStackAddress ();
16253 15674 : ConstParamStack = M2StackWord_InitStackWord ();
16254 15674 : ConstExprStack = M2StackWord_InitStackWord ();
16255 : /* StressStack ; */
16256 15674 : SuppressWith = false;
16257 15674 : Head = 1;
16258 15674 : LastQuadNo = 0;
16259 15674 : MustNotCheckBounds = false;
16260 15674 : InitQuad = 0;
16261 15674 : GrowInitialization = 0;
16262 15674 : ForInfo = Indexing_InitIndex (1);
16263 15674 : QuadrupleGeneration = true;
16264 15674 : BuildingHigh = false;
16265 15674 : BuildingSize = false;
16266 15674 : AutoStack = M2StackWord_InitStackWord ();
16267 15674 : IsAutoOn = true;
16268 15674 : InConstExpression = false;
16269 15674 : InConstParameters = false;
16270 15674 : FreeLineList = NULL;
16271 15674 : Lists_InitList (&VarientFields);
16272 15674 : VarientFieldNo = 0;
16273 15674 : NoOfQuads = 0;
16274 15674 : QuadMemDiag = M2Diagnostic_InitMemDiagnostic ((const char *) "M2Quad:Quadruples", 17, (const char *) "{0N} total quadruples {1d} consuming {2M} ram {0M} ({2P})", 57);
16275 15674 : }
16276 :
16277 :
16278 : /*
16279 : SetOptionCoding - builds a code quadruple if the profiling
16280 : option was given to the compiler.
16281 : */
16282 :
16283 0 : extern "C" void M2Quads_SetOptionCoding (bool b)
16284 : {
16285 0 : if (b != M2Options_Coding)
16286 : {
16287 0 : if (b)
16288 : {
16289 0 : M2Quads_BuildCodeOn ();
16290 : }
16291 : else
16292 : {
16293 0 : M2Quads_BuildCodeOff ();
16294 : }
16295 0 : M2Options_Coding = b;
16296 : }
16297 0 : }
16298 :
16299 :
16300 : /*
16301 : SetOptionProfiling - builds a profile quadruple if the profiling
16302 : option was given to the compiler.
16303 : */
16304 :
16305 0 : extern "C" void M2Quads_SetOptionProfiling (bool b)
16306 : {
16307 0 : if (b != M2Options_Profiling)
16308 : {
16309 0 : if (b)
16310 : {
16311 0 : M2Quads_BuildProfileOn ();
16312 : }
16313 : else
16314 : {
16315 0 : M2Quads_BuildProfileOff ();
16316 : }
16317 0 : M2Options_Profiling = b;
16318 : }
16319 0 : }
16320 :
16321 :
16322 : /*
16323 : SetOptionOptimizing - builds a quadruple to say that the optimization option
16324 : has been found in a comment.
16325 : */
16326 :
16327 0 : extern "C" void M2Quads_SetOptionOptimizing (bool b)
16328 : {
16329 0 : if (b)
16330 : {
16331 0 : M2Quads_BuildOptimizeOn ();
16332 : }
16333 : else
16334 : {
16335 0 : M2Quads_BuildOptimizeOff ();
16336 : }
16337 0 : }
16338 :
16339 :
16340 : /*
16341 : Opposite - returns the opposite comparison operator.
16342 : */
16343 :
16344 82188 : extern "C" M2Quads_QuadOperator M2Quads_Opposite (M2Quads_QuadOperator Operator)
16345 : {
16346 82188 : M2Quads_QuadOperator Op;
16347 :
16348 82188 : switch (Operator)
16349 : {
16350 : case M2Quads_IfNotEquOp:
16351 : Op = M2Quads_IfEquOp;
16352 : break;
16353 :
16354 : case M2Quads_IfEquOp:
16355 : Op = M2Quads_IfNotEquOp;
16356 : break;
16357 :
16358 : case M2Quads_IfLessEquOp:
16359 : Op = M2Quads_IfGreOp;
16360 : break;
16361 :
16362 : case M2Quads_IfGreOp:
16363 : Op = M2Quads_IfLessEquOp;
16364 : break;
16365 :
16366 : case M2Quads_IfGreEquOp:
16367 : Op = M2Quads_IfLessOp;
16368 : break;
16369 :
16370 : case M2Quads_IfLessOp:
16371 : Op = M2Quads_IfGreEquOp;
16372 : break;
16373 :
16374 : case M2Quads_IfInOp:
16375 : Op = M2Quads_IfNotInOp;
16376 : break;
16377 :
16378 : case M2Quads_IfNotInOp:
16379 : Op = M2Quads_IfInOp;
16380 : break;
16381 :
16382 :
16383 0 : default:
16384 0 : M2Error_InternalError ((const char *) "unexpected operator", 19);
16385 82188 : break;
16386 : }
16387 82188 : return Op;
16388 : /* static analysis guarentees a RETURN statement will be used before here. */
16389 : __builtin_unreachable ();
16390 : }
16391 :
16392 :
16393 : /*
16394 : IsReferenced - returns true if QuadNo is referenced by another quadruple.
16395 : */
16396 :
16397 259950585 : extern "C" bool M2Quads_IsReferenced (unsigned int QuadNo)
16398 : {
16399 259950585 : M2Quads_QuadFrame f;
16400 :
16401 259950585 : f = GetQF (QuadNo);
16402 259950585 : return ((f->Operator == M2Quads_ProcedureScopeOp) || (f->Operator == M2Quads_NewLocalVarOp)) || (f->NoOfTimesReferenced > 0);
16403 : /* static analysis guarentees a RETURN statement will be used before here. */
16404 : __builtin_unreachable ();
16405 : }
16406 :
16407 :
16408 : /*
16409 : IsBackReference - returns TRUE if quadruple, q, is referenced from a quad further on.
16410 : */
16411 :
16412 97025 : extern "C" bool M2Quads_IsBackReference (unsigned int q)
16413 : {
16414 97025 : unsigned int i;
16415 97025 : M2Quads_QuadOperator op;
16416 97025 : unsigned int op1;
16417 97025 : unsigned int op2;
16418 97025 : unsigned int op3;
16419 :
16420 97025 : i = q;
16421 3803984 : while (i != 0)
16422 : {
16423 3803984 : M2Quads_GetQuad (i, &op, &op1, &op2, &op3);
16424 3803984 : switch (op)
16425 : {
16426 : case M2Quads_NewLocalVarOp:
16427 : case M2Quads_KillLocalVarOp:
16428 : case M2Quads_FinallyStartOp:
16429 : case M2Quads_FinallyEndOp:
16430 : case M2Quads_InitEndOp:
16431 : case M2Quads_InitStartOp:
16432 : case M2Quads_EndFileOp:
16433 : case M2Quads_StartDefFileOp:
16434 : case M2Quads_StartModFileOp:
16435 : return false; /* run into end of procedure or module */
16436 168340 : break;
16437 :
16438 168340 : case M2Quads_GotoOp:
16439 168340 : case M2Quads_IfEquOp:
16440 168340 : case M2Quads_IfLessEquOp:
16441 168340 : case M2Quads_IfGreEquOp:
16442 168340 : case M2Quads_IfGreOp:
16443 168340 : case M2Quads_IfLessOp:
16444 168340 : case M2Quads_IfNotEquOp:
16445 168340 : case M2Quads_IfInOp:
16446 168340 : case M2Quads_IfNotInOp:
16447 168340 : if (op3 == q) /* run into end of procedure or module */
16448 : {
16449 : return true;
16450 : }
16451 : break;
16452 :
16453 :
16454 : default:
16455 : break;
16456 : }
16457 3706959 : i = M2Quads_GetNextQuad (i);
16458 : }
16459 0 : M2Error_InternalError ((const char *) "fix this for the sake of efficiency..", 37);
16460 : ReturnException ("/home/worker/buildworker/tiber-lcov/build/gcc/m2/gm2-compiler/M2Quads.def", 20, 1);
16461 : __builtin_unreachable ();
16462 : }
16463 :
16464 :
16465 : /*
16466 : IsUnConditional - returns true if QuadNo is an unconditional jump.
16467 : */
16468 :
16469 528183338 : extern "C" bool M2Quads_IsUnConditional (unsigned int QuadNo)
16470 : {
16471 528183338 : M2Quads_QuadFrame f;
16472 :
16473 528183338 : f = GetQF (QuadNo);
16474 528183338 : switch (f->Operator)
16475 : {
16476 : case M2Quads_ThrowOp:
16477 : case M2Quads_RetryOp:
16478 : case M2Quads_CallOp:
16479 : case M2Quads_ReturnOp:
16480 : case M2Quads_GotoOp:
16481 : return true;
16482 507589237 : break;
16483 :
16484 :
16485 507589237 : default:
16486 507589237 : return false;
16487 : break;
16488 : }
16489 : /* static analysis guarentees a RETURN statement will be used before here. */
16490 : __builtin_unreachable ();
16491 : }
16492 :
16493 :
16494 : /*
16495 : IsConditional - returns true if QuadNo is a conditional jump.
16496 : */
16497 :
16498 528290737 : extern "C" bool M2Quads_IsConditional (unsigned int QuadNo)
16499 : {
16500 528290737 : M2Quads_QuadFrame f;
16501 :
16502 528290737 : f = GetQF (QuadNo);
16503 528290737 : switch (f->Operator)
16504 : {
16505 : case M2Quads_IfInOp:
16506 : case M2Quads_IfNotInOp:
16507 : case M2Quads_IfEquOp:
16508 : case M2Quads_IfNotEquOp:
16509 : case M2Quads_IfLessOp:
16510 : case M2Quads_IfLessEquOp:
16511 : case M2Quads_IfGreOp:
16512 : case M2Quads_IfGreEquOp:
16513 : return true;
16514 524308874 : break;
16515 :
16516 :
16517 524308874 : default:
16518 524308874 : return false;
16519 : break;
16520 : }
16521 : /* static analysis guarentees a RETURN statement will be used before here. */
16522 : __builtin_unreachable ();
16523 : }
16524 :
16525 :
16526 : /*
16527 : IsBackReferenceConditional - returns TRUE if quadruple, q, is referenced from
16528 : a conditional quad further on.
16529 : */
16530 :
16531 0 : extern "C" bool M2Quads_IsBackReferenceConditional (unsigned int q)
16532 : {
16533 0 : unsigned int i;
16534 0 : M2Quads_QuadOperator op;
16535 0 : unsigned int op1;
16536 0 : unsigned int op2;
16537 0 : unsigned int op3;
16538 :
16539 0 : i = q;
16540 0 : while (i != 0)
16541 : {
16542 0 : M2Quads_GetQuad (i, &op, &op1, &op2, &op3);
16543 0 : switch (op)
16544 : {
16545 : case M2Quads_NewLocalVarOp:
16546 : case M2Quads_KillLocalVarOp:
16547 : case M2Quads_FinallyStartOp:
16548 : case M2Quads_FinallyEndOp:
16549 : case M2Quads_InitEndOp:
16550 : case M2Quads_InitStartOp:
16551 : case M2Quads_EndFileOp:
16552 : case M2Quads_StartDefFileOp:
16553 : case M2Quads_StartModFileOp:
16554 : return false; /* run into end of procedure or module */
16555 0 : break;
16556 :
16557 0 : case M2Quads_TryOp:
16558 0 : case M2Quads_RetryOp:
16559 0 : case M2Quads_GotoOp:
16560 0 : case M2Quads_IfEquOp:
16561 0 : case M2Quads_IfLessEquOp:
16562 0 : case M2Quads_IfGreEquOp:
16563 0 : case M2Quads_IfGreOp:
16564 0 : case M2Quads_IfLessOp:
16565 0 : case M2Quads_IfNotEquOp:
16566 0 : case M2Quads_IfInOp:
16567 0 : case M2Quads_IfNotInOp:
16568 0 : if ((op3 == q) && (M2Quads_IsConditional (q))) /* run into end of procedure or module */
16569 : {
16570 : return true;
16571 : }
16572 0 : break;
16573 :
16574 :
16575 : default:
16576 : return false;
16577 0 : break;
16578 : }
16579 0 : i = M2Quads_GetNextQuad (i);
16580 : }
16581 0 : M2Error_InternalError ((const char *) "fix this for the sake of efficiency..", 37);
16582 : ReturnException ("/home/worker/buildworker/tiber-lcov/build/gcc/m2/gm2-compiler/M2Quads.def", 20, 1);
16583 : __builtin_unreachable ();
16584 : }
16585 :
16586 :
16587 : /*
16588 : IsGoto - returns true if QuadNo is a goto operation.
16589 : */
16590 :
16591 97025 : extern "C" bool M2Quads_IsGoto (unsigned int QuadNo)
16592 : {
16593 97025 : return IsQuadA (QuadNo, M2Quads_GotoOp);
16594 : /* static analysis guarentees a RETURN statement will be used before here. */
16595 : __builtin_unreachable ();
16596 : }
16597 :
16598 :
16599 : /*
16600 : IsCall - returns true if QuadNo is a call operation.
16601 : */
16602 :
16603 528280363 : extern "C" bool M2Quads_IsCall (unsigned int QuadNo)
16604 : {
16605 528280363 : return IsQuadA (QuadNo, M2Quads_CallOp);
16606 : /* static analysis guarentees a RETURN statement will be used before here. */
16607 : __builtin_unreachable ();
16608 : }
16609 :
16610 :
16611 : /*
16612 : IsReturn - returns true if QuadNo is a return operation.
16613 : */
16614 :
16615 528442403 : extern "C" bool M2Quads_IsReturn (unsigned int QuadNo)
16616 : {
16617 528442403 : return IsQuadA (QuadNo, M2Quads_ReturnOp);
16618 : /* static analysis guarentees a RETURN statement will be used before here. */
16619 : __builtin_unreachable ();
16620 : }
16621 :
16622 :
16623 : /*
16624 : IsProcedureScope - returns true if QuadNo is a ProcedureScope operation.
16625 : */
16626 :
16627 0 : extern "C" bool M2Quads_IsProcedureScope (unsigned int QuadNo)
16628 : {
16629 0 : return IsQuadA (QuadNo, M2Quads_ProcedureScopeOp);
16630 : /* static analysis guarentees a RETURN statement will be used before here. */
16631 : __builtin_unreachable ();
16632 : }
16633 :
16634 :
16635 : /*
16636 : IsNewLocalVar - returns true if QuadNo is a NewLocalVar operation.
16637 : */
16638 :
16639 0 : extern "C" bool M2Quads_IsNewLocalVar (unsigned int QuadNo)
16640 : {
16641 0 : return IsQuadA (QuadNo, M2Quads_NewLocalVarOp);
16642 : /* static analysis guarentees a RETURN statement will be used before here. */
16643 : __builtin_unreachable ();
16644 : }
16645 :
16646 :
16647 : /*
16648 : IsKillLocalVar - returns true if QuadNo is a KillLocalVar operation.
16649 : */
16650 :
16651 254909 : extern "C" bool M2Quads_IsKillLocalVar (unsigned int QuadNo)
16652 : {
16653 254909 : return IsQuadA (QuadNo, M2Quads_KillLocalVarOp);
16654 : /* static analysis guarentees a RETURN statement will be used before here. */
16655 : __builtin_unreachable ();
16656 : }
16657 :
16658 :
16659 : /*
16660 : IsCatchBegin - returns true if QuadNo is a catch begin quad.
16661 : */
16662 :
16663 137120 : extern "C" bool M2Quads_IsCatchBegin (unsigned int QuadNo)
16664 : {
16665 137120 : return IsQuadA (QuadNo, M2Quads_CatchBeginOp);
16666 : /* static analysis guarentees a RETURN statement will be used before here. */
16667 : __builtin_unreachable ();
16668 : }
16669 :
16670 :
16671 : /*
16672 : IsCatchEnd - returns true if QuadNo is a catch end quad.
16673 : */
16674 :
16675 153728 : extern "C" bool M2Quads_IsCatchEnd (unsigned int QuadNo)
16676 : {
16677 153728 : return IsQuadA (QuadNo, M2Quads_CatchEndOp);
16678 : /* static analysis guarentees a RETURN statement will be used before here. */
16679 : __builtin_unreachable ();
16680 : }
16681 :
16682 :
16683 : /*
16684 : IsInitStart - returns true if QuadNo is a init start quad.
16685 : */
16686 :
16687 137120 : extern "C" bool M2Quads_IsInitStart (unsigned int QuadNo)
16688 : {
16689 137120 : return IsQuadA (QuadNo, M2Quads_InitStartOp);
16690 : /* static analysis guarentees a RETURN statement will be used before here. */
16691 : __builtin_unreachable ();
16692 : }
16693 :
16694 :
16695 : /*
16696 : IsInitEnd - returns true if QuadNo is a init end quad.
16697 : */
16698 :
16699 137120 : extern "C" bool M2Quads_IsInitEnd (unsigned int QuadNo)
16700 : {
16701 137120 : return IsQuadA (QuadNo, M2Quads_InitEndOp);
16702 : /* static analysis guarentees a RETURN statement will be used before here. */
16703 : __builtin_unreachable ();
16704 : }
16705 :
16706 :
16707 : /*
16708 : IsFinallyStart - returns true if QuadNo is a finally start quad.
16709 : */
16710 :
16711 131666 : extern "C" bool M2Quads_IsFinallyStart (unsigned int QuadNo)
16712 : {
16713 131666 : return IsQuadA (QuadNo, M2Quads_FinallyStartOp);
16714 : /* static analysis guarentees a RETURN statement will be used before here. */
16715 : __builtin_unreachable ();
16716 : }
16717 :
16718 :
16719 : /*
16720 : IsFinallyEnd - returns true if QuadNo is a finally end quad.
16721 : */
16722 :
16723 126212 : extern "C" bool M2Quads_IsFinallyEnd (unsigned int QuadNo)
16724 : {
16725 126212 : return IsQuadA (QuadNo, M2Quads_FinallyEndOp);
16726 : /* static analysis guarentees a RETURN statement will be used before here. */
16727 : __builtin_unreachable ();
16728 : }
16729 :
16730 :
16731 : /*
16732 : IsBecomes - return TRUE if QuadNo is a BecomesOp.
16733 : */
16734 :
16735 0 : extern "C" bool M2Quads_IsBecomes (unsigned int QuadNo)
16736 : {
16737 0 : return IsQuadA (QuadNo, M2Quads_BecomesOp);
16738 : /* static analysis guarentees a RETURN statement will be used before here. */
16739 : __builtin_unreachable ();
16740 : }
16741 :
16742 :
16743 : /*
16744 : IsDummy - return TRUE if QuadNo is a DummyOp.
16745 : */
16746 :
16747 0 : extern "C" bool M2Quads_IsDummy (unsigned int QuadNo)
16748 : {
16749 0 : return IsQuadA (QuadNo, M2Quads_DummyOp);
16750 : /* static analysis guarentees a RETURN statement will be used before here. */
16751 : __builtin_unreachable ();
16752 : }
16753 :
16754 :
16755 : /*
16756 : IsQuadConstExpr - returns TRUE if QuadNo is part of a constant expression.
16757 : */
16758 :
16759 0 : extern "C" bool M2Quads_IsQuadConstExpr (unsigned int QuadNo)
16760 : {
16761 0 : M2Quads_QuadFrame f;
16762 :
16763 0 : f = GetQF (QuadNo);
16764 0 : return f->ConstExpr;
16765 : /* static analysis guarentees a RETURN statement will be used before here. */
16766 : __builtin_unreachable ();
16767 : }
16768 :
16769 :
16770 : /*
16771 : SetQuadConstExpr - sets the constexpr field to value.
16772 : */
16773 :
16774 0 : extern "C" void M2Quads_SetQuadConstExpr (unsigned int QuadNo, bool value)
16775 : {
16776 0 : M2Quads_QuadFrame f;
16777 :
16778 0 : f = GetQF (QuadNo);
16779 0 : f->ConstExpr = value;
16780 0 : }
16781 :
16782 :
16783 : /*
16784 : GetQuadDest - returns the jump destination associated with quad.
16785 : */
16786 :
16787 0 : extern "C" unsigned int M2Quads_GetQuadDest (unsigned int QuadNo)
16788 : {
16789 0 : return M2Quads_GetQuadOp3 (QuadNo);
16790 : /* static analysis guarentees a RETURN statement will be used before here. */
16791 : __builtin_unreachable ();
16792 : }
16793 :
16794 :
16795 : /*
16796 : GetQuadOp1 - returns the 1st operand associated with quad.
16797 : */
16798 :
16799 0 : extern "C" unsigned int M2Quads_GetQuadOp1 (unsigned int QuadNo)
16800 : {
16801 0 : M2Quads_QuadFrame f;
16802 :
16803 0 : f = GetQF (QuadNo);
16804 0 : return f->Operand1;
16805 : /* static analysis guarentees a RETURN statement will be used before here. */
16806 : __builtin_unreachable ();
16807 : }
16808 :
16809 :
16810 : /*
16811 : GetQuadOp2 - returns the 2nd operand associated with quad.
16812 : */
16813 :
16814 0 : extern "C" unsigned int M2Quads_GetQuadOp2 (unsigned int QuadNo)
16815 : {
16816 0 : M2Quads_QuadFrame f;
16817 :
16818 0 : f = GetQF (QuadNo);
16819 0 : return f->Operand2;
16820 : /* static analysis guarentees a RETURN statement will be used before here. */
16821 : __builtin_unreachable ();
16822 : }
16823 :
16824 :
16825 : /*
16826 : GetQuadOp3 - returns the 3rd operand associated with quad.
16827 : */
16828 :
16829 0 : extern "C" unsigned int M2Quads_GetQuadOp3 (unsigned int QuadNo)
16830 : {
16831 0 : M2Quads_QuadFrame f;
16832 :
16833 0 : f = GetQF (QuadNo);
16834 0 : return f->Operand3;
16835 : /* static analysis guarentees a RETURN statement will be used before here. */
16836 : __builtin_unreachable ();
16837 : }
16838 :
16839 :
16840 : /*
16841 : IsInitialisingConst - returns TRUE if the quadruple is setting
16842 : a const (op1) with a value.
16843 : */
16844 :
16845 0 : extern "C" bool M2Quads_IsInitialisingConst (unsigned int QuadNo)
16846 : {
16847 0 : M2Quads_QuadOperator op;
16848 0 : unsigned int op1;
16849 0 : unsigned int op2;
16850 0 : unsigned int op3;
16851 :
16852 0 : M2Quads_GetQuad (QuadNo, &op, &op1, &op2, &op3);
16853 0 : return (OpUsesOp1 (op)) && (SymbolTable_IsConst (op1));
16854 : /* static analysis guarentees a RETURN statement will be used before here. */
16855 : __builtin_unreachable ();
16856 : }
16857 :
16858 :
16859 : /*
16860 : IsConstQuad - return TRUE if the quadruple is marked as a constexpr.
16861 : */
16862 :
16863 0 : extern "C" bool M2Quads_IsConstQuad (unsigned int quad)
16864 : {
16865 0 : M2Quads_QuadFrame f;
16866 :
16867 0 : f = GetQF (quad);
16868 0 : return f->ConstExpr;
16869 : /* static analysis guarentees a RETURN statement will be used before here. */
16870 : __builtin_unreachable ();
16871 : }
16872 :
16873 :
16874 : /*
16875 : IsConditionalBooleanQuad - return TRUE if operand 1 is a boolean result.
16876 : */
16877 :
16878 425884 : extern "C" bool M2Quads_IsConditionalBooleanQuad (unsigned int quad)
16879 : {
16880 425884 : M2Quads_QuadFrame f;
16881 :
16882 425884 : f = GetQF (quad);
16883 425884 : return ((OpUsesOp1 (f->Operator)) && ((SymbolTable_IsVar (f->Operand1)) || (SymbolTable_IsConst (f->Operand1)))) && (SymbolTable_IsVarConditional (f->Operand1));
16884 : /* static analysis guarentees a RETURN statement will be used before here. */
16885 : __builtin_unreachable ();
16886 : }
16887 :
16888 :
16889 : /*
16890 : IsOptimizeOn - returns true if the Optimize flag was true at QuadNo.
16891 : */
16892 :
16893 0 : extern "C" bool M2Quads_IsOptimizeOn (unsigned int QuadNo)
16894 : {
16895 0 : M2Quads_QuadFrame f;
16896 0 : unsigned int n;
16897 0 : unsigned int q;
16898 0 : bool On;
16899 :
16900 0 : On = M2Options_Optimizing;
16901 0 : q = Head;
16902 0 : while ((q != 0) && (q != QuadNo))
16903 : {
16904 0 : f = GetQF (q);
16905 0 : if (f->Operator == M2Quads_OptimizeOnOp)
16906 : {
16907 : On = true;
16908 : }
16909 0 : else if (f->Operator == M2Quads_OptimizeOffOp)
16910 : {
16911 : /* avoid dangling else. */
16912 0 : On = false;
16913 : }
16914 0 : n = f->Next;
16915 0 : q = n;
16916 : }
16917 0 : return On;
16918 : /* static analysis guarentees a RETURN statement will be used before here. */
16919 : __builtin_unreachable ();
16920 : }
16921 :
16922 :
16923 : /*
16924 : IsProfileOn - returns true if the Profile flag was true at QuadNo.
16925 : */
16926 :
16927 0 : extern "C" bool M2Quads_IsProfileOn (unsigned int QuadNo)
16928 : {
16929 0 : M2Quads_QuadFrame f;
16930 0 : unsigned int n;
16931 0 : unsigned int q;
16932 0 : bool On;
16933 :
16934 0 : On = M2Options_Profiling;
16935 0 : q = Head;
16936 0 : while ((q != 0) && (q != QuadNo))
16937 : {
16938 0 : f = GetQF (q);
16939 0 : if (f->Operator == M2Quads_ProfileOnOp)
16940 : {
16941 : On = true;
16942 : }
16943 0 : else if (f->Operator == M2Quads_ProfileOffOp)
16944 : {
16945 : /* avoid dangling else. */
16946 0 : On = false;
16947 : }
16948 0 : n = f->Next;
16949 0 : q = n;
16950 : }
16951 0 : return On;
16952 : /* static analysis guarentees a RETURN statement will be used before here. */
16953 : __builtin_unreachable ();
16954 : }
16955 :
16956 :
16957 : /*
16958 : IsCodeOn - returns true if the Code flag was true at QuadNo.
16959 : */
16960 :
16961 0 : extern "C" bool M2Quads_IsCodeOn (unsigned int QuadNo)
16962 : {
16963 0 : M2Quads_QuadFrame f;
16964 0 : unsigned int n;
16965 0 : unsigned int q;
16966 0 : bool On;
16967 :
16968 0 : On = M2Options_Coding;
16969 0 : q = Head;
16970 0 : while ((q != 0) && (q != QuadNo))
16971 : {
16972 0 : f = GetQF (q);
16973 0 : if (f->Operator == M2Quads_CodeOnOp)
16974 : {
16975 : On = true;
16976 : }
16977 0 : else if (f->Operator == M2Quads_CodeOffOp)
16978 : {
16979 : /* avoid dangling else. */
16980 0 : On = false;
16981 : }
16982 0 : n = f->Next;
16983 0 : q = n;
16984 : }
16985 0 : return On;
16986 : /* static analysis guarentees a RETURN statement will be used before here. */
16987 : __builtin_unreachable ();
16988 : }
16989 :
16990 :
16991 : /*
16992 : IsPseudoQuad - returns true if QuadNo is a compiler directive.
16993 : ie code, profile and optimize.
16994 : StartFile, EndFile,
16995 : */
16996 :
16997 23406537 : extern "C" bool M2Quads_IsPseudoQuad (unsigned int QuadNo)
16998 : {
16999 23406537 : M2Quads_QuadFrame f;
17000 :
17001 23406537 : f = GetQF (QuadNo);
17002 23406537 : return ((((((((f->Operator == M2Quads_CodeOnOp) || (f->Operator == M2Quads_CodeOffOp)) || (f->Operator == M2Quads_ProfileOnOp)) || (f->Operator == M2Quads_ProfileOffOp)) || (f->Operator == M2Quads_OptimizeOnOp)) || (f->Operator == M2Quads_OptimizeOffOp)) || (f->Operator == M2Quads_EndFileOp)) || (f->Operator == M2Quads_StartDefFileOp)) || (f->Operator == M2Quads_StartModFileOp);
17003 : /* static analysis guarentees a RETURN statement will be used before here. */
17004 : __builtin_unreachable ();
17005 : }
17006 :
17007 :
17008 : /*
17009 : IsDefOrModFile - returns TRUE if QuadNo is a start of Module or Def file
17010 : directive.
17011 : */
17012 :
17013 528183338 : extern "C" bool M2Quads_IsDefOrModFile (unsigned int QuadNo)
17014 : {
17015 528183338 : M2Quads_QuadFrame f;
17016 :
17017 528183338 : f = GetQF (QuadNo);
17018 528183338 : return (f->Operator == M2Quads_StartDefFileOp) || (f->Operator == M2Quads_StartModFileOp);
17019 : /* static analysis guarentees a RETURN statement will be used before here. */
17020 : __builtin_unreachable ();
17021 : }
17022 :
17023 :
17024 : /*
17025 : DumpQuadruples - dump all quadruples providing the -fq, -fdump-lang-quad,
17026 : -fdump-lang-quad= or -fdump-lang-all were issued to the
17027 : command line.
17028 : */
17029 :
17030 73022 : extern "C" void M2Quads_DumpQuadruples (const char *title_, unsigned int _title_high)
17031 : {
17032 73022 : char title[_title_high+1];
17033 :
17034 : /* make a local copy of each unbounded array. */
17035 73022 : memcpy (title, title_, _title_high+1);
17036 :
17037 73022 : if (M2Options_GetDumpQuad ())
17038 : {
17039 0 : M2LangDump_CreateDumpQuad ((const char *) title, _title_high);
17040 0 : if ((M2Options_GetM2DumpFilter ()) == NULL)
17041 : {
17042 0 : DumpQuadrupleAll ();
17043 : }
17044 : else
17045 : {
17046 0 : DumpQuadrupleFilter ();
17047 : }
17048 0 : M2LangDump_CloseDumpQuad ();
17049 : }
17050 73022 : }
17051 :
17052 :
17053 : /*
17054 : DisplayQuadRange - displays all quads in list range, start..end.
17055 : */
17056 :
17057 0 : extern "C" void M2Quads_DisplayQuadRange (unsigned int scope, unsigned int start, unsigned int end)
17058 : {
17059 0 : M2Quads_QuadFrame f;
17060 :
17061 0 : M2Printf_fprintf1 (M2LangDump_GetDumpFile (), (const char *) "Quadruples for scope: %d\\n", 26, (const unsigned char *) &scope, (sizeof (scope)-1));
17062 0 : while ((start <= end) && (start != 0))
17063 : {
17064 0 : M2Quads_DisplayQuad (start);
17065 0 : f = GetQF (start);
17066 0 : start = f->Next;
17067 : }
17068 0 : }
17069 :
17070 :
17071 : /*
17072 : DisplayQuad - displays a quadruple, QuadNo.
17073 : */
17074 :
17075 0 : extern "C" void M2Quads_DisplayQuad (unsigned int QuadNo)
17076 : {
17077 0 : if (QuadNo != 0)
17078 : {
17079 0 : DSdbEnter ();
17080 0 : M2Printf_fprintf1 (M2LangDump_GetDumpFile (), (const char *) "%4d ", 5, (const unsigned char *) &QuadNo, (sizeof (QuadNo)-1));
17081 0 : WriteQuad (QuadNo);
17082 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "\\n", 2);
17083 0 : DSdbExit ();
17084 : }
17085 0 : }
17086 :
17087 :
17088 : /*
17089 : GetLastFileQuad - returns the Quadruple number of the last StartDefFile or
17090 : StartModFile quadruple.
17091 : */
17092 :
17093 0 : extern "C" unsigned int M2Quads_GetLastFileQuad (unsigned int QuadNo)
17094 : {
17095 0 : M2Quads_QuadFrame f;
17096 0 : unsigned int q;
17097 0 : unsigned int i;
17098 0 : unsigned int FileQuad;
17099 :
17100 0 : q = Head;
17101 0 : FileQuad = 0;
17102 0 : do {
17103 0 : f = GetQF (q);
17104 0 : if ((f->Operator == M2Quads_StartModFileOp) || (f->Operator == M2Quads_StartDefFileOp))
17105 : {
17106 0 : FileQuad = q;
17107 : }
17108 0 : i = f->Next;
17109 0 : q = i;
17110 0 : } while (! ((i == QuadNo) || (i == 0)));
17111 0 : M2Debug_Assert (i != 0);
17112 0 : M2Debug_Assert (FileQuad != 0);
17113 0 : return FileQuad;
17114 : /* static analysis guarentees a RETURN statement will be used before here. */
17115 : __builtin_unreachable ();
17116 : }
17117 :
17118 :
17119 : /*
17120 : GetLastQuadNo - returns the last quadruple number referenced
17121 : by a GetQuad.
17122 : */
17123 :
17124 0 : extern "C" unsigned int M2Quads_GetLastQuadNo (void)
17125 : {
17126 0 : return LastQuadNo;
17127 : /* static analysis guarentees a RETURN statement will be used before here. */
17128 : __builtin_unreachable ();
17129 : }
17130 :
17131 :
17132 : /*
17133 : QuadToTokenNo - Converts a QuadNo into the approprate token number of the
17134 : source file, the line number is returned.
17135 :
17136 : This may be used to yield an idea where abouts in the
17137 : source file the code generetion is
17138 : processing.
17139 : */
17140 :
17141 7456763 : extern "C" unsigned int M2Quads_QuadToTokenNo (unsigned int QuadNo)
17142 : {
17143 7456763 : M2Quads_QuadFrame f;
17144 :
17145 7456763 : if ((((LastQuadNo == 0) && (! (M2Pass_IsNoPass ()))) && (! (M2Pass_IsPassCodeGeneration ()))) || (! (Indexing_InBounds (QuadArray, QuadNo))))
17146 : {
17147 0 : return 0;
17148 : }
17149 : else
17150 : {
17151 7456763 : f = GetQF (QuadNo);
17152 7456763 : return f->TokenNo;
17153 : }
17154 : /* static analysis guarentees a RETURN statement will be used before here. */
17155 : __builtin_unreachable ();
17156 : }
17157 :
17158 :
17159 : /*
17160 : QuadToLineNo - Converts a QuadNo into the approprate line number of the
17161 : source file, the line number is returned.
17162 :
17163 : This may be used to yield an idea where abouts in the
17164 : source file the code generetion is
17165 : processing.
17166 : */
17167 :
17168 0 : extern "C" unsigned int M2Quads_QuadToLineNo (unsigned int QuadNo)
17169 : {
17170 0 : M2Quads_QuadFrame f;
17171 :
17172 0 : if ((((LastQuadNo == 0) && (! (M2Pass_IsNoPass ()))) && (! (M2Pass_IsPassCodeGeneration ()))) || (! (Indexing_InBounds (QuadArray, QuadNo))))
17173 : {
17174 0 : return 0;
17175 : }
17176 : else
17177 : {
17178 0 : f = GetQF (QuadNo);
17179 0 : return f->LineNo;
17180 : }
17181 : /* static analysis guarentees a RETURN statement will be used before here. */
17182 : __builtin_unreachable ();
17183 : }
17184 :
17185 :
17186 : /*
17187 : GetQuad - returns the Quadruple QuadNo.
17188 : */
17189 :
17190 2682970632 : extern "C" void M2Quads_GetQuad (unsigned int QuadNo, M2Quads_QuadOperator *Op, unsigned int *Oper1, unsigned int *Oper2, unsigned int *Oper3)
17191 : {
17192 2682970632 : M2Quads_QuadFrame f;
17193 :
17194 2682970632 : f = GetQF (QuadNo);
17195 2682970632 : LastQuadNo = QuadNo;
17196 2682970632 : (*Op) = f->Operator;
17197 2682970632 : (*Oper1) = f->Operand1;
17198 2682970632 : (*Oper2) = f->Operand2;
17199 2682970632 : (*Oper3) = f->Operand3;
17200 2682970632 : }
17201 :
17202 :
17203 : /*
17204 : GetQuadOp - returns the operator for quad.
17205 : */
17206 :
17207 24 : extern "C" M2Quads_QuadOperator M2Quads_GetQuadOp (unsigned int quad)
17208 : {
17209 24 : M2Quads_QuadFrame f;
17210 :
17211 24 : f = GetQF (quad);
17212 24 : return f->Operator;
17213 : /* static analysis guarentees a RETURN statement will be used before here. */
17214 : __builtin_unreachable ();
17215 : }
17216 :
17217 :
17218 : /*
17219 : GetM2OperatorDesc - returns the Modula-2 string associated with the quad operator
17220 : (if possible). It returns NIL if no there is not an obvious match
17221 : in Modula-2. It is assummed that the string will be used during
17222 : construction of error messages and therefore keywords are
17223 : wrapped with a format specifier.
17224 : */
17225 :
17226 31 : extern "C" DynamicStrings_String M2Quads_GetM2OperatorDesc (M2Quads_QuadOperator op)
17227 : {
17228 31 : switch (op)
17229 : {
17230 6 : case M2Quads_NegateOp:
17231 6 : return DynamicStrings_InitString ((const char *) "-", 1);
17232 18 : break;
17233 :
17234 18 : case M2Quads_AddOp:
17235 18 : return DynamicStrings_InitString ((const char *) "+", 1);
17236 0 : break;
17237 :
17238 0 : case M2Quads_SubOp:
17239 0 : return DynamicStrings_InitString ((const char *) "-", 1);
17240 0 : break;
17241 :
17242 0 : case M2Quads_MultOp:
17243 0 : return DynamicStrings_InitString ((const char *) "*", 1);
17244 0 : break;
17245 :
17246 0 : case M2Quads_DivM2Op:
17247 0 : case M2Quads_DivCeilOp:
17248 0 : case M2Quads_DivFloorOp:
17249 0 : case M2Quads_DivTruncOp:
17250 0 : return DynamicStrings_InitString ((const char *) "{%kDIV}", 7);
17251 0 : break;
17252 :
17253 0 : case M2Quads_ModM2Op:
17254 0 : case M2Quads_ModCeilOp:
17255 0 : case M2Quads_ModFloorOp:
17256 0 : return DynamicStrings_InitString ((const char *) "{%kMOD}", 7);
17257 0 : break;
17258 :
17259 0 : case M2Quads_ModTruncOp:
17260 0 : return DynamicStrings_InitString ((const char *) "{%kREM}", 7);
17261 0 : break;
17262 :
17263 0 : case M2Quads_LogicalOrOp:
17264 0 : return DynamicStrings_InitString ((const char *) "{%kOR}", 6);
17265 0 : break;
17266 :
17267 0 : case M2Quads_LogicalAndOp:
17268 0 : return DynamicStrings_InitString ((const char *) "{%kAND}", 7);
17269 0 : break;
17270 :
17271 0 : case M2Quads_InclOp:
17272 0 : return DynamicStrings_InitString ((const char *) "{%kINCL}", 8);
17273 0 : break;
17274 :
17275 0 : case M2Quads_ExclOp:
17276 0 : return DynamicStrings_InitString ((const char *) "{%kEXCL}", 8);
17277 7 : break;
17278 :
17279 7 : case M2Quads_IfEquOp:
17280 7 : return DynamicStrings_InitString ((const char *) "=", 1);
17281 0 : break;
17282 :
17283 0 : case M2Quads_IfLessEquOp:
17284 0 : return DynamicStrings_InitString ((const char *) "<=", 2);
17285 0 : break;
17286 :
17287 0 : case M2Quads_IfGreEquOp:
17288 0 : return DynamicStrings_InitString ((const char *) ">=", 2);
17289 0 : break;
17290 :
17291 0 : case M2Quads_IfGreOp:
17292 0 : return DynamicStrings_InitString ((const char *) ">", 1);
17293 0 : break;
17294 :
17295 0 : case M2Quads_IfLessOp:
17296 0 : return DynamicStrings_InitString ((const char *) "<", 1);
17297 0 : break;
17298 :
17299 0 : case M2Quads_IfNotEquOp:
17300 0 : return DynamicStrings_InitString ((const char *) "#", 1);
17301 0 : break;
17302 :
17303 0 : case M2Quads_IfInOp:
17304 0 : return DynamicStrings_InitString ((const char *) "IN", 2);
17305 0 : break;
17306 :
17307 0 : case M2Quads_IfNotInOp:
17308 0 : return DynamicStrings_InitString ((const char *) "NOT IN", 6);
17309 : break;
17310 :
17311 :
17312 : default:
17313 : return static_cast<DynamicStrings_String> (NULL);
17314 : break;
17315 : }
17316 : /* static analysis guarentees a RETURN statement will be used before here. */
17317 : __builtin_unreachable ();
17318 : }
17319 :
17320 :
17321 : /*
17322 : GetQuadtok - returns the Quadruple QuadNo.
17323 : */
17324 :
17325 173335803 : extern "C" void M2Quads_GetQuadtok (unsigned int QuadNo, M2Quads_QuadOperator *Op, unsigned int *Oper1, unsigned int *Oper2, unsigned int *Oper3, unsigned int *Op1Pos, unsigned int *Op2Pos, unsigned int *Op3Pos)
17326 : {
17327 173335803 : M2Quads_QuadFrame f;
17328 :
17329 173335803 : f = GetQF (QuadNo);
17330 173335803 : LastQuadNo = QuadNo;
17331 173335803 : (*Op) = f->Operator;
17332 173335803 : (*Oper1) = f->Operand1;
17333 173335803 : (*Oper2) = f->Operand2;
17334 173335803 : (*Oper3) = f->Operand3;
17335 173335803 : (*Op1Pos) = f->op1pos;
17336 173335803 : (*Op2Pos) = f->op2pos;
17337 173335803 : (*Op3Pos) = f->op3pos;
17338 173335803 : }
17339 :
17340 :
17341 : /*
17342 : GetQuadOtok - returns the Quadruple QuadNo.
17343 : */
17344 :
17345 6989103 : extern "C" void M2Quads_GetQuadOtok (unsigned int QuadNo, unsigned int *tok, M2Quads_QuadOperator *Op, unsigned int *Oper1, unsigned int *Oper2, unsigned int *Oper3, bool *overflowChecking, bool *constExpr, unsigned int *Op1Pos, unsigned int *Op2Pos, unsigned int *Op3Pos)
17346 : {
17347 6989103 : M2Quads_QuadFrame f;
17348 :
17349 6989103 : f = GetQF (QuadNo);
17350 6989103 : LastQuadNo = QuadNo;
17351 6989103 : (*Op) = f->Operator;
17352 6989103 : (*Oper1) = f->Operand1;
17353 6989103 : (*Oper2) = f->Operand2;
17354 6989103 : (*Oper3) = f->Operand3;
17355 6989103 : (*Op1Pos) = f->op1pos;
17356 6989103 : (*Op2Pos) = f->op2pos;
17357 6989103 : (*Op3Pos) = f->op3pos;
17358 6989103 : (*tok) = f->TokenNo;
17359 6989103 : (*overflowChecking) = f->CheckOverflow;
17360 6989103 : (*constExpr) = f->ConstExpr;
17361 6989103 : }
17362 :
17363 :
17364 : /*
17365 : GetQuadOTypetok - returns the fields associated with quadruple QuadNo.
17366 : */
17367 :
17368 6668 : extern "C" void M2Quads_GetQuadOTypetok (unsigned int QuadNo, unsigned int *tok, M2Quads_QuadOperator *Op, unsigned int *Oper1, unsigned int *Oper2, unsigned int *Oper3, bool *overflowChecking, bool *typeChecking, bool *constExpr, unsigned int *Op1Pos, unsigned int *Op2Pos, unsigned int *Op3Pos)
17369 : {
17370 6668 : M2Quads_QuadFrame f;
17371 :
17372 6668 : f = GetQF (QuadNo);
17373 6668 : LastQuadNo = QuadNo;
17374 6668 : (*Op) = f->Operator;
17375 6668 : (*Oper1) = f->Operand1;
17376 6668 : (*Oper2) = f->Operand2;
17377 6668 : (*Oper3) = f->Operand3;
17378 6668 : (*Op1Pos) = f->op1pos;
17379 6668 : (*Op2Pos) = f->op2pos;
17380 6668 : (*Op3Pos) = f->op3pos;
17381 6668 : (*tok) = f->TokenNo;
17382 6668 : (*overflowChecking) = f->CheckOverflow;
17383 6668 : (*typeChecking) = f->CheckType;
17384 6668 : (*constExpr) = f->ConstExpr;
17385 6668 : }
17386 :
17387 :
17388 : /*
17389 : PutQuadOtok - alters a quadruple QuadNo with Op, Oper1, Oper2, Oper3, and
17390 : sets a boolean to determinine whether overflow should be checked.
17391 : */
17392 :
17393 82181 : extern "C" void M2Quads_PutQuadOtok (unsigned int QuadNo, unsigned int tok, M2Quads_QuadOperator Op, unsigned int Oper1, unsigned int Oper2, unsigned int Oper3, bool overflowChecking, bool constExpr, unsigned int Op1Pos, unsigned int Op2Pos, unsigned int Op3Pos)
17394 : {
17395 82181 : M2Quads_QuadFrame f;
17396 :
17397 82181 : if (QuadrupleGeneration)
17398 : {
17399 82181 : M2Quads_EraseQuad (QuadNo);
17400 82181 : AddQuadInformation (QuadNo, Op, Oper1, Oper2, Oper3);
17401 82181 : f = GetQF (QuadNo);
17402 82181 : f->Operator = Op;
17403 82181 : f->Operand1 = Oper1;
17404 82181 : f->Operand2 = Oper2;
17405 82181 : f->Operand3 = Oper3;
17406 82181 : f->CheckOverflow = overflowChecking;
17407 82181 : f->op1pos = Op1Pos;
17408 82181 : f->op2pos = Op2Pos;
17409 82181 : f->op3pos = Op3Pos;
17410 82181 : f->TokenNo = tok;
17411 82181 : f->ConstExpr = constExpr;
17412 : }
17413 82181 : }
17414 :
17415 :
17416 : /*
17417 : PutQuad - overwrites a quadruple QuadNo with Op, Oper1, Oper2, Oper3
17418 : */
17419 :
17420 14721 : extern "C" void M2Quads_PutQuad (unsigned int QuadNo, M2Quads_QuadOperator Op, unsigned int Oper1, unsigned int Oper2, unsigned int Oper3)
17421 : {
17422 14721 : PutQuadO (QuadNo, Op, Oper1, Oper2, Oper3, true);
17423 14721 : }
17424 :
17425 :
17426 : /*
17427 : GetFirstQuad - returns the first quadruple.
17428 : */
17429 :
17430 801534 : extern "C" unsigned int M2Quads_GetFirstQuad (void)
17431 : {
17432 801534 : return Head;
17433 : /* static analysis guarentees a RETURN statement will be used before here. */
17434 : __builtin_unreachable ();
17435 : }
17436 :
17437 :
17438 : /*
17439 : GetNextQuad - returns the Quadruple number following QuadNo.
17440 : */
17441 :
17442 3385034129 : extern "C" unsigned int M2Quads_GetNextQuad (unsigned int QuadNo)
17443 : {
17444 3385034129 : M2Quads_QuadFrame f;
17445 :
17446 3385034129 : f = GetQF (QuadNo);
17447 3385034129 : return f->Next;
17448 : /* static analysis guarentees a RETURN statement will be used before here. */
17449 : __builtin_unreachable ();
17450 : }
17451 :
17452 :
17453 : /*
17454 : GetRealQuad - returns the Quadruple number of the real quadruple
17455 : at QuadNo or beyond.
17456 : */
17457 :
17458 15341236 : extern "C" unsigned int M2Quads_GetRealQuad (unsigned int QuadNo)
17459 : {
17460 15341236 : M2Quads_QuadFrame f;
17461 :
17462 23323530 : while (QuadNo != 0)
17463 : {
17464 23323530 : if (Indexing_InBounds (QuadArray, QuadNo))
17465 : {
17466 23239043 : f = GetQF (QuadNo);
17467 23239043 : if ((((! (M2Quads_IsPseudoQuad (QuadNo))) && (f->Operator != M2Quads_DummyOp)) && (f->Operator != M2Quads_LineNumberOp)) && (f->Operator != M2Quads_StatementNoteOp))
17468 : {
17469 : return QuadNo;
17470 : }
17471 7982294 : QuadNo += 1;
17472 : }
17473 : else
17474 : {
17475 : return 0;
17476 : }
17477 : }
17478 : return 0;
17479 : /* static analysis guarentees a RETURN statement will be used before here. */
17480 : __builtin_unreachable ();
17481 : }
17482 :
17483 :
17484 : /*
17485 : SubQuad - subtracts a quadruple QuadNo from a list Head.
17486 : */
17487 :
17488 1928561 : extern "C" void M2Quads_SubQuad (unsigned int QuadNo)
17489 : {
17490 1928561 : unsigned int i;
17491 1928561 : M2Quads_QuadFrame f;
17492 1928561 : M2Quads_QuadFrame g;
17493 :
17494 1928561 : CheckBreak (QuadNo);
17495 1928561 : f = GetQF (QuadNo);
17496 1928561 : AlterReference (Head, QuadNo, f->Next);
17497 1928561 : UndoReadWriteInfo (QuadNo, f->Operator, f->Operand1, f->Operand2, f->Operand3);
17498 1928561 : if (Head == QuadNo)
17499 : {
17500 0 : Head = f->Next;
17501 : }
17502 : else
17503 : {
17504 1928561 : i = Head;
17505 1928561 : g = GetQF (i);
17506 5044066260 : while (g->Next != QuadNo)
17507 : {
17508 5040209138 : i = g->Next;
17509 5040209138 : g = GetQF (i);
17510 : }
17511 1928561 : g->Next = f->Next;
17512 : }
17513 1928561 : f->Operator = M2Quads_DummyOp;
17514 1928561 : NoOfQuads -= 1;
17515 1928561 : }
17516 :
17517 :
17518 : /*
17519 : EraseQuad - erases a quadruple QuadNo, the quadruple is still in the list
17520 : but wiped clean.
17521 : */
17522 :
17523 6411484 : extern "C" void M2Quads_EraseQuad (unsigned int QuadNo)
17524 : {
17525 6411484 : M2Quads_QuadFrame f;
17526 :
17527 6411484 : CheckBreak (QuadNo);
17528 6411484 : f = GetQF (QuadNo);
17529 6411484 : UndoReadWriteInfo (QuadNo, f->Operator, f->Operand1, f->Operand2, f->Operand3);
17530 6411484 : f->Operator = M2Quads_DummyOp; /* finally blank it out */
17531 6411484 : f->Operand1 = 0; /* finally blank it out */
17532 6411484 : f->Operand2 = 0;
17533 6411484 : f->Operand3 = 0;
17534 6411484 : f->Trash = 0;
17535 6411484 : f->op1pos = M2LexBuf_UnknownTokenNo;
17536 6411484 : f->op2pos = M2LexBuf_UnknownTokenNo;
17537 6411484 : f->op3pos = M2LexBuf_UnknownTokenNo;
17538 6411484 : f->ConstExpr = false;
17539 6411484 : }
17540 :
17541 :
17542 : /*
17543 : CountQuads - returns the number of quadruples.
17544 : */
17545 :
17546 9219529 : extern "C" unsigned int M2Quads_CountQuads (void)
17547 : {
17548 9219529 : return NoOfQuads;
17549 : /* static analysis guarentees a RETURN statement will be used before here. */
17550 : __builtin_unreachable ();
17551 : }
17552 :
17553 :
17554 : /*
17555 : BuildScaffold - generate the main, init, finish functions if
17556 : no -c and this is the application module.
17557 : */
17558 :
17559 15827 : extern "C" void M2Quads_BuildScaffold (unsigned int tok, unsigned int moduleSym)
17560 : {
17561 15827 : if ((SymbolTable_GetMainModule ()) == moduleSym)
17562 : {
17563 15299 : M2Scaffold_DeclareScaffold (tok);
17564 15299 : if (M2Options_ScaffoldMain || ! M2Options_cflag)
17565 : {
17566 : /* There are module init/fini functions and
17567 : application init/fini functions.
17568 : Here we create the application pair. */
17569 2783 : BuildM2LinkFunction (tok);
17570 2783 : BuildM2MainFunction (tok);
17571 2783 : BuildM2InitFunction (tok, moduleSym); /* Application init. */
17572 2783 : BuildM2FiniFunction (tok, moduleSym); /* Application fini. */
17573 : }
17574 : /* Application fini. */
17575 15299 : BuildM2DepFunction (tok, moduleSym); /* Per module dependency. */
17576 : /* Each module needs a ctor to register the module
17577 : init/finish/dep with M2RTS. */
17578 15299 : BuildM2CtorFunction (tok, moduleSym);
17579 : }
17580 528 : else if (M2Options_WholeProgram)
17581 : {
17582 : /* avoid dangling else. */
17583 528 : M2Scaffold_DeclareScaffold (tok);
17584 528 : BuildM2DepFunction (tok, moduleSym); /* Per module dependency. */
17585 : /* Each module needs a ctor to register the module
17586 : init/finish/dep with M2RTS. */
17587 528 : BuildM2CtorFunction (tok, moduleSym);
17588 : }
17589 15827 : }
17590 :
17591 :
17592 : /*
17593 : StartBuildDefFile - generates a StartFileDefOp quadruple indicating the file
17594 : that has produced the subsequent quadruples.
17595 : The code generator uses the StartDefFileOp quadruples
17596 : to relate any error to the appropriate file.
17597 :
17598 :
17599 : Entry Exit
17600 : ===== ====
17601 :
17602 :
17603 : Ptr -> <- Ptr
17604 : +------------+ +------------+
17605 : | ModuleName | | ModuleName |
17606 : |------------| |------------|
17607 :
17608 :
17609 : Quadruples Produced
17610 :
17611 : q StartDefFileOp _ _ ModuleSym
17612 : */
17613 :
17614 165950 : extern "C" void M2Quads_StartBuildDefFile (unsigned int tok)
17615 : {
17616 165950 : NameKey_Name ModuleName;
17617 :
17618 165950 : M2Quads_PopT (&ModuleName);
17619 165950 : M2Quads_PushT (ModuleName);
17620 165950 : GenQuadO (tok, M2Quads_StartDefFileOp, tok, SymbolTable_NulSym, SymbolTable_GetModule (ModuleName), false);
17621 165950 : }
17622 :
17623 :
17624 : /*
17625 : StartBuildModFile - generates a StartModFileOp quadruple indicating the file
17626 : that has produced the subsequent quadruples.
17627 : The code generator uses the StartModFileOp quadruples
17628 : to relate any error to the appropriate file.
17629 :
17630 :
17631 : Entry Exit
17632 : ===== ====
17633 :
17634 :
17635 : Ptr -> <- Ptr
17636 : +------------+ +------------+
17637 : | ModuleName | | ModuleName |
17638 : |------------| |------------|
17639 :
17640 :
17641 : Quadruples Produced
17642 :
17643 : q StartModFileOp lineno filename ModuleSym
17644 : */
17645 :
17646 84473 : extern "C" void M2Quads_StartBuildModFile (unsigned int tok)
17647 : {
17648 84473 : GenQuadO (tok, M2Quads_StartModFileOp, tok, (unsigned int ) (NameKey_makekey (DynamicStrings_string (M2LexBuf_GetFileName ()))), SymbolTable_GetFileModule (), false);
17649 84473 : }
17650 :
17651 :
17652 : /*
17653 : EndBuildFile - generates an EndFileOp quadruple indicating the file
17654 : that has produced the previous quadruples has ended.
17655 :
17656 : Entry Exit
17657 : ===== ====
17658 :
17659 :
17660 : Ptr -> <- Ptr
17661 : +------------+ +------------+
17662 : | ModuleName | | ModuleName |
17663 : |------------| |------------|
17664 :
17665 :
17666 : Quadruples Produced
17667 :
17668 : q EndFileOp _ _ ModuleSym
17669 : */
17670 :
17671 250209 : extern "C" void M2Quads_EndBuildFile (unsigned int tok)
17672 : {
17673 250209 : NameKey_Name ModuleName;
17674 :
17675 250209 : ModuleName = static_cast<NameKey_Name> (M2Quads_OperandT (1));
17676 250209 : GenQuadO (tok, M2Quads_EndFileOp, SymbolTable_NulSym, SymbolTable_NulSym, SymbolTable_GetModule (ModuleName), false);
17677 250209 : }
17678 :
17679 :
17680 : /*
17681 : StartBuildInit - Sets the start of initialization code of the
17682 : current module to the next quadruple.
17683 : */
17684 :
17685 84839 : extern "C" void M2Quads_StartBuildInit (unsigned int tok)
17686 : {
17687 84839 : NameKey_Name name;
17688 84839 : unsigned int ModuleSym;
17689 :
17690 84839 : M2Quads_PopT (&name);
17691 84839 : ModuleSym = SymbolTable_GetCurrentModule ();
17692 169678 : M2Debug_Assert ((SymbolTable_IsModule (ModuleSym)) || (SymbolTable_IsDefImp (ModuleSym)));
17693 84839 : M2Debug_Assert ((SymbolTable_GetSymName (ModuleSym)) == name);
17694 84833 : SymbolTable_PutModuleStartQuad (ModuleSym, NextQuad);
17695 84833 : GenQuad (M2Quads_InitStartOp, tok, SymbolTable_GetFileModule (), ModuleSym);
17696 84833 : M2StackWord_PushWord (ReturnStack, static_cast<unsigned int> (0));
17697 84833 : M2Quads_PushT (name);
17698 84833 : CheckVariablesAt (ModuleSym);
17699 84833 : CheckNeedPriorityBegin (tok, ModuleSym, ModuleSym);
17700 84833 : M2StackWord_PushWord (TryStack, NextQuad);
17701 84833 : M2StackWord_PushWord (CatchStack, static_cast<unsigned int> (0));
17702 84833 : if (SymbolTable_HasExceptionBlock (ModuleSym))
17703 : {
17704 54 : GenQuad (M2Quads_TryOp, SymbolTable_NulSym, SymbolTable_NulSym, 0);
17705 : }
17706 84833 : }
17707 :
17708 :
17709 : /*
17710 : EndBuildInit - Sets the end initialization code of a module.
17711 : */
17712 :
17713 84685 : extern "C" void M2Quads_EndBuildInit (unsigned int tok)
17714 : {
17715 84685 : if (SymbolTable_HasExceptionBlock (SymbolTable_GetCurrentModule ()))
17716 : {
17717 54 : BuildRTExceptLeave (tok, true);
17718 54 : GenQuadO (tok, M2Quads_CatchEndOp, SymbolTable_NulSym, SymbolTable_NulSym, SymbolTable_NulSym, false);
17719 : }
17720 84685 : BackPatch (M2StackWord_PopWord (ReturnStack), NextQuad);
17721 84685 : CheckNeedPriorityEnd (tok, SymbolTable_GetCurrentModule (), SymbolTable_GetCurrentModule ());
17722 84685 : SymbolTable_PutModuleEndQuad (SymbolTable_GetCurrentModule (), NextQuad);
17723 84685 : CheckVariablesInBlock (SymbolTable_GetCurrentModule ());
17724 84685 : GenQuadO (tok, M2Quads_InitEndOp, tok, SymbolTable_GetFileModule (), SymbolTable_GetCurrentModule (), false);
17725 84685 : }
17726 :
17727 :
17728 : /*
17729 : StartBuildFinally - Sets the start of finalization code of the
17730 : current module to the next quadruple.
17731 : */
17732 :
17733 16039 : extern "C" void M2Quads_StartBuildFinally (unsigned int tok)
17734 : {
17735 16039 : NameKey_Name name;
17736 16039 : unsigned int ModuleSym;
17737 :
17738 16039 : M2Quads_PopT (&name);
17739 16033 : ModuleSym = SymbolTable_GetCurrentModule ();
17740 32066 : M2Debug_Assert ((SymbolTable_IsModule (ModuleSym)) || (SymbolTable_IsDefImp (ModuleSym)));
17741 16033 : M2Debug_Assert ((SymbolTable_GetSymName (ModuleSym)) == name);
17742 16033 : SymbolTable_PutModuleFinallyStartQuad (ModuleSym, NextQuad);
17743 16033 : GenQuadO (tok, M2Quads_FinallyStartOp, tok, SymbolTable_GetFileModule (), ModuleSym, false);
17744 16033 : M2StackWord_PushWord (ReturnStack, static_cast<unsigned int> (0));
17745 16033 : M2Quads_PushT (name);
17746 : /* CheckVariablesAt(ModuleSym) ; */
17747 16033 : CheckNeedPriorityBegin (tok, ModuleSym, ModuleSym);
17748 16033 : M2StackWord_PushWord (TryStack, NextQuad);
17749 16033 : M2StackWord_PushWord (CatchStack, static_cast<unsigned int> (0));
17750 16033 : if (SymbolTable_HasExceptionFinally (ModuleSym))
17751 : {
17752 0 : GenQuadO (tok, M2Quads_TryOp, SymbolTable_NulSym, SymbolTable_NulSym, 0, false);
17753 : }
17754 16033 : }
17755 :
17756 :
17757 : /*
17758 : EndBuildFinally - Sets the end finalization code of a module.
17759 : */
17760 :
17761 16033 : extern "C" void M2Quads_EndBuildFinally (unsigned int tok)
17762 : {
17763 16033 : if (SymbolTable_HasExceptionFinally (SymbolTable_GetCurrentModule ()))
17764 : {
17765 0 : BuildRTExceptLeave (tok, true);
17766 0 : GenQuadO (tok, M2Quads_CatchEndOp, SymbolTable_NulSym, SymbolTable_NulSym, SymbolTable_NulSym, false);
17767 : }
17768 16033 : BackPatch (M2StackWord_PopWord (ReturnStack), NextQuad);
17769 16033 : CheckNeedPriorityEnd (tok, SymbolTable_GetCurrentModule (), SymbolTable_GetCurrentModule ());
17770 16033 : SymbolTable_PutModuleFinallyEndQuad (SymbolTable_GetCurrentModule (), NextQuad);
17771 16033 : CheckVariablesInBlock (SymbolTable_GetCurrentModule ());
17772 16033 : GenQuadO (tok, M2Quads_FinallyEndOp, tok, SymbolTable_GetFileModule (), SymbolTable_GetCurrentModule (), false);
17773 16033 : }
17774 :
17775 :
17776 : /*
17777 : BuildExceptInitial - adds an CatchBeginOp, CatchEndOp quadruple
17778 : in the current block.
17779 : */
17780 :
17781 2969 : extern "C" void M2Quads_BuildExceptInitial (unsigned int tok)
17782 : {
17783 2969 : unsigned int previous;
17784 :
17785 : /* we have finished the 'try' block, so now goto the return
17786 : section which will tidy up (any) priorities before returning.
17787 : */
17788 2969 : GenQuadO (tok, M2Quads_GotoOp, SymbolTable_NulSym, SymbolTable_NulSym, M2StackWord_PopWord (ReturnStack), false);
17789 2969 : M2StackWord_PushWord (ReturnStack, NextQuad-1);
17790 : /*
17791 : this is the 'catch' block.
17792 : */
17793 2969 : BackPatch (M2StackWord_PeepWord (TryStack, 1), NextQuad);
17794 2969 : GenQuadO (tok, M2Quads_CatchBeginOp, SymbolTable_NulSym, SymbolTable_NulSym, SymbolTable_NulSym, false);
17795 2969 : previous = static_cast<unsigned int> (M2StackWord_PopWord (CatchStack));
17796 2969 : if (previous != 0)
17797 : {
17798 0 : M2MetaError_MetaErrorT0 (tok, (const char *) "{%E}only allowed one EXCEPT statement in a procedure or module", 62);
17799 : }
17800 2969 : M2StackWord_PushWord (CatchStack, NextQuad-1);
17801 2969 : BuildRTExceptEnter (tok);
17802 2969 : }
17803 :
17804 :
17805 : /*
17806 : BuildExceptFinally - adds an ExceptOp quadruple in a modules
17807 : finally block.
17808 : */
17809 :
17810 0 : extern "C" void M2Quads_BuildExceptFinally (unsigned int tok)
17811 : {
17812 0 : M2Quads_BuildExceptInitial (tok);
17813 0 : }
17814 :
17815 :
17816 : /*
17817 : BuildExceptProcedure - adds an ExceptOp quadruple in a procedure
17818 : block.
17819 : */
17820 :
17821 168 : extern "C" void M2Quads_BuildExceptProcedure (unsigned int tok)
17822 : {
17823 168 : M2Quads_BuildExceptInitial (tok);
17824 168 : }
17825 :
17826 :
17827 : /*
17828 : BuildRetry - adds an RetryOp quadruple.
17829 : */
17830 :
17831 168 : extern "C" void M2Quads_BuildRetry (unsigned int tok)
17832 : {
17833 168 : if ((M2StackWord_PeepWord (CatchStack, 1)) == 0)
17834 : {
17835 6 : M2MetaError_MetaErrorT0 (tok, (const char *) "{%E}the {%kRETRY} statement must occur after an {%kEXCEPT} statement in the same module or procedure block", 106);
17836 : }
17837 : else
17838 : {
17839 162 : BuildRTExceptLeave (tok, false);
17840 162 : GenQuadO (tok, M2Quads_RetryOp, SymbolTable_NulSym, SymbolTable_NulSym, M2StackWord_PeepWord (TryStack, 1), false);
17841 : }
17842 168 : }
17843 :
17844 :
17845 : /*
17846 : BuildReThrow - creates a ThrowOp _ _ NulSym, indicating that
17847 : the exception needs to be rethrown. The stack
17848 : is unaltered.
17849 : */
17850 :
17851 222 : extern "C" void M2Quads_BuildReThrow (unsigned int tokenno)
17852 : {
17853 222 : GenQuadO (tokenno, M2Quads_ThrowOp, SymbolTable_NulSym, SymbolTable_NulSym, SymbolTable_NulSym, false);
17854 222 : }
17855 :
17856 :
17857 : /*
17858 : StartBuildInnerInit - Sets the start of initialization code of the
17859 : inner module to the next quadruple.
17860 : */
17861 :
17862 0 : extern "C" void M2Quads_StartBuildInnerInit (unsigned int tok)
17863 : {
17864 0 : SymbolTable_PutModuleStartQuad (SymbolTable_GetCurrentModule (), NextQuad);
17865 0 : GenQuadO (tok, M2Quads_InitStartOp, tok, SymbolTable_NulSym, SymbolTable_GetCurrentModule (), false);
17866 0 : M2StackWord_PushWord (ReturnStack, static_cast<unsigned int> (0));
17867 0 : CheckNeedPriorityBegin (tok, SymbolTable_GetCurrentModule (), SymbolTable_GetCurrentModule ());
17868 0 : M2StackWord_PushWord (TryStack, NextQuad);
17869 0 : M2StackWord_PushWord (CatchStack, static_cast<unsigned int> (0));
17870 0 : if (SymbolTable_HasExceptionFinally (SymbolTable_GetCurrentModule ()))
17871 : {
17872 0 : GenQuadO (tok, M2Quads_TryOp, SymbolTable_NulSym, SymbolTable_NulSym, 0, false);
17873 : }
17874 0 : }
17875 :
17876 :
17877 : /*
17878 : EndBuildInnerInit - Sets the end initialization code of a module.
17879 : */
17880 :
17881 0 : extern "C" void M2Quads_EndBuildInnerInit (unsigned int tok)
17882 : {
17883 0 : if (SymbolTable_HasExceptionBlock (SymbolTable_GetCurrentModule ()))
17884 : {
17885 0 : BuildRTExceptLeave (tok, true);
17886 0 : GenQuadO (tok, M2Quads_CatchEndOp, SymbolTable_NulSym, SymbolTable_NulSym, SymbolTable_NulSym, false);
17887 : }
17888 0 : SymbolTable_PutModuleEndQuad (SymbolTable_GetCurrentModule (), NextQuad);
17889 0 : CheckVariablesInBlock (SymbolTable_GetCurrentModule ());
17890 0 : BackPatch (M2StackWord_PopWord (ReturnStack), NextQuad);
17891 0 : CheckNeedPriorityEnd (tok, SymbolTable_GetCurrentModule (), SymbolTable_GetCurrentModule ());
17892 0 : GenQuadO (tok, M2Quads_InitEndOp, tok, SymbolTable_NulSym, SymbolTable_GetCurrentModule (), false);
17893 0 : }
17894 :
17895 :
17896 : /*
17897 : BuildBuiltinConst - makes reference to a builtin constant within gm2.
17898 :
17899 : Entry Exit
17900 :
17901 : Ptr ->
17902 : +------------+ +------------+
17903 : | Ident | | Sym |
17904 : |------------| |------------|
17905 :
17906 : Quadruple produced:
17907 :
17908 : q Sym BuiltinConstOp Ident
17909 : */
17910 :
17911 30174 : extern "C" void M2Quads_BuildBuiltinConst (void)
17912 : {
17913 30174 : unsigned int idtok;
17914 30174 : unsigned int Id;
17915 30174 : unsigned int Sym;
17916 :
17917 30174 : M2Quads_PopTtok (&Id, &idtok);
17918 30174 : Sym = SymbolTable_MakeTemporary (idtok, SymbolTable_ImmediateValue);
17919 30174 : SymbolTable_PutVar (Sym, M2Base_Integer);
17920 : /*
17921 : CASE GetBuiltinConstType(KeyToCharStar(Name(Id))) OF
17922 :
17923 : 0: ErrorFormat1(NewError(GetTokenNo()),
17924 : '%a unrecognised builtin constant', Id) |
17925 : 1: PutVar(Sym, Integer) |
17926 : 2: PutVar(Sym, Real)
17927 :
17928 : ELSE
17929 : InternalError ('unrecognised value')
17930 : END ;
17931 : */
17932 30174 : GenQuadO (idtok, M2Quads_BuiltinConstOp, Sym, SymbolTable_NulSym, Id, false);
17933 30174 : M2Quads_PushTtok (Sym, idtok);
17934 30174 : }
17935 :
17936 :
17937 : /*
17938 : BuildBuiltinTypeInfo - make reference to a builtin typeinfo function
17939 : within gm2.
17940 :
17941 : Entry Exit
17942 :
17943 : Ptr ->
17944 : +-------------+
17945 : | Type |
17946 : |-------------| +------------+
17947 : | Ident | | Sym |
17948 : |-------------| |------------|
17949 :
17950 : Quadruple produced:
17951 :
17952 : q Sym BuiltinTypeInfoOp Type Ident
17953 : */
17954 :
17955 360 : extern "C" void M2Quads_BuildBuiltinTypeInfo (void)
17956 : {
17957 360 : unsigned int idtok;
17958 360 : unsigned int Ident;
17959 360 : unsigned int Type;
17960 360 : unsigned int Sym;
17961 :
17962 360 : M2Quads_PopTtok (&Ident, &idtok);
17963 360 : M2Quads_PopT (&Type);
17964 360 : Sym = SymbolTable_MakeTemporary (M2LexBuf_BuiltinTokenNo, SymbolTable_ImmediateValue);
17965 360 : switch (m2builtins_GetBuiltinTypeInfoType (const_cast <const char * > (static_cast <char * > (NameKey_KeyToCharStar ((NameKey_Name) (Ident))))))
17966 : {
17967 0 : case 0:
17968 0 : M2Error_ErrorFormat1 (M2Error_NewError (idtok), (const char *) "%a unrecognised builtin constant", 32, (const unsigned char *) &Ident, (sizeof (Ident)-1));
17969 0 : break;
17970 :
17971 192 : case 1:
17972 192 : SymbolTable_PutVar (Sym, M2Base_Boolean);
17973 192 : break;
17974 :
17975 120 : case 2:
17976 120 : SymbolTable_PutVar (Sym, M2Base_ZType);
17977 120 : break;
17978 :
17979 48 : case 3:
17980 48 : SymbolTable_PutVar (Sym, M2Base_RType);
17981 48 : break;
17982 :
17983 :
17984 0 : default:
17985 0 : M2Error_InternalError ((const char *) "unrecognised value", 18);
17986 360 : break;
17987 : }
17988 360 : GenQuadO (idtok, M2Quads_BuiltinTypeInfoOp, Sym, Type, Ident, false);
17989 360 : M2Quads_PushTtok (Sym, idtok);
17990 360 : }
17991 :
17992 :
17993 : /*
17994 : BuildAssignment - Builds an assignment from the values given on the
17995 : quad stack. Either an assignment to an
17996 : arithmetic expression or an assignment to a
17997 : boolean expression. This procedure should not
17998 : be called in CONST declarations.
17999 : The Stack is expected to contain:
18000 :
18001 :
18002 : Either
18003 :
18004 : Entry Exit
18005 : ===== ====
18006 :
18007 : Ptr ->
18008 : +------------+
18009 : | Expression |
18010 : |------------|
18011 : | Designator |
18012 : |------------| +------------+
18013 : | | | | <- Ptr
18014 : |------------| |------------|
18015 :
18016 :
18017 : Quadruples Produced
18018 :
18019 : q BecomesOp Designator _ Expression
18020 :
18021 : OR
18022 :
18023 : Entry Exit
18024 : ===== ====
18025 :
18026 : Ptr ->
18027 : +------------+
18028 : | True |False|
18029 : |------------|
18030 : | Designator |
18031 : |------------| +------------+
18032 : | | | | <- Ptr
18033 : |------------| |------------|
18034 :
18035 :
18036 : Quadruples Produced
18037 :
18038 : q BecomesOp Designator _ TRUE
18039 : q+1 GotoOp q+3
18040 : q+2 BecomesOp Designator _ FALSE
18041 :
18042 : */
18043 :
18044 128200 : extern "C" void M2Quads_BuildAssignment (unsigned int becomesTokNo)
18045 : {
18046 128200 : unsigned int des;
18047 128200 : unsigned int exp;
18048 128200 : unsigned int destok;
18049 128200 : unsigned int exptok;
18050 128200 : unsigned int combinedtok;
18051 :
18052 128200 : des = static_cast<unsigned int> (M2Quads_OperandT (2));
18053 128200 : if (IsReadOnly (des))
18054 : {
18055 36 : destok = static_cast<unsigned int> (M2Quads_OperandTok (2));
18056 36 : exptok = static_cast<unsigned int> (M2Quads_OperandTok (1));
18057 36 : exp = static_cast<unsigned int> (M2Quads_OperandT (1));
18058 36 : if (DebugTokPos)
18059 : {
18060 : M2MetaError_MetaErrorT1 (destok, (const char *) "destok {%1Ead}", 14, des);
18061 : M2MetaError_MetaErrorT1 (exptok, (const char *) "exptok {%1Ead}", 14, exp);
18062 : }
18063 36 : combinedtok = M2LexBuf_MakeVirtualTok (becomesTokNo, destok, exptok);
18064 36 : if (DebugTokPos)
18065 : {
18066 : M2MetaError_MetaErrorT1 (combinedtok, (const char *) "combined {%1Ead}", 16, des);
18067 : }
18068 36 : if (IsBoolean (1))
18069 : {
18070 0 : M2MetaError_MetaErrorT1 (combinedtok, (const char *) "cannot assign expression to a constant designator {%1Ead}", 57, des);
18071 : }
18072 : else
18073 : {
18074 36 : exp = static_cast<unsigned int> (M2Quads_OperandT (1));
18075 36 : M2MetaError_MetaErrorT2 (combinedtok, (const char *) "cannot assign a constant designator {%1Ead} with an expression {%2Ead}", 70, des, exp);
18076 : }
18077 36 : M2Quads_PopN (2); /* Remove both parameters. */
18078 : }
18079 128164 : else if (SymbolTable_IsError (des))
18080 : {
18081 : /* avoid dangling else. */
18082 25 : M2Quads_PopN (2); /* Remove both parameters. */
18083 : }
18084 : else
18085 : {
18086 : /* avoid dangling else. */
18087 128139 : doBuildAssignment (becomesTokNo, true, true);
18088 : }
18089 128194 : }
18090 :
18091 :
18092 : /*
18093 : BuildAssignConstant - used to create constant in the CONST declaration.
18094 : The stack is expected to contain:
18095 :
18096 : Either
18097 :
18098 : Entry Exit
18099 : ===== ====
18100 :
18101 : Ptr ->
18102 : +------------+
18103 : | Expression |
18104 : |------------|
18105 : | Designator |
18106 : |------------| +------------+
18107 : | | | | <- Ptr
18108 : |------------| |------------|
18109 :
18110 :
18111 : Quadruples Produced
18112 :
18113 : q BecomesOp Designator _ Expression
18114 :
18115 : OR
18116 :
18117 : Entry Exit
18118 : ===== ====
18119 :
18120 : Ptr ->
18121 : +------------+
18122 : | True |False|
18123 : |------------|
18124 : | Designator |
18125 : |------------| +------------+
18126 : | | | | <- Ptr
18127 : |------------| |------------|
18128 :
18129 :
18130 : Quadruples Produced
18131 :
18132 : q BecomesOp Designator _ TRUE
18133 : q+1 GotoOp q+3
18134 : q+2 BecomesOp Designator _ FALSE
18135 : */
18136 :
18137 300431 : extern "C" void M2Quads_BuildAssignConstant (unsigned int equalsTokNo)
18138 : {
18139 300431 : doBuildAssignment (equalsTokNo, true, true);
18140 300431 : }
18141 :
18142 :
18143 : /*
18144 : BuildAlignment - builds an assignment to an alignment constant.
18145 :
18146 : The Stack is expected to contain:
18147 :
18148 :
18149 : Entry Exit
18150 : ===== ====
18151 :
18152 : Ptr ->
18153 : +---------------+
18154 : | Expression |
18155 : |---------------|
18156 : | bytealignment |
18157 : |---------------| empty
18158 : */
18159 :
18160 72 : extern "C" void M2Quads_BuildAlignment (unsigned int tokno)
18161 : {
18162 72 : NameKey_Name name;
18163 72 : unsigned int expr;
18164 72 : unsigned int align;
18165 :
18166 72 : M2Quads_PopT (&expr);
18167 72 : M2Quads_PopT (&name);
18168 72 : if (name != (NameKey_MakeKey ((const char *) "bytealignment", 13)))
18169 : {
18170 0 : M2MetaError_MetaError1 ((const char *) "expecting bytealignment identifier, rather than {%1Ea}", 54, SymbolTable_MakeError (tokno, name));
18171 : }
18172 72 : FifoQueue_GetConstFromFifoQueue (&align);
18173 72 : M2Quads_PushT (align);
18174 72 : M2Quads_PushT (expr);
18175 72 : M2Quads_BuildAssignConstant (tokno);
18176 72 : }
18177 :
18178 :
18179 : /*
18180 : BuildBitLength - builds an assignment to a bit length constant.
18181 :
18182 : The Stack is expected to contain:
18183 :
18184 :
18185 : Entry Exit
18186 : ===== ====
18187 :
18188 : Ptr ->
18189 : +------------+
18190 : | Expression |
18191 : |------------| empty
18192 : */
18193 :
18194 0 : extern "C" void M2Quads_BuildBitLength (unsigned int tokno)
18195 : {
18196 0 : unsigned int expr;
18197 0 : unsigned int length;
18198 :
18199 0 : M2Quads_PopT (&expr);
18200 0 : FifoQueue_GetConstFromFifoQueue (&length);
18201 0 : M2Quads_PushT (length);
18202 0 : M2Quads_PushT (expr);
18203 0 : M2Quads_BuildAssignConstant (tokno);
18204 0 : }
18205 :
18206 :
18207 : /*
18208 : BuildPragmaField - builds an assignment to an alignment constant.
18209 :
18210 : The Stack is expected to contain:
18211 :
18212 :
18213 : Entry Exit
18214 : ===== ====
18215 :
18216 : Ptr ->
18217 : +------------+
18218 : | Expression |
18219 : |------------| empty
18220 : */
18221 :
18222 12 : extern "C" void M2Quads_BuildPragmaField (void)
18223 : {
18224 12 : unsigned int expr;
18225 12 : unsigned int const_;
18226 12 : NameKey_Name name;
18227 :
18228 12 : M2Quads_PopT (&expr);
18229 12 : M2Quads_PopT (&name);
18230 12 : if ((name != (NameKey_MakeKey ((const char *) "unused", 6))) && (name != (NameKey_MakeKey ((const char *) "bytealignment", 13))))
18231 : {
18232 0 : M2MetaError_MetaError0 ((const char *) "only allowed to use the attribute {%Ekbytealignment} in the default record field alignment pragma", 97);
18233 : }
18234 12 : if (expr != SymbolTable_NulSym)
18235 : {
18236 12 : FifoQueue_GetConstFromFifoQueue (&const_);
18237 12 : M2Quads_PushT (const_);
18238 12 : M2Quads_PushT (expr);
18239 12 : M2Quads_BuildAssignConstant (M2LexBuf_GetTokenNo ());
18240 : }
18241 12 : }
18242 :
18243 :
18244 : /*
18245 : BuildDefaultFieldAlignment - builds an assignment to an alignment constant.
18246 :
18247 : The Stack is expected to contain:
18248 :
18249 :
18250 : Entry Exit
18251 : ===== ====
18252 :
18253 : Ptr ->
18254 : +------------+
18255 : | Expression |
18256 : |------------| empty
18257 : */
18258 :
18259 36 : extern "C" void M2Quads_BuildDefaultFieldAlignment (void)
18260 : {
18261 36 : unsigned int expr;
18262 36 : unsigned int align;
18263 36 : NameKey_Name name;
18264 :
18265 36 : M2Quads_PopT (&expr);
18266 36 : M2Quads_PopT (&name);
18267 36 : if (name != (NameKey_MakeKey ((const char *) "bytealignment", 13)))
18268 : {
18269 0 : M2MetaError_MetaError0 ((const char *) "{%E}only allowed to use the attribute {%kbytealignment} in the default record field alignment pragma", 100);
18270 : }
18271 36 : FifoQueue_GetConstFromFifoQueue (&align);
18272 36 : M2Quads_PushT (align);
18273 36 : M2Quads_PushT (expr);
18274 36 : M2Quads_BuildAssignConstant (M2LexBuf_GetTokenNo ());
18275 36 : }
18276 :
18277 :
18278 : /*
18279 : BuildRepeat - Builds the repeat statement from the quad stack.
18280 : The Stack is expected to contain:
18281 :
18282 :
18283 : Entry Exit
18284 : ===== ====
18285 :
18286 :
18287 : Empty
18288 : <- Ptr
18289 : +------------+
18290 : | RepeatQuad |
18291 : |------------|
18292 :
18293 : */
18294 :
18295 1422 : extern "C" void M2Quads_BuildRepeat (void)
18296 : {
18297 1422 : M2Quads_PushT (NextQuad);
18298 1422 : }
18299 :
18300 :
18301 : /*
18302 : BuildUntil - Builds the until part of the repeat statement
18303 : from the quad stack.
18304 : The Stack is expected to contain:
18305 :
18306 :
18307 : Entry Exit
18308 : ===== ====
18309 :
18310 : Ptr ->
18311 : +------------+
18312 : | t | f |
18313 : |------------|
18314 : | RepeatQuad | Empty
18315 : |------------|
18316 : */
18317 :
18318 1422 : extern "C" void M2Quads_BuildUntil (void)
18319 : {
18320 1422 : unsigned int t;
18321 1422 : unsigned int f;
18322 1422 : unsigned int Repeat;
18323 :
18324 1422 : CheckBooleanId ();
18325 1422 : PopBool (&t, &f);
18326 1422 : M2Quads_PopT (&Repeat);
18327 1422 : BackPatch (f, Repeat); /* If False then keep on repeating */
18328 1422 : BackPatch (t, NextQuad); /* If True then exit repeat */
18329 1422 : }
18330 :
18331 :
18332 : /*
18333 : BuildWhile - Builds the While part of the While statement
18334 : from the quad stack.
18335 : The Stack is expected to contain:
18336 :
18337 :
18338 : Entry Exit
18339 : ===== ====
18340 :
18341 : <- Ptr
18342 : |------------|
18343 : Empty | WhileQuad |
18344 : |------------|
18345 : */
18346 :
18347 7870 : extern "C" void M2Quads_BuildWhile (void)
18348 : {
18349 7870 : M2Quads_PushT (NextQuad);
18350 7870 : }
18351 :
18352 :
18353 : /*
18354 : BuildDoWhile - Builds the Do part of the while statement
18355 : from the quad stack.
18356 : The Stack is expected to contain:
18357 :
18358 :
18359 : Entry Exit
18360 : ===== ====
18361 :
18362 : Ptr ->
18363 : +------------+ +------------+
18364 : | t | f | | 0 | f |
18365 : |------------| |------------|
18366 : | WhileQuad | | WhileQuad |
18367 : |------------| |------------|
18368 :
18369 : Quadruples
18370 :
18371 : BackPatch t exit to the NextQuad
18372 : */
18373 :
18374 7870 : extern "C" void M2Quads_BuildDoWhile (void)
18375 : {
18376 7870 : unsigned int t;
18377 7870 : unsigned int f;
18378 :
18379 7870 : CheckBooleanId ();
18380 7870 : PopBool (&t, &f);
18381 7870 : BackPatch (t, NextQuad);
18382 7870 : PushBool (0, f);
18383 7870 : }
18384 :
18385 :
18386 : /*
18387 : BuildEndWhile - Builds the end part of the while statement
18388 : from the quad stack.
18389 : The Stack is expected to contain:
18390 :
18391 :
18392 : Entry Exit
18393 : ===== ====
18394 :
18395 : Ptr ->
18396 : +------------+
18397 : | t | f |
18398 : |------------|
18399 : | WhileQuad | Empty
18400 : |------------|
18401 :
18402 : Quadruples
18403 :
18404 : q GotoOp WhileQuad
18405 : False exit is backpatched with q+1
18406 : */
18407 :
18408 7870 : extern "C" void M2Quads_BuildEndWhile (int reltokpos)
18409 : {
18410 7870 : unsigned int tok;
18411 7870 : unsigned int While;
18412 7870 : unsigned int t;
18413 7870 : unsigned int f;
18414 :
18415 7870 : tok = M2LexBuf_GetTokenNo ();
18416 7870 : tok = ((int ) (tok))+reltokpos;
18417 7870 : PopBool (&t, &f);
18418 7870 : M2Debug_Assert (t == 0);
18419 7870 : M2Quads_PopT (&While);
18420 7870 : GenQuadO (tok, M2Quads_GotoOp, SymbolTable_NulSym, SymbolTable_NulSym, While, false);
18421 7870 : BackPatch (f, NextQuad);
18422 7870 : }
18423 :
18424 :
18425 : /*
18426 : BuildLoop - Builds the Loop part of the Loop statement
18427 : from the quad stack.
18428 : The Stack is expected to contain:
18429 :
18430 :
18431 : Entry Exit
18432 : ===== ====
18433 :
18434 : <- Ptr
18435 : Empty +------------+
18436 : | LoopQuad |
18437 : |------------|
18438 : */
18439 :
18440 516 : extern "C" void M2Quads_BuildLoop (void)
18441 : {
18442 516 : M2Quads_PushT (NextQuad);
18443 516 : PushExit (0); /* Seperate Exit Stack for loop end */
18444 516 : }
18445 :
18446 :
18447 : /*
18448 : BuildExit - Builds the Exit part of the Loop statement.
18449 : */
18450 :
18451 94 : extern "C" void M2Quads_BuildExit (void)
18452 : {
18453 94 : if (M2StackWord_IsEmptyWord (ExitStack))
18454 : {
18455 0 : M2MetaError_MetaError0 ((const char *) "{%EkEXIT} is only allowed in a {%kLOOP} statement", 49);
18456 : }
18457 : else
18458 : {
18459 94 : GenQuad (M2Quads_GotoOp, SymbolTable_NulSym, SymbolTable_NulSym, 0);
18460 94 : PushExit (Merge (PopExit (), NextQuad-1));
18461 : }
18462 94 : }
18463 :
18464 :
18465 : /*
18466 : BuildEndLoop - Builds the End part of the Loop statement
18467 : from the quad stack.
18468 : The Stack is expected to contain:
18469 :
18470 :
18471 : Entry Exit
18472 : ===== ====
18473 :
18474 : Ptr ->
18475 : +------------+
18476 : | LoopQuad | Empty
18477 : |------------|
18478 :
18479 : Quadruples
18480 :
18481 : Goto _ _ LoopQuad
18482 : */
18483 :
18484 516 : extern "C" void M2Quads_BuildEndLoop (void)
18485 : {
18486 516 : unsigned int Loop;
18487 :
18488 516 : M2Quads_PopT (&Loop);
18489 516 : GenQuad (M2Quads_GotoOp, SymbolTable_NulSym, SymbolTable_NulSym, Loop);
18490 516 : BackPatch (PopExit (), NextQuad);
18491 516 : }
18492 :
18493 :
18494 : /*
18495 : BuildThenIf - Builds the Then part of the If statement
18496 : from the quad stack.
18497 : The Stack is expected to contain:
18498 :
18499 :
18500 : Entry Exit
18501 : ===== ====
18502 :
18503 : Ptr -> <- Ptr
18504 : +------------+ +------------+
18505 : | t | f | | 0 | f |
18506 : |------------| |------------|
18507 :
18508 : Quadruples
18509 :
18510 : The true exit is BackPatched to point to
18511 : the NextQuad.
18512 : */
18513 :
18514 45164 : extern "C" void M2Quads_BuildThenIf (void)
18515 : {
18516 45164 : unsigned int t;
18517 45164 : unsigned int f;
18518 :
18519 45164 : CheckBooleanId ();
18520 45164 : PopBool (&t, &f);
18521 45164 : BackPatch (t, NextQuad);
18522 45164 : PushBool (0, f);
18523 45164 : }
18524 :
18525 :
18526 : /*
18527 : BuildElse - Builds the Else part of the If statement
18528 : from the quad stack.
18529 : The Stack is expected to contain:
18530 :
18531 :
18532 : Entry Exit
18533 : ===== ====
18534 :
18535 : Ptr ->
18536 : +------------+ +------------+
18537 : | t | f | | t+q | 0 |
18538 : |------------| |------------|
18539 :
18540 : Quadruples
18541 :
18542 : q GotoOp _ _ 0
18543 : q+1 <- BackPatched from f
18544 : */
18545 :
18546 15236 : extern "C" void M2Quads_BuildElse (void)
18547 : {
18548 15236 : unsigned int t;
18549 15236 : unsigned int f;
18550 :
18551 15236 : GenQuad (M2Quads_GotoOp, SymbolTable_NulSym, SymbolTable_NulSym, 0);
18552 15236 : PopBool (&t, &f);
18553 15236 : BackPatch (f, NextQuad);
18554 15236 : PushBool (Merge (t, NextQuad-1), 0); /* NextQuad-1 = Goto Quad */
18555 15236 : }
18556 :
18557 :
18558 : /*
18559 : BuildEndIf - Builds the End part of the If statement
18560 : from the quad stack.
18561 : The Stack is expected to contain:
18562 :
18563 :
18564 : Entry Exit
18565 : ===== ====
18566 :
18567 : Ptr ->
18568 : +------------+
18569 : | t | f | Empty
18570 : |------------|
18571 :
18572 : Quadruples
18573 :
18574 : Both t and f are backpatched to point to the NextQuad
18575 : */
18576 :
18577 41884 : extern "C" void M2Quads_BuildEndIf (void)
18578 : {
18579 41884 : unsigned int t;
18580 41884 : unsigned int f;
18581 :
18582 41884 : PopBool (&t, &f);
18583 41884 : BackPatch (t, NextQuad);
18584 41884 : BackPatch (f, NextQuad);
18585 41884 : }
18586 :
18587 :
18588 : /*
18589 : BuildElsif1 - Builds the Elsif part of the If statement
18590 : from the quad stack.
18591 : The Stack is expected to contain:
18592 :
18593 :
18594 : Entry Exit
18595 : ===== ====
18596 :
18597 : Ptr ->
18598 : +------------+ +------------+
18599 : | t | f | | t+q | 0 |
18600 : |------------| |------------|
18601 :
18602 : Quadruples
18603 :
18604 : q GotoOp _ _ 0
18605 : q+1 <- BackPatched from f
18606 : */
18607 :
18608 3280 : extern "C" void M2Quads_BuildElsif1 (void)
18609 : {
18610 3280 : unsigned int t;
18611 3280 : unsigned int f;
18612 :
18613 3280 : GenQuad (M2Quads_GotoOp, SymbolTable_NulSym, SymbolTable_NulSym, 0);
18614 3280 : PopBool (&t, &f);
18615 3280 : BackPatch (f, NextQuad);
18616 3280 : PushBool (Merge (t, NextQuad-1), 0); /* NextQuad-1 = Goto Quad */
18617 3280 : }
18618 :
18619 :
18620 : /*
18621 : BuildElsif2 - Builds the Elsif until part of the If statement
18622 : from the quad stack.
18623 : The Stack is expected to contain:
18624 :
18625 :
18626 : Entry Exit
18627 : ===== ====
18628 :
18629 : Ptr ->
18630 : +--------------+
18631 : | 0 | f1 | <- Ptr
18632 : |--------------| +---------------+
18633 : | t2 | f2 | | t2 | f1+f2 |
18634 : |--------------| |---------------|
18635 : */
18636 :
18637 3280 : extern "C" void M2Quads_BuildElsif2 (void)
18638 : {
18639 3280 : unsigned int t1;
18640 3280 : unsigned int f1;
18641 3280 : unsigned int t2;
18642 3280 : unsigned int f2;
18643 :
18644 3280 : PopBool (&t1, &f1);
18645 3280 : M2Debug_Assert (t1 == 0);
18646 3280 : PopBool (&t2, &f2);
18647 3280 : PushBool (t2, Merge (f1, f2));
18648 3280 : }
18649 :
18650 :
18651 : /*
18652 : BuildForToByDo - Builds the For To By Do part of the For statement
18653 : from the quad stack.
18654 : The Stack is expected to contain:
18655 :
18656 :
18657 : Entry Exit
18658 : ===== ====
18659 :
18660 : <- Ptr
18661 : +----------------+
18662 : Ptr -> | RangeId |
18663 : +----------------+ |----------------|
18664 : | BySym | ByType | | ForQuad |
18665 : |----------------| |----------------|
18666 : | e2 | | LastValue |
18667 : |----------------| |----------------|
18668 : | e1 | | BySym | ByType |
18669 : |----------------| |----------------|
18670 : | Ident | | IdentSym |
18671 : |----------------| |----------------|
18672 :
18673 :
18674 : x := e1 ;
18675 : Note that LASTVALUE is calculated during M2GenGCC
18676 : after all the types have been resolved.
18677 : LASTVALUE := ((e2-e1) DIV BySym) * BySym + e1
18678 : IF BySym<0
18679 : THEN
18680 : IF e1<e2
18681 : THEN
18682 : goto exit
18683 : END
18684 : ELSE
18685 : IF e1>e2
18686 : THEN
18687 : goto exit
18688 : END
18689 : END ;
18690 : LOOP
18691 : body
18692 : IF x=LASTVALUE
18693 : THEN
18694 : goto exit
18695 : END ;
18696 : INC(x, BySym)
18697 : END
18698 :
18699 : Quadruples:
18700 :
18701 : q BecomesOp IdentSym _ e1
18702 : q+ LastForIteratorOp LastValue := ((e1-e2) DIV by) * by + e1
18703 : q+1 if >= by 0 q+..2
18704 : q+2 GotoOp q+3
18705 : q+3 If >= e1 e2 q+5
18706 : q+4 GotoOp exit
18707 : q+5 ..
18708 : q+..1 Goto q+..5
18709 : q+..2 If >= e2 e1 q+..4
18710 : q+..3 GotoOp exit
18711 : q+..4 ..
18712 :
18713 : The For Loop is regarded:
18714 :
18715 : For ident := e1 To e2 By by Do
18716 :
18717 : End
18718 : */
18719 :
18720 2610 : extern "C" void M2Quads_BuildForToByDo (void)
18721 : {
18722 2610 : M2Quads_LineNote l1;
18723 2610 : M2Quads_LineNote l2;
18724 2610 : NameKey_Name e1;
18725 2610 : NameKey_Name e2;
18726 2610 : NameKey_Name Id;
18727 2610 : unsigned int e1tok;
18728 2610 : unsigned int e2tok;
18729 2610 : unsigned int idtok;
18730 2610 : unsigned int bytok;
18731 2610 : unsigned int LastIterator;
18732 2610 : unsigned int exit1;
18733 2610 : unsigned int IdSym;
18734 2610 : unsigned int BySym;
18735 2610 : unsigned int ByType;
18736 2610 : unsigned int ForLoop;
18737 2610 : unsigned int RangeId;
18738 2610 : unsigned int t;
18739 2610 : unsigned int f;
18740 2610 : unsigned int etype;
18741 2610 : unsigned int t1;
18742 :
18743 2610 : l2 = PopLineNo ();
18744 2610 : l1 = PopLineNo ();
18745 2610 : UseLineNote (l1);
18746 2610 : PushFor (0);
18747 2610 : M2Quads_PopTFtok (&BySym, &ByType, &bytok);
18748 2610 : M2Quads_PopTtok (&e2, &e2tok);
18749 2610 : M2Quads_PopTtok (&e1, &e1tok);
18750 2610 : M2Quads_PopTtok (&Id, &idtok);
18751 2610 : IdSym = SymbolTable_RequestSym (idtok, Id);
18752 2610 : RangeId = M2Range_InitForLoopBeginRangeCheck (IdSym, idtok, e1, e1tok, e2, e2tok, BySym, bytok);
18753 2610 : BuildRange (RangeId);
18754 2610 : M2Quads_PushTtok (IdSym, idtok);
18755 2610 : M2Quads_PushTtok (e1, e1tok);
18756 2610 : BuildAssignmentWithoutBounds (idtok, true, true);
18757 2610 : UseLineNote (l2);
18758 3492 : LastIterator = SymbolTable_MakeTemporary (e2tok, AreConstant (((SymbolTable_IsConst (e1)) && (SymbolTable_IsConst (e2))) && (SymbolTable_IsConst (BySym))));
18759 2610 : SymbolTable_PutVar (LastIterator, SymbolTable_GetSType (IdSym));
18760 2610 : etype = M2Base_MixTypes (SymbolTable_GetSType (e1), SymbolTable_GetSType (e2), e2tok);
18761 2610 : e1 = doConvert (etype, e1);
18762 2610 : e2 = doConvert (etype, e2);
18763 2604 : ForLoopLastIterator (LastIterator, e1, e2, BySym, e1tok, e2tok, bytok);
18764 : /* q+2 GotoOp q+3 */
18765 2604 : M2Quads_PushTFtok (BySym, ByType, bytok); /* BuildRelOp 1st parameter. */
18766 2604 : M2Quads_PushT (M2Reserved_GreaterEqualTok); /* 2nd parameter. */
18767 : /* 3rd parameter. */
18768 2604 : PushZero (bytok, ByType);
18769 2604 : M2Quads_BuildRelOp (e2tok); /* Choose final expression position. */
18770 2604 : PopBool (&t, &f); /* Choose final expression position. */
18771 2604 : BackPatch (f, NextQuad);
18772 : /* q+4 GotoOp Exit */
18773 2604 : M2Quads_PushTFtok (e1, SymbolTable_GetSType (e1), e1tok); /* BuildRelOp 1st parameter */
18774 2604 : M2Quads_PushT (M2Reserved_GreaterEqualTok); /* 2nd parameter */
18775 2604 : M2Quads_PushTFtok (e2, SymbolTable_GetSType (e2), e2tok); /* 3rd parameter */
18776 2604 : M2Quads_BuildRelOp (e2tok); /* Choose final expression position. */
18777 2604 : PopBool (&t1, &exit1); /* Choose final expression position. */
18778 2604 : BackPatch (t1, NextQuad);
18779 2604 : PushFor (Merge (PopFor (), exit1)); /* Merge exit1. */
18780 2604 : GenQuad (M2Quads_GotoOp, SymbolTable_NulSym, SymbolTable_NulSym, 0); /* Merge exit1. */
18781 2604 : ForLoop = NextQuad-1;
18782 : /* ELSE. */
18783 2604 : BackPatch (t, NextQuad);
18784 2604 : M2Quads_PushTFtok (e2, SymbolTable_GetSType (e2), e2tok); /* BuildRelOp 1st parameter */
18785 2604 : M2Quads_PushT (M2Reserved_GreaterEqualTok); /* 2nd parameter */
18786 2604 : M2Quads_PushTFtok (e1, SymbolTable_GetSType (e1), e1tok); /* 3rd parameter */
18787 2604 : M2Quads_BuildRelOp (e2tok); /* 3rd parameter */
18788 2604 : PopBool (&t1, &exit1);
18789 2604 : BackPatch (t1, NextQuad);
18790 2604 : PushFor (Merge (PopFor (), exit1)); /* Merge exit1. */
18791 2604 : BackPatch (ForLoop, NextQuad); /* Fixes the start of the for loop. */
18792 2604 : ForLoop = NextQuad;
18793 : /* And set up the stack. */
18794 2604 : M2Quads_PushTFtok (IdSym, SymbolTable_GetSym (IdSym), idtok);
18795 2604 : M2Quads_PushTFtok (BySym, ByType, bytok);
18796 2604 : M2Quads_PushTFtok (LastIterator, SymbolTable_GetSType (LastIterator), e2tok);
18797 2604 : M2Quads_PushT (ForLoop);
18798 2604 : M2Quads_PushT (RangeId);
18799 2604 : }
18800 :
18801 :
18802 : /*
18803 : BuildPseudoBy - Builds the Non existant part of the By
18804 : clause of the For statement
18805 : from the quad stack.
18806 : The Stack is expected to contain:
18807 :
18808 :
18809 : Entry Exit
18810 : ===== ====
18811 :
18812 : <- Ptr
18813 : +------------+
18814 : Ptr -> | BySym | t |
18815 : +------------+ |------------|
18816 : | e | t | | e | t |
18817 : |------------| |------------|
18818 : */
18819 :
18820 2244 : extern "C" void M2Quads_BuildPseudoBy (void)
18821 : {
18822 2244 : unsigned int expr;
18823 2244 : unsigned int type;
18824 2244 : unsigned int dotok;
18825 :
18826 : /* As there is no BY token this position is the DO at the end of the last expression. */
18827 2244 : M2Quads_PopTFtok (&expr, &type, &dotok);
18828 2244 : M2Quads_PushTFtok (expr, type, dotok);
18829 2244 : if (type == SymbolTable_NulSym)
18830 : {} /* empty. */
18831 : /* Use type. */
18832 2024 : else if ((SymbolTable_IsEnumeration (SymbolTable_SkipType (type))) || ((SymbolTable_SkipType (type)) == M2Base_Char))
18833 : {
18834 : /* avoid dangling else. */
18835 : }
18836 1804 : else if (M2Base_IsOrdinalType (SymbolTable_SkipType (type)))
18837 : {
18838 : /* avoid dangling else. */
18839 1804 : type = M2Base_ZType;
18840 : }
18841 2244 : PushOne (dotok, type, (const char *) "the implied {%kFOR} loop increment will cause an overflow {%1ad}", 64);
18842 2244 : }
18843 :
18844 :
18845 : /*
18846 : BuildEndFor - Builds the End part of the For statement
18847 : from the quad stack.
18848 : The Stack is expected to contain:
18849 :
18850 :
18851 : Entry Exit
18852 : ===== ====
18853 :
18854 : Ptr ->
18855 : +----------------+
18856 : | RangeId |
18857 : |----------------|
18858 : | ForQuad |
18859 : |----------------|
18860 : | LastValue |
18861 : |----------------|
18862 : | BySym | ByType |
18863 : |----------------|
18864 : | IdSym | Empty
18865 : |----------------|
18866 : */
18867 :
18868 2604 : extern "C" void M2Quads_BuildEndFor (unsigned int endpostok)
18869 : {
18870 2604 : unsigned int t;
18871 2604 : unsigned int f;
18872 2604 : unsigned int tsym;
18873 2604 : unsigned int RangeId;
18874 2604 : unsigned int IncQuad;
18875 2604 : unsigned int ForQuad;
18876 2604 : unsigned int LastSym;
18877 2604 : unsigned int ByType;
18878 2604 : unsigned int BySym;
18879 2604 : unsigned int bytok;
18880 2604 : unsigned int IdSym;
18881 2604 : unsigned int idtok;
18882 :
18883 2604 : M2Quads_PopT (&RangeId);
18884 2604 : M2Quads_PopT (&ForQuad);
18885 2604 : M2Quads_PopT (&LastSym);
18886 2604 : M2Quads_PopTFtok (&BySym, &ByType, &bytok);
18887 2604 : M2Quads_PopTtok (&IdSym, &idtok);
18888 : /* IF IdSym=LastSym THEN exit END */
18889 2604 : M2Quads_PushTF (IdSym, SymbolTable_GetSType (IdSym));
18890 2604 : M2Quads_PushT (M2Reserved_EqualTok);
18891 2604 : M2Quads_PushTF (LastSym, SymbolTable_GetSType (LastSym));
18892 2604 : M2Quads_BuildRelOp (endpostok);
18893 2604 : PopBool (&t, &f);
18894 2604 : BackPatch (t, NextQuad);
18895 2604 : GenQuad (M2Quads_GotoOp, SymbolTable_NulSym, SymbolTable_NulSym, 0);
18896 2604 : PushFor (Merge (PopFor (), NextQuad-1));
18897 2604 : BackPatch (f, NextQuad);
18898 2604 : if ((SymbolTable_GetMode (IdSym)) == SymbolTable_LeftValue)
18899 : {
18900 : /* index variable is a LeftValue, therefore we must dereference it */
18901 0 : tsym = SymbolTable_MakeTemporary (idtok, SymbolTable_RightValue);
18902 0 : SymbolTable_PutVar (tsym, SymbolTable_GetSType (IdSym));
18903 0 : CheckPointerThroughNil (idtok, IdSym);
18904 0 : doIndrX (endpostok, tsym, IdSym);
18905 0 : BuildRange (M2Range_InitForLoopEndRangeCheck (tsym, BySym)); /* --fixme-- pass endpostok. */
18906 0 : IncQuad = NextQuad;
18907 : /* we have explicitly checked using the above and also
18908 : this addition can legitimately overflow if a cardinal type
18909 : is counting down. The above test will generate a more
18910 : precise error message, so we suppress overflow detection
18911 : here. */
18912 0 : GenQuadOTypetok (bytok, M2Quads_AddOp, tsym, tsym, BySym, false, false, idtok, idtok, bytok);
18913 0 : CheckPointerThroughNil (idtok, IdSym);
18914 0 : GenQuadOtok (idtok, M2Quads_XIndrOp, IdSym, SymbolTable_GetSType (IdSym), tsym, false, idtok, idtok, idtok);
18915 : }
18916 : else
18917 : {
18918 2604 : BuildRange (M2Range_InitForLoopEndRangeCheck (IdSym, BySym));
18919 2604 : IncQuad = NextQuad;
18920 : /* we have explicitly checked using the above and also
18921 : this addition can legitimately overflow if a cardinal type
18922 : is counting down. The above test will generate a more
18923 : precise error message, so we suppress overflow detection
18924 : here.
18925 :
18926 : This quadruple suppresses the generic binary op type
18927 : check (performed in M2GenGCC.mod) as there
18928 : will be a more informative/exhaustive check performed by the
18929 : InitForLoopBeginRangeCheck setup in BuildForToByDo and
18930 : performed by M2Range.mod. */
18931 2604 : GenQuadOTypetok (idtok, M2Quads_AddOp, IdSym, IdSym, BySym, false, false, idtok, idtok, bytok);
18932 : }
18933 2604 : GenQuadO (endpostok, M2Quads_GotoOp, SymbolTable_NulSym, SymbolTable_NulSym, ForQuad, false);
18934 2604 : BackPatch (PopFor (), NextQuad);
18935 2604 : AddForInfo (ForQuad, NextQuad-1, IncQuad, IdSym, idtok);
18936 2604 : M2Range_PutRangeForIncrement (RangeId, IncQuad);
18937 2604 : }
18938 :
18939 :
18940 : /*
18941 : BuildCaseStart - starts the case statement.
18942 : It initializes a backpatch list on the compile
18943 : time stack, the list is used to contain all
18944 : case break points. The list is later backpatched
18945 : and contains all positions of the case statement
18946 : which jump to the end of the case statement.
18947 : The stack also contains room for a boolean
18948 : expression, this is needed to allow , operator
18949 : in the CaseField alternatives.
18950 :
18951 : The Stack is expected to contain:
18952 :
18953 :
18954 : Entry Exit
18955 : ===== ====
18956 :
18957 : <- Ptr
18958 : +------------+
18959 : | 0 | 0 |
18960 : |------------|
18961 : | 0 | 0 |
18962 : +-------------+ |------------|
18963 : | Expr | | | Expr | |
18964 : |-------------| |------------|
18965 : */
18966 :
18967 1002 : extern "C" void M2Quads_BuildCaseStart (void)
18968 : {
18969 1002 : BuildRange (M2Range_InitCaseBounds (M2CaseList_PushCase (SymbolTable_NulSym, SymbolTable_NulSym, M2Quads_OperandT (1))));
18970 1002 : PushBool (0, 0); /* BackPatch list initialized */
18971 1002 : PushBool (0, 0); /* Room for a boolean expression */
18972 1002 : }
18973 :
18974 :
18975 : /*
18976 : BuildCaseStartStatementSequence - starts the statement sequence
18977 : inside a case clause.
18978 : BackPatches the true exit to the
18979 : NextQuad.
18980 : The Stack:
18981 :
18982 : Entry Exit
18983 :
18984 : Ptr -> <- Ptr
18985 : +-----------+ +------------+
18986 : | t | f | | 0 | f |
18987 : |-----------| |------------|
18988 : */
18989 :
18990 3892 : extern "C" void M2Quads_BuildCaseStartStatementSequence (void)
18991 : {
18992 3892 : unsigned int t;
18993 3892 : unsigned int f;
18994 :
18995 3892 : PopBool (&t, &f);
18996 3892 : BackPatch (t, NextQuad);
18997 3892 : PushBool (0, f);
18998 3892 : }
18999 :
19000 :
19001 : /*
19002 : BuildCaseEndStatementSequence - ends the statement sequence
19003 : inside a case clause.
19004 : BackPatches the false exit f1 to the
19005 : NextQuad.
19006 : Asserts that t1 and f2 is 0
19007 : Pushes t2+q and 0
19008 :
19009 : Quadruples:
19010 :
19011 : q GotoOp _ _ 0
19012 :
19013 : The Stack:
19014 :
19015 : Entry Exit
19016 :
19017 : Ptr -> <- Ptr
19018 : +-----------+ +------------+
19019 : | t1 | f1 | | 0 | 0 |
19020 : |-----------| |------------|
19021 : | t2 | f2 | | t2+q | 0 |
19022 : |-----------| |------------|
19023 : */
19024 :
19025 3892 : extern "C" void M2Quads_BuildCaseEndStatementSequence (void)
19026 : {
19027 3892 : unsigned int t1;
19028 3892 : unsigned int f1;
19029 3892 : unsigned int t2;
19030 3892 : unsigned int f2;
19031 :
19032 3892 : GenQuad (M2Quads_GotoOp, SymbolTable_NulSym, SymbolTable_NulSym, 0);
19033 3892 : PopBool (&t1, &f1);
19034 3892 : PopBool (&t2, &f2); /* t2 contains the break list for the case */
19035 3892 : BackPatch (f1, NextQuad); /* f1 no longer needed */
19036 3892 : M2Debug_Assert (t1 == 0); /* f1 no longer needed */
19037 3892 : M2Debug_Assert (f2 == 0);
19038 3892 : PushBool (Merge (t2, NextQuad-1), 0); /* NextQuad-1 = Goto Quad */
19039 3892 : PushBool (0, 0); /* Room for boolean expression */
19040 3892 : }
19041 :
19042 :
19043 : /*
19044 : BuildCaseRange - builds the range testing quaruples for
19045 : a case clause.
19046 :
19047 : IF (e1>=ce1) AND (e1<=ce2)
19048 : THEN
19049 :
19050 : ELS..
19051 :
19052 : The Stack:
19053 :
19054 : Entry Exit
19055 :
19056 : Ptr ->
19057 : +-----------+
19058 : | ce2 | <- Ptr
19059 : |-----------| +-----------+
19060 : | ce1 | | t | f |
19061 : |-----------| |-----------|
19062 : | t1 | f1 | | t1 | f1 |
19063 : |-----------| |-----------|
19064 : | t2 | f2 | | t2 | f2 |
19065 : |-----------| |-----------|
19066 : | e1 | | e1 |
19067 : |-----------| |-----------|
19068 : */
19069 :
19070 172 : extern "C" void M2Quads_BuildCaseRange (void)
19071 : {
19072 172 : unsigned int ce1;
19073 172 : unsigned int ce2;
19074 172 : unsigned int combinedtok;
19075 172 : unsigned int ce1tok;
19076 172 : unsigned int ce2tok;
19077 172 : unsigned int e1tok;
19078 172 : unsigned int e1;
19079 172 : unsigned int t2;
19080 172 : unsigned int f2;
19081 172 : unsigned int t1;
19082 172 : unsigned int f1;
19083 :
19084 172 : M2Quads_PopTtok (&ce2, &ce2tok);
19085 172 : M2Quads_PopTtok (&ce1, &ce1tok);
19086 172 : combinedtok = M2LexBuf_MakeVirtualTok (ce2tok, ce2tok, ce1tok);
19087 172 : M2CaseList_AddRange (ce1, ce2, combinedtok);
19088 172 : PopBool (&t1, &f1);
19089 172 : PopBool (&t2, &f2);
19090 172 : M2Quads_PopTtok (&e1, &e1tok);
19091 172 : M2Quads_PushTtok (e1, e1tok); /* leave e1 on bottom of stack when exit procedure */
19092 172 : PushBool (t2, f2); /* leave e1 on bottom of stack when exit procedure */
19093 172 : PushBool (t1, f1); /* also leave t1 and f1 on the bottom of the stack */
19094 172 : M2Quads_PushTtok (e1, e1tok); /* also leave t1 and f1 on the bottom of the stack */
19095 172 : M2Quads_PushT (M2Reserved_GreaterEqualTok);
19096 172 : M2Quads_PushTtok (ce1, ce1tok);
19097 172 : M2Quads_BuildRelOp (combinedtok);
19098 172 : M2Quads_PushT (M2Reserved_AndTok);
19099 172 : M2Quads_RecordOp ();
19100 172 : M2Quads_PushTtok (e1, e1tok);
19101 172 : M2Quads_PushT (M2Reserved_LessEqualTok);
19102 172 : M2Quads_PushTtok (ce2, ce2tok);
19103 172 : M2Quads_BuildRelOp (combinedtok);
19104 172 : M2Quads_BuildBinaryOp ();
19105 172 : }
19106 :
19107 :
19108 : /*
19109 : BuildCaseEquality - builds the range testing quadruples for
19110 : a case clause.
19111 :
19112 : IF e1=ce1
19113 : THEN
19114 :
19115 : ELS..
19116 :
19117 : The Stack:
19118 :
19119 : Entry Exit
19120 :
19121 : Ptr ->
19122 : +-----------+ +-----------+
19123 : | ce1 | | t | f |
19124 : |-----------| |-----------|
19125 : | t1 | f1 | | t1 | f1 |
19126 : |-----------| |-----------|
19127 : | t2 | f2 | | t2 | f2 |
19128 : |-----------| |-----------|
19129 : | e1 | | e1 |
19130 : |-----------| |-----------|
19131 : */
19132 :
19133 3770 : extern "C" void M2Quads_BuildCaseEquality (void)
19134 : {
19135 3770 : unsigned int ce1tok;
19136 3770 : unsigned int e1tok;
19137 3770 : unsigned int ce1;
19138 3770 : unsigned int e1;
19139 3770 : unsigned int t2;
19140 3770 : unsigned int f2;
19141 3770 : unsigned int t1;
19142 3770 : unsigned int f1;
19143 :
19144 3770 : M2Quads_PopTtok (&ce1, &ce1tok);
19145 3770 : M2CaseList_AddRange (ce1, SymbolTable_NulSym, ce1tok);
19146 3770 : PopBool (&t1, &f1);
19147 3770 : PopBool (&t2, &f2);
19148 3770 : M2Quads_PopTtok (&e1, &e1tok);
19149 3770 : M2Quads_PushTtok (e1, e1tok); /* leave e1 on bottom of stack when exit procedure */
19150 3770 : PushBool (t2, f2); /* also leave t2 and f2 on the bottom of the stack */
19151 3770 : PushBool (t1, f1); /* also leave t2 and f2 on the bottom of the stack */
19152 3770 : M2Quads_PushTtok (e1, e1tok);
19153 3770 : M2Quads_PushT (M2Reserved_EqualTok);
19154 3770 : M2Quads_PushTtok (ce1, ce1tok);
19155 3770 : M2Quads_BuildRelOp (ce1tok);
19156 3770 : }
19157 :
19158 :
19159 : /*
19160 : BuildCaseList - merges two case tests into one
19161 :
19162 : The Stack:
19163 :
19164 : Entry Exit
19165 :
19166 : Ptr ->
19167 : +-----------+
19168 : | t2 | f2 |
19169 : |-----------| +-------------+
19170 : | t1 | f1 | | t1+t2| f1+f2|
19171 : |-----------| |-------------|
19172 : */
19173 :
19174 3942 : extern "C" void M2Quads_BuildCaseList (void)
19175 : {
19176 3942 : unsigned int t2;
19177 3942 : unsigned int f2;
19178 3942 : unsigned int t1;
19179 3942 : unsigned int f1;
19180 :
19181 3942 : PopBool (&t2, &f2);
19182 3942 : PopBool (&t1, &f1);
19183 3942 : PushBool (Merge (t1, t2), Merge (f1, f2));
19184 3942 : }
19185 :
19186 :
19187 : /*
19188 : BuildCaseOr - builds the , in the case clause.
19189 :
19190 : The Stack:
19191 :
19192 : Entry Exit
19193 :
19194 : Ptr -> <- Ptr
19195 : +-----------+ +------------+
19196 : | t | f | | t | 0 |
19197 : |-----------| |------------|
19198 : */
19199 :
19200 50 : extern "C" void M2Quads_BuildCaseOr (void)
19201 : {
19202 50 : unsigned int t;
19203 50 : unsigned int f;
19204 :
19205 50 : PopBool (&t, &f);
19206 50 : BackPatch (f, NextQuad);
19207 50 : PushBool (t, 0);
19208 50 : }
19209 :
19210 :
19211 : /*
19212 : BuildCaseElse - builds the else of case clause.
19213 :
19214 : The Stack:
19215 :
19216 : Entry Exit
19217 :
19218 : Ptr -> <- Ptr
19219 : +-----------+ +------------+
19220 : | t | f | | t | 0 |
19221 : |-----------| |------------|
19222 : */
19223 :
19224 1002 : extern "C" void M2Quads_BuildCaseElse (void)
19225 : {
19226 1002 : unsigned int t;
19227 1002 : unsigned int f;
19228 :
19229 1002 : PopBool (&t, &f);
19230 1002 : BackPatch (f, NextQuad);
19231 1002 : PushBool (t, 0);
19232 1002 : }
19233 :
19234 :
19235 : /*
19236 : BuildCaseEnd - builds the end of case clause.
19237 :
19238 : The Stack:
19239 :
19240 : Entry Exit
19241 :
19242 : Ptr ->
19243 : +-----------+
19244 : | t1 | f1 |
19245 : |-----------|
19246 : | t2 | f2 |
19247 : |-----------|
19248 : | e1 |
19249 : |-----------| Empty
19250 : */
19251 :
19252 1002 : extern "C" void M2Quads_BuildCaseEnd (void)
19253 : {
19254 1002 : unsigned int e1;
19255 1002 : unsigned int t;
19256 1002 : unsigned int f;
19257 :
19258 1002 : PopBool (&t, &f);
19259 1002 : BackPatch (f, NextQuad);
19260 1002 : BackPatch (t, NextQuad);
19261 1002 : PopBool (&t, &f);
19262 1002 : BackPatch (f, NextQuad);
19263 1002 : BackPatch (t, NextQuad);
19264 1002 : M2Quads_PopT (&e1);
19265 1002 : M2CaseList_PopCase ();
19266 1002 : }
19267 :
19268 :
19269 : /*
19270 : BuildCaseCheck - builds the case checking code to ensure that
19271 : the program does not need an else clause at runtime.
19272 : The stack is unaltered.
19273 : */
19274 :
19275 494 : extern "C" void M2Quads_BuildCaseCheck (void)
19276 : {
19277 494 : BuildError (M2Range_InitNoElseRangeCheck ());
19278 494 : }
19279 :
19280 :
19281 : /*
19282 : BuildNulParam - Builds a nul parameter on the stack.
19283 : The Stack:
19284 :
19285 : Entry Exit
19286 :
19287 : <- Ptr
19288 : Empty +------------+
19289 : | 0 |
19290 : |------------|
19291 : */
19292 :
19293 18618 : extern "C" void M2Quads_BuildNulParam (void)
19294 : {
19295 18618 : M2Quads_PushT (static_cast<unsigned int> (0));
19296 18618 : }
19297 :
19298 :
19299 : /*
19300 : BuildProcedureCall - builds a procedure call.
19301 : Although this procedure does not directly
19302 : destroy the procedure parameters, it calls
19303 : routine which will manipulate the stack and
19304 : so the entry and exit states of the stack are shown.
19305 :
19306 : The Stack:
19307 :
19308 :
19309 : Entry Exit
19310 :
19311 : Ptr ->
19312 : +----------------+
19313 : | NoOfParam |
19314 : |----------------|
19315 : | Param 1 |
19316 : |----------------|
19317 : | Param 2 |
19318 : |----------------|
19319 : . .
19320 : . .
19321 : . .
19322 : |----------------|
19323 : | Param # |
19324 : |----------------|
19325 : | ProcSym | Type | Empty
19326 : |----------------|
19327 : */
19328 :
19329 180257 : extern "C" void M2Quads_BuildProcedureCall (unsigned int tokno)
19330 : {
19331 180257 : unsigned int NoOfParam;
19332 180257 : unsigned int ProcSym;
19333 :
19334 180257 : M2Quads_PopT (&NoOfParam);
19335 180257 : ProcSym = static_cast<unsigned int> (M2Quads_OperandT (NoOfParam+1));
19336 180257 : M2Quads_PushT (NoOfParam); /* Compile time stack restored to entry state */
19337 180257 : if ((M2Base_IsPseudoBaseProcedure (ProcSym)) || (M2System_IsPseudoSystemProcedure (ProcSym))) /* Compile time stack restored to entry state */
19338 : {
19339 21535 : M2Quads_DisplayStack ();
19340 21535 : ManipulatePseudoCallParameters ();
19341 21535 : M2Quads_DisplayStack ();
19342 21535 : BuildPseudoProcedureCall (tokno);
19343 21535 : M2Quads_DisplayStack ();
19344 : }
19345 158722 : else if (SymbolTable_IsUnknown (ProcSym))
19346 : {
19347 : /* avoid dangling else. */
19348 : /* Spellcheck. */
19349 30 : M2MetaError_MetaError1 ((const char *) "{%1Ua} is not recognised as a procedure {%1&s}", 46, ProcSym);
19350 30 : M2Quads_PopN (NoOfParam+2);
19351 30 : SymbolTable_UnknownReported (ProcSym);
19352 : }
19353 : else
19354 : {
19355 : /* avoid dangling else. */
19356 158692 : M2Quads_DisplayStack ();
19357 158692 : BuildRealProcedureCall (tokno);
19358 158686 : M2Quads_DisplayStack ();
19359 : }
19360 180251 : }
19361 :
19362 :
19363 : /*
19364 : CheckBuildFunction - checks to see whether ProcSym is a function
19365 : and if so it adds a TempSym value which will
19366 : hold the return value once the function finishes.
19367 : This procedure also generates an error message
19368 : if the user is calling a function and ignoring
19369 : the return result. The additional TempSym
19370 : is not created if ProcSym is a procedure
19371 : and the stack is unaltered.
19372 :
19373 : The Stack:
19374 :
19375 :
19376 : Entry Exit
19377 :
19378 : Ptr ->
19379 :
19380 : +----------------+
19381 : | ProcSym | Type |
19382 : +----------------+ |----------------|
19383 : | ProcSym | Type | | TempSym | Type |
19384 : |----------------| |----------------|
19385 : */
19386 :
19387 107723 : extern "C" bool M2Quads_CheckBuildFunction (void)
19388 : {
19389 107723 : unsigned int tokpos;
19390 107723 : unsigned int TempSym;
19391 107723 : unsigned int ProcSym;
19392 107723 : unsigned int Type;
19393 :
19394 107723 : M2Quads_PopTFtok (&ProcSym, &Type, &tokpos);
19395 107723 : if ((SymbolTable_IsVar (ProcSym)) && (SymbolTable_IsProcType (Type)))
19396 : {
19397 : /* avoid dangling else. */
19398 684 : if ((SymbolTable_GetSType (Type)) != SymbolTable_NulSym)
19399 : {
19400 0 : TempSym = SymbolTable_MakeTemporary (tokpos, SymbolTable_RightValue);
19401 0 : SymbolTable_PutVar (TempSym, SymbolTable_GetSType (Type));
19402 0 : M2Quads_PushTFtok (TempSym, SymbolTable_GetSType (Type), tokpos);
19403 0 : M2Quads_PushTFtok (ProcSym, Type, tokpos);
19404 0 : if (! (SymbolTable_IsReturnOptionalAny (Type)))
19405 : {
19406 0 : M2MetaError_MetaErrorT1 (tokpos, (const char *) "function {%1Ea} is called but its return value is ignored", 57, ProcSym);
19407 : }
19408 0 : return true;
19409 : }
19410 : }
19411 107039 : else if ((SymbolTable_IsProcedure (ProcSym)) && (Type != SymbolTable_NulSym))
19412 : {
19413 : /* avoid dangling else. */
19414 0 : TempSym = SymbolTable_MakeTemporary (tokpos, SymbolTable_RightValue);
19415 0 : SymbolTable_PutVar (TempSym, Type);
19416 0 : M2Quads_PushTFtok (TempSym, Type, tokpos);
19417 0 : M2Quads_PushTFtok (ProcSym, Type, tokpos);
19418 0 : if (! (SymbolTable_IsReturnOptionalAny (ProcSym)))
19419 : {
19420 0 : M2MetaError_MetaErrorT1 (tokpos, (const char *) "function {%1Ea} is called but its return value is ignored", 57, ProcSym);
19421 : }
19422 0 : return true;
19423 : }
19424 107723 : M2Quads_PushTFtok (ProcSym, Type, tokpos);
19425 107723 : return false;
19426 : /* static analysis guarentees a RETURN statement will be used before here. */
19427 : __builtin_unreachable ();
19428 : }
19429 :
19430 :
19431 : /*
19432 : BuildFunctionCall - builds a function call.
19433 : The Stack:
19434 :
19435 :
19436 : Entry Exit
19437 :
19438 : Ptr ->
19439 : +----------------+
19440 : | NoOfParam |
19441 : |----------------|
19442 : | Param 1 |
19443 : |----------------|
19444 : | Param 2 |
19445 : |----------------|
19446 : . .
19447 : . .
19448 : . .
19449 : |----------------|
19450 : | Param # | <- Ptr
19451 : |----------------| +------------+
19452 : | ProcSym | Type | | ReturnVar |
19453 : |----------------| |------------|
19454 : */
19455 :
19456 107008 : extern "C" void M2Quads_BuildFunctionCall (bool ConstExpr)
19457 : {
19458 107008 : unsigned int paramtok;
19459 107008 : unsigned int combinedtok;
19460 107008 : unsigned int functok;
19461 107008 : unsigned int NoOfParam;
19462 107008 : unsigned int ProcSym;
19463 :
19464 107008 : M2Quads_PopT (&NoOfParam);
19465 107008 : functok = OperandTtok (NoOfParam+1);
19466 107008 : ProcSym = static_cast<unsigned int> (M2Quads_OperandT (NoOfParam+1));
19467 107008 : ProcSym = PCSymBuild_SkipConst (ProcSym);
19468 107008 : M2Quads_PushT (NoOfParam);
19469 : /* Compile time stack restored to entry state. */
19470 107008 : if (SymbolTable_IsUnknown (ProcSym))
19471 : {
19472 : /* Spellcheck. */
19473 6 : paramtok = OperandTtok (1);
19474 6 : combinedtok = M2LexBuf_MakeVirtual2Tok (functok, paramtok);
19475 6 : M2MetaError_MetaErrorT1 (functok, (const char *) "procedure function {%1Ea} is undefined {%1&s}", 45, ProcSym);
19476 6 : SymbolTable_UnknownReported (ProcSym);
19477 6 : M2Quads_PopN (NoOfParam+2);
19478 : /* Fake return value to continue compiling. */
19479 6 : M2Quads_PushT (SymbolTable_MakeConstLit (combinedtok, NameKey_MakeKey ((const char *) "0", 1), SymbolTable_NulSym));
19480 : }
19481 107002 : else if (SymbolTable_IsAModula2Type (ProcSym))
19482 : {
19483 : /* avoid dangling else. */
19484 2544 : ManipulatePseudoCallParameters ();
19485 2544 : BuildTypeCoercion (ConstExpr);
19486 : }
19487 104458 : else if ((M2System_IsPseudoSystemFunction (ProcSym)) || (M2Base_IsPseudoBaseFunction (ProcSym)))
19488 : {
19489 : /* avoid dangling else. */
19490 42796 : ManipulatePseudoCallParameters ();
19491 42796 : BuildPseudoFunctionCall (ConstExpr);
19492 : }
19493 : else
19494 : {
19495 : /* avoid dangling else. */
19496 61662 : BuildRealFunctionCall (functok, ConstExpr);
19497 : }
19498 106981 : }
19499 :
19500 :
19501 : /*
19502 : BuildConstFunctionCall - builds a function call and checks that this function can be
19503 : called inside a ConstExpression.
19504 :
19505 : The Stack:
19506 :
19507 :
19508 : Entry Exit
19509 :
19510 : Ptr ->
19511 : +----------------+
19512 : | NoOfParam |
19513 : |----------------|
19514 : | Param 1 |
19515 : |----------------|
19516 : | Param 2 |
19517 : |----------------|
19518 : . .
19519 : . .
19520 : . .
19521 : |----------------|
19522 : | Param # | <- Ptr
19523 : |----------------| +------------+
19524 : | ProcSym | Type | | ReturnVar |
19525 : |----------------| |------------|
19526 :
19527 : */
19528 :
19529 7394 : extern "C" void M2Quads_BuildConstFunctionCall (void)
19530 : {
19531 7394 : unsigned int functok;
19532 7394 : unsigned int combinedtok;
19533 7394 : unsigned int paramtok;
19534 7394 : unsigned int ConstExpression;
19535 7394 : unsigned int NoOfParam;
19536 7394 : unsigned int ProcSym;
19537 :
19538 7394 : M2Quads_DisplayStack ();
19539 7394 : M2Quads_PopT (&NoOfParam);
19540 7394 : ProcSym = static_cast<unsigned int> (M2Quads_OperandT (NoOfParam+1));
19541 7394 : functok = OperandTtok (NoOfParam+1);
19542 7394 : if (M2Options_CompilerDebugging)
19543 : {
19544 0 : M2Printf_printf2 ((const char *) "procsym = %d token = %d\\n", 26, (const unsigned char *) &ProcSym, (sizeof (ProcSym)-1), (const unsigned char *) &functok, (sizeof (functok)-1));
19545 : }
19546 : /* ErrorStringAt (InitString ('constant function'), functok). */
19547 7394 : M2Quads_PushT (NoOfParam);
19548 7394 : if ((ProcSym != M2Base_Convert) && (((M2Base_IsPseudoBaseFunction (ProcSym)) || (M2System_IsPseudoSystemFunctionConstExpression (ProcSym))) || ((SymbolTable_IsProcedure (ProcSym)) && (SymbolTable_IsProcedureBuiltin (ProcSym)))))
19549 : {
19550 7262 : M2Quads_BuildFunctionCall (true);
19551 : }
19552 : else
19553 : {
19554 132 : if (SymbolTable_IsAModula2Type (ProcSym))
19555 : {
19556 : /* Type conversion. */
19557 132 : if (NoOfParam == 1)
19558 : {
19559 132 : ConstExpression = static_cast<unsigned int> (M2Quads_OperandT (NoOfParam+1));
19560 132 : paramtok = OperandTtok (NoOfParam+1);
19561 132 : M2Quads_PopN (NoOfParam+2);
19562 : /* Build macro: CONVERT( ProcSym, ConstExpression ). */
19563 132 : M2Quads_PushTFtok (M2Base_Convert, static_cast<unsigned int> (SymbolTable_NulSym), functok);
19564 132 : M2Quads_PushTtok (ProcSym, functok);
19565 132 : M2Quads_PushTtok (ConstExpression, paramtok);
19566 132 : M2Quads_PushT (static_cast<unsigned int> (2)); /* Two parameters. */
19567 132 : BuildConvertFunction (M2Base_Convert, true); /* Two parameters. */
19568 : }
19569 : else
19570 : {
19571 0 : M2MetaError_MetaErrorT0 (functok, (const char *) "{%E}a constant type conversion can only have one argument", 57);
19572 : }
19573 : }
19574 : else
19575 : {
19576 : /* Error issue message and fake return stack. */
19577 0 : if (M2Options_Iso)
19578 : {
19579 0 : M2MetaError_MetaErrorT0 (functok, (const char *) "the only functions permissible in a constant expression are: {%kCAP}, {%kCHR}, {%kCMPLX}, {%kFLOAT}, {%kHIGH}, {%kIM}, {%kLENGTH}, {%kMAX}, {%kMIN}, {%kODD}, {%kORD}, {%kRE}, {%kSIZE}, {%kTSIZE}, {%kTBITSIZE}, {%kTRUNC}, {%kVAL} and gcc builtins", 245);
19580 : }
19581 : else
19582 : {
19583 0 : M2MetaError_MetaErrorT0 (functok, (const char *) "the only functions permissible in a constant expression are: {%kCAP}, {%kCHR}, {%kFLOAT}, {%kHIGH}, {%kMAX}, {%kMIN}, {%kODD}, {%kORD}, {%kSIZE}, {%kTSIZE}, {%kTRUNC}, {%kTBITSIZE}, {%kVAL} and gcc builtins", 206);
19584 : }
19585 0 : if (NoOfParam > 0)
19586 : {
19587 0 : paramtok = OperandTtok (NoOfParam+1);
19588 0 : combinedtok = M2LexBuf_MakeVirtualTok (functok, functok, paramtok);
19589 : }
19590 : else
19591 : {
19592 0 : combinedtok = functok;
19593 : }
19594 0 : M2Quads_PopN (NoOfParam+2);
19595 0 : M2Quads_PushT (SymbolTable_MakeConstLit (combinedtok, NameKey_MakeKey ((const char *) "0", 1), SymbolTable_NulSym)); /* Fake return value to continue compiling. */
19596 : }
19597 : }
19598 7394 : }
19599 :
19600 :
19601 : /*
19602 : BuildBooleanVariable - tests to see whether top of stack is a boolean
19603 : conditional and if so it converts it into a boolean
19604 : variable.
19605 : */
19606 :
19607 361118 : extern "C" void M2Quads_BuildBooleanVariable (void)
19608 : {
19609 361118 : if (IsBoolean (1))
19610 : {
19611 7262 : ConvertBooleanToVariable (OperandTtok (1), 1);
19612 : }
19613 361118 : }
19614 :
19615 :
19616 : /*
19617 : BuildModuleStart - starts current module scope.
19618 : */
19619 :
19620 84893 : extern "C" void M2Quads_BuildModuleStart (unsigned int tok)
19621 : {
19622 84893 : GenQuadO (tok, M2Quads_ModuleScopeOp, tok, (unsigned int ) (NameKey_makekey (DynamicStrings_string (M2LexBuf_GetFileName ()))), SymbolTable_GetCurrentModule (), false);
19623 84893 : }
19624 :
19625 :
19626 : /*
19627 : BuildProcedureStart - Builds start of the procedure. Generates a
19628 : quadruple which indicated the start of
19629 : this procedure declarations scope.
19630 : The Stack is expected to contain:
19631 :
19632 :
19633 : Entry Exit
19634 : ===== ====
19635 :
19636 : Ptr -> <- Ptr
19637 : +------------+ +-----------+
19638 : | ProcSym | | ProcSym |
19639 : |------------| |-----------|
19640 : | Name | | Name |
19641 : |------------| |-----------|
19642 :
19643 :
19644 : Quadruples:
19645 :
19646 : q ProcedureScopeOp Line# Scope ProcSym
19647 : */
19648 :
19649 81810 : extern "C" void M2Quads_BuildProcedureStart (void)
19650 : {
19651 81810 : unsigned int ProcSym;
19652 :
19653 81810 : M2Quads_PopT (&ProcSym);
19654 81810 : M2Debug_Assert (SymbolTable_IsProcedure (ProcSym));
19655 81810 : SymbolTable_PutProcedureScopeQuad (ProcSym, NextQuad);
19656 81810 : GenQuad (M2Quads_ProcedureScopeOp, M2LexBuf_GetPreviousTokenLineNo (), SymbolTable_GetScope (ProcSym), ProcSym);
19657 81810 : M2Quads_PushT (ProcSym);
19658 81810 : }
19659 :
19660 :
19661 : /*
19662 : BuildProcedureBegin - determines the start of the BEGIN END block of
19663 : the procedure.
19664 : The Stack is expected to contain:
19665 :
19666 :
19667 : Entry Exit
19668 : ===== ====
19669 :
19670 : Ptr -> <- Ptr
19671 : +------------+ +-----------+
19672 : | ProcSym | | ProcSym |
19673 : |------------| |-----------|
19674 : | Name | | Name |
19675 : |------------| |-----------|
19676 :
19677 :
19678 : Quadruples:
19679 :
19680 : q NewLocalVarOp TokenNo(BEGIN) _ ProcSym
19681 : */
19682 :
19683 81798 : extern "C" void M2Quads_BuildProcedureBegin (void)
19684 : {
19685 81798 : unsigned int ProcSym;
19686 :
19687 81798 : M2Quads_PopT (&ProcSym);
19688 81798 : M2Debug_Assert (SymbolTable_IsProcedure (ProcSym));
19689 81798 : SymbolTable_PutProcedureStartQuad (ProcSym, NextQuad);
19690 81798 : SymbolTable_PutProcedureBegin (ProcSym, M2LexBuf_GetTokenNo ());
19691 81798 : GenQuad (M2Quads_NewLocalVarOp, M2LexBuf_GetTokenNo (), SymbolTable_GetScope (ProcSym), ProcSym);
19692 81798 : CurrentProc = ProcSym;
19693 81798 : M2StackWord_PushWord (ReturnStack, static_cast<unsigned int> (0));
19694 81798 : M2Quads_PushT (ProcSym);
19695 81798 : CheckVariablesAt (ProcSym);
19696 81798 : CheckNeedPriorityBegin (M2LexBuf_GetTokenNo (), ProcSym, SymbolTable_GetCurrentModule ());
19697 81798 : M2StackWord_PushWord (TryStack, NextQuad);
19698 81798 : M2StackWord_PushWord (CatchStack, static_cast<unsigned int> (0));
19699 81798 : if (SymbolTable_HasExceptionBlock (ProcSym))
19700 : {
19701 168 : GenQuad (M2Quads_TryOp, SymbolTable_NulSym, SymbolTable_NulSym, 0);
19702 : }
19703 81798 : }
19704 :
19705 :
19706 : /*
19707 : BuildProcedureEnd - Builds end of the procedure. Destroys space for
19708 : the local variables.
19709 : The Stack is expected to contain:
19710 :
19711 :
19712 : Entry Exit
19713 : ===== ====
19714 :
19715 : Ptr -> <- Ptr
19716 : +------------+ +-----------+
19717 : | ProcSym | | ProcSym |
19718 : |------------| |-----------|
19719 : | Name | | Name |
19720 : |------------| |-----------|
19721 :
19722 :
19723 : Quadruples:
19724 :
19725 : q KillLocalVarOp TokenNo(END) _ ProcSym
19726 : */
19727 :
19728 81768 : extern "C" void M2Quads_BuildProcedureEnd (void)
19729 : {
19730 81768 : unsigned int tok;
19731 81768 : unsigned int ProcSym;
19732 :
19733 81768 : M2Quads_PopTtok (&ProcSym, &tok);
19734 81768 : if (SymbolTable_HasExceptionBlock (ProcSym))
19735 : {
19736 168 : BuildRTExceptLeave (tok, true);
19737 168 : GenQuad (M2Quads_CatchEndOp, SymbolTable_NulSym, SymbolTable_NulSym, SymbolTable_NulSym);
19738 : }
19739 81768 : if ((SymbolTable_GetSType (ProcSym)) != SymbolTable_NulSym)
19740 : {
19741 19166 : BuildError (M2Range_InitNoReturnRangeCheck ());
19742 : }
19743 81768 : BackPatch (M2StackWord_PopWord (ReturnStack), NextQuad);
19744 81768 : CheckNeedPriorityEnd (tok, ProcSym, SymbolTable_GetCurrentModule ());
19745 81768 : CurrentProc = SymbolTable_NulSym;
19746 81768 : SymbolTable_PutProcedureEnd (ProcSym, (M2LexBuf_GetTokenNo ())-1); /* --fixme-- */
19747 81768 : GenQuad (M2Quads_KillLocalVarOp, (M2LexBuf_GetTokenNo ())-1, SymbolTable_NulSym, ProcSym); /* --fixme-- */
19748 81768 : SymbolTable_PutProcedureEndQuad (ProcSym, NextQuad);
19749 81768 : GenQuad (M2Quads_ReturnOp, SymbolTable_NulSym, SymbolTable_NulSym, ProcSym);
19750 81768 : CheckFunctionReturn (ProcSym);
19751 81768 : CheckVariablesInBlock (ProcSym);
19752 : /* Call PutProcedureEndQuad so that any runtime procedure will be
19753 : seen as defined even if it not seen during pass 2 (which will also
19754 : call PutProcedureEndQuad). */
19755 81768 : SymbolTable_PutProcedureParametersDefined (ProcSym, SymbolTable_ProperProcedure);
19756 81768 : SymbolTable_PutProcedureDefined (ProcSym, SymbolTable_ProperProcedure);
19757 81768 : M2StackWord_RemoveTop (CatchStack);
19758 81768 : M2StackWord_RemoveTop (TryStack);
19759 81768 : M2Quads_PushT (ProcSym);
19760 81768 : }
19761 :
19762 :
19763 : /*
19764 : BuildReturn - Builds the Return part of the procedure.
19765 : tokreturn is the location of the RETURN keyword.
19766 : The Stack is expected to contain:
19767 :
19768 :
19769 : Entry Exit
19770 : ===== ====
19771 :
19772 : Ptr ->
19773 : +------------+
19774 : | e1 | Empty
19775 : |------------|
19776 : */
19777 :
19778 28975 : extern "C" void M2Quads_BuildReturn (unsigned int tokreturn)
19779 : {
19780 28975 : unsigned int tokcombined;
19781 28975 : unsigned int tokexpr;
19782 28975 : unsigned int e1;
19783 28975 : unsigned int t1;
19784 28975 : unsigned int t;
19785 28975 : unsigned int f;
19786 28975 : unsigned int Des;
19787 :
19788 28975 : if (IsBoolean (1))
19789 : {
19790 1816 : PopBooltok (&t, &f, &tokexpr);
19791 : /* Des will be a boolean type */
19792 1816 : Des = SymbolTable_MakeTemporary (tokexpr, SymbolTable_RightValue);
19793 1816 : SymbolTable_PutVar (Des, M2Base_Boolean);
19794 1816 : M2Quads_PushTFtok (Des, M2Base_Boolean, tokexpr);
19795 1816 : PushBooltok (t, f, tokexpr);
19796 1816 : BuildAssignmentWithoutBounds (tokreturn, false, true);
19797 1816 : M2Quads_PushTFtok (Des, M2Base_Boolean, tokexpr);
19798 : }
19799 28975 : M2Quads_PopTFtok (&e1, &t1, &tokexpr);
19800 28975 : tokcombined = M2LexBuf_MakeVirtualTok (tokreturn, tokreturn, tokexpr);
19801 28975 : if (e1 != SymbolTable_NulSym)
19802 : {
19803 : /* avoid gcc warning by using compound statement even if not strictly necessary. */
19804 : /* Check we are in a procedure scope and that the procedure has a return type. */
19805 28123 : if (CurrentProc == SymbolTable_NulSym)
19806 : {
19807 6 : M2MetaError_MetaErrorT0 (tokcombined, (const char *) "{%1E} attempting to return a value when not in a procedure scope", 64);
19808 : }
19809 28117 : else if ((SymbolTable_GetSType (CurrentProc)) == SymbolTable_NulSym)
19810 : {
19811 : /* avoid dangling else. */
19812 6 : M2MetaError_MetaErrorT1 (tokcombined, (const char *) "attempting to return a value from procedure {%1Ea} which does not have a return type", 84, CurrentProc);
19813 : }
19814 : else
19815 : {
19816 : /* avoid dangling else. */
19817 28111 : BuildReturnLower (tokcombined, tokexpr, e1, t1);
19818 : }
19819 : }
19820 28975 : GenQuadO (tokcombined, M2Quads_GotoOp, SymbolTable_NulSym, SymbolTable_NulSym, M2StackWord_PopWord (ReturnStack), false);
19821 28975 : M2StackWord_PushWord (ReturnStack, NextQuad-1);
19822 28975 : }
19823 :
19824 :
19825 : /*
19826 : BuildModulePriority - assigns the current module with a priority
19827 : from the top of stack.
19828 :
19829 : Entry Exit
19830 : ===== ====
19831 :
19832 :
19833 : Ptr -> Empty
19834 : +------------+
19835 : | Priority |
19836 : |------------|
19837 : */
19838 :
19839 38 : extern "C" void M2Quads_BuildModulePriority (void)
19840 : {
19841 38 : unsigned int Priority;
19842 :
19843 38 : M2Quads_PopT (&Priority);
19844 38 : SymbolTable_PutPriority (SymbolTable_GetCurrentModule (), Priority);
19845 38 : }
19846 :
19847 :
19848 : /*
19849 : StartBuildWith - performs the with statement.
19850 : The Stack:
19851 :
19852 : Entry Exit
19853 :
19854 : +------------+
19855 : | Sym | Type | Empty
19856 : |------------|
19857 : */
19858 :
19859 6196 : extern "C" void M2Quads_StartBuildWith (unsigned int withTok)
19860 : {
19861 6196 : unsigned int tok;
19862 6196 : unsigned int Sym;
19863 6196 : unsigned int Type;
19864 6196 : unsigned int Ref;
19865 :
19866 6196 : DebugLocation (static_cast<unsigned int> (M2Reserved_withtok), (const char *) "with", 4);
19867 6196 : BuildStmtNoteTok (withTok);
19868 6196 : M2Quads_DisplayStack ();
19869 6196 : M2Quads_PopTFtok (&Sym, &Type, &tok);
19870 6196 : DebugLocation (tok, (const char *) "expression", 10);
19871 6196 : Type = SymbolTable_SkipType (Type);
19872 6196 : if (Type == SymbolTable_NulSym)
19873 : {
19874 6 : M2MetaError_MetaErrorT1 (tok, (const char *) "{%1Aa} {%1d} has a no type, the {%kWITH} statement requires a variable or parameter of a {%kRECORD} type", 104, Sym);
19875 : }
19876 : else
19877 : {
19878 6190 : Ref = SymbolTable_MakeTemporary (tok, SymbolTable_LeftValue);
19879 6190 : SymbolTable_PutVar (Ref, Type);
19880 6190 : if ((SymbolTable_GetMode (Sym)) == SymbolTable_LeftValue)
19881 : {
19882 : /* Copy LeftValue. */
19883 5878 : GenQuadO (tok, M2Quads_BecomesOp, Ref, SymbolTable_NulSym, Sym, true);
19884 : }
19885 : else
19886 : {
19887 : /* Calculate the address of Sym. */
19888 312 : GenQuadO (tok, M2Quads_AddrOp, Ref, SymbolTable_NulSym, Sym, true);
19889 : }
19890 6190 : PushWith (Sym, Type, Ref, tok);
19891 6190 : DebugLocation (tok, (const char *) "with ref", 8);
19892 6190 : if (! (SymbolTable_IsRecord (Type)))
19893 : {
19894 0 : M2MetaError_MetaErrorT1 (tok, (const char *) "the {%kWITH} statement requires that {%1Ea} {%1d} be of a {%kRECORD} {%1tsa:type rather than {%1tsa}}", 101, Sym);
19895 : }
19896 6190 : SymbolTable_StartScope (Type);
19897 : }
19898 6190 : M2StackSpell_Push (Type);
19899 6190 : M2Quads_DisplayStack ();
19900 6190 : }
19901 :
19902 :
19903 : /*
19904 : EndBuildWith - terminates the innermost with scope.
19905 : */
19906 :
19907 6190 : extern "C" void M2Quads_EndBuildWith (void)
19908 : {
19909 6190 : M2Quads_DisplayStack ();
19910 6190 : SymbolTable_EndScope ();
19911 6190 : PopWith ();
19912 6190 : M2StackSpell_Pop ();
19913 6190 : M2Quads_DisplayStack ();
19914 6190 : }
19915 :
19916 :
19917 : /*
19918 : CheckWithReference - performs the with statement.
19919 : The Stack:
19920 :
19921 : Entry Exit
19922 :
19923 : +------------+ +------------+
19924 : | Sym | Type | | Sym | Type |
19925 : |------------| |------------|
19926 : */
19927 :
19928 697255 : extern "C" void M2Quads_CheckWithReference (void)
19929 : {
19930 697255 : M2Quads_WithFrame f;
19931 697255 : unsigned int tokpos;
19932 697255 : unsigned int i;
19933 697255 : unsigned int n;
19934 697255 : unsigned int rw;
19935 697255 : unsigned int Sym;
19936 697255 : unsigned int Type;
19937 :
19938 697255 : n = M2StackAddress_NoOfItemsInStackAddress (WithStack);
19939 697255 : if ((n > 0) && ! SuppressWith)
19940 : {
19941 107206 : PopTFrwtok (&Sym, &Type, &rw, &tokpos);
19942 107206 : M2Debug_Assert (tokpos != M2LexBuf_UnknownTokenNo);
19943 107206 : if (SymbolTable_IsUnknown (Sym))
19944 : {
19945 6 : M2MetaError_MetaErrorT1 (tokpos, (const char *) "{%1ad} is unknown {%1&s}", 24, Sym);
19946 6 : SymbolTable_UnknownReported (Sym);
19947 : }
19948 : else
19949 : {
19950 : /* Inner WITH always has precedence. */
19951 : i = 1; /* top of stack */
19952 : /* WriteString('Checking for a with') ; */
19953 227600 : while (i <= n)
19954 : {
19955 120400 : f = static_cast<M2Quads_WithFrame> (M2StackAddress_PeepAddress (WithStack, i));
19956 120400 : if ((SymbolTable_IsRecordField (Sym)) && ((SymbolTable_GetRecord (SymbolTable_GetParent (Sym))) == f->RecordType))
19957 : {
19958 31040 : if (SymbolTable_IsUnused (Sym))
19959 : {
19960 0 : M2MetaError_MetaError1 ((const char *) "record field {%1Dad} was declared as unused by a pragma", 55, Sym);
19961 : }
19962 : /* Fake a RecordSym.op */
19963 31040 : PushTFrwtok (f->RecordRef, f->RecordType, f->rw, f->RecordTokPos);
19964 31040 : M2Quads_PushTFtok (Sym, Type, tokpos);
19965 31040 : BuildAccessWithField ();
19966 31040 : PopTFrw (&Sym, &Type, &f->rw);
19967 31040 : i = n+1; /* Finish loop. */
19968 : }
19969 : else
19970 : {
19971 89360 : i += 1;
19972 : }
19973 : }
19974 : }
19975 107206 : PushTFrwtok (Sym, Type, rw, tokpos);
19976 : }
19977 697255 : }
19978 :
19979 :
19980 : /*
19981 : BuildDesignatorRecord - Builds the record referencing.
19982 : The Stack is expected to contain:
19983 :
19984 :
19985 : Entry Exit
19986 : ===== ====
19987 :
19988 : Ptr ->
19989 : +--------------+
19990 : | n |
19991 : |--------------|
19992 : | fld1 | type1 |
19993 : |--------------|
19994 : . .
19995 : . .
19996 : . .
19997 : |--------------|
19998 : | fldn | typen | <- Ptr
19999 : |--------------| +-------------+
20000 : | Sym | Type | | S | type1|
20001 : |--------------| |-------------|
20002 : */
20003 :
20004 117234 : extern "C" void M2Quads_BuildDesignatorRecord (unsigned int dottok)
20005 : {
20006 117234 : unsigned int RecordTok;
20007 117234 : unsigned int FieldTok;
20008 117234 : unsigned int combinedtok;
20009 117234 : unsigned int n;
20010 117234 : unsigned int rw;
20011 117234 : unsigned int Field;
20012 117234 : unsigned int FieldType;
20013 117234 : unsigned int RecordSym;
20014 117234 : unsigned int Res;
20015 :
20016 117234 : M2Quads_PopT (&n);
20017 117234 : RecordSym = static_cast<unsigned int> (M2Quads_OperandT (n+1));
20018 : /* RecordType could be found by: SkipType (OperandF (n+1)). */
20019 117234 : RecordTok = static_cast<unsigned int> (M2Quads_OperandTok (n+1));
20020 117234 : rw = static_cast<unsigned int> (OperandMergeRW (n+1));
20021 117234 : M2Debug_Assert (SymbolTable_IsLegal (rw));
20022 117234 : Field = static_cast<unsigned int> (M2Quads_OperandT (n));
20023 117234 : FieldType = SymbolTable_SkipType (M2Quads_OperandF (n));
20024 117234 : FieldTok = static_cast<unsigned int> (M2Quads_OperandTok (n));
20025 117234 : combinedtok = M2LexBuf_MakeVirtualTok (dottok, RecordTok, FieldTok);
20026 117234 : if (n > 1)
20027 : {
20028 0 : M2Error_InternalError ((const char *) "not expecting to see n>1", 24);
20029 : }
20030 117234 : if (SymbolTable_IsUnused (Field))
20031 : {
20032 0 : M2MetaError_MetaErrors1 ((const char *) "record field {%1Dad} was declared as unused by a pragma", 55, (const char *) "record field {%1ad} is being used after being declared as unused by a pragma", 76, Field);
20033 : }
20034 117234 : Res = SymbolTable_MakeComponentRef (SymbolTable_MakeComponentRecord (combinedtok, SymbolTable_RightValue, RecordSym), Field);
20035 117234 : SymbolTable_PutVarConst (Res, IsReadOnly (RecordSym));
20036 117234 : GenQuadO (combinedtok, M2Quads_RecordFieldOp, Res, RecordSym, Field, false);
20037 117234 : M2Quads_PopN (n+1);
20038 117234 : PushTFrwtok (Res, FieldType, rw, combinedtok);
20039 117234 : }
20040 :
20041 :
20042 : /*
20043 : BuildDesignatorArray - Builds the array referencing.
20044 : The purpose of this procedure is to work out
20045 : whether the DesignatorArray is a constant string or
20046 : dynamic array/static array and to call the appropriate
20047 : BuildRoutine.
20048 :
20049 : The Stack is expected to contain:
20050 :
20051 : Entry Exit
20052 : ===== ====
20053 :
20054 : Ptr ->
20055 : +--------------+
20056 : | e | <- Ptr
20057 : |--------------| +------------+
20058 : | Sym | Type | | S | T |
20059 : |--------------| |------------|
20060 : */
20061 :
20062 57026 : extern "C" void M2Quads_BuildDesignatorArray (void)
20063 : {
20064 57026 : if ((SymbolTable_IsConst (M2Quads_OperandT (2))) && (SymbolTable_IsConstString (M2Quads_OperandT (2))))
20065 : {
20066 6 : M2MetaError_MetaErrorT1 (OperandTtok (2), (const char *) "{%1Ead} is not an array, but a constant string. Hint use a string constant created with an array constructor", 109, M2Quads_OperandT (2));
20067 6 : BuildDesignatorError ((const char *) "bad array access", 16);
20068 : }
20069 : else
20070 : {
20071 57020 : BuildDesignatorArrayStaticDynamic ();
20072 : }
20073 57020 : }
20074 :
20075 :
20076 : /*
20077 : BuildDesignatorPointer - Builds a pointer reference.
20078 : The Stack is expected to contain:
20079 :
20080 :
20081 : Entry Exit
20082 : ===== ====
20083 :
20084 : Ptr -> <- Ptr
20085 : +--------------+ +--------------+
20086 : | Sym1 | Type1| | Sym2 | Type2|
20087 : |--------------| |--------------|
20088 : */
20089 :
20090 20106 : extern "C" void M2Quads_BuildDesignatorPointer (unsigned int ptrtok)
20091 : {
20092 20106 : unsigned int combinedtok;
20093 20106 : unsigned int destok;
20094 20106 : unsigned int rw;
20095 20106 : unsigned int Sym1;
20096 20106 : unsigned int Type1;
20097 20106 : unsigned int Sym2;
20098 20106 : unsigned int Type2;
20099 :
20100 20106 : PopTFrwtok (&Sym1, &Type1, &rw, &destok);
20101 20106 : DebugLocation (destok, (const char *) "des ptr expression", 18);
20102 20106 : Type1 = SymbolTable_SkipType (Type1);
20103 20106 : if (Type1 == SymbolTable_NulSym)
20104 : {
20105 0 : M2MetaError_MetaErrorT1 (ptrtok, (const char *) "{%1ad} has no type and therefore cannot be dereferenced by ^", 60, Sym1);
20106 : }
20107 20106 : else if (SymbolTable_IsUnknown (Sym1))
20108 : {
20109 : /* avoid dangling else. */
20110 : /* Spellcheck. */
20111 0 : M2MetaError_MetaError1 ((const char *) "{%1EMad} is undefined and therefore {%1ad}^ cannot be resolved {%1&s}", 69, Sym1);
20112 0 : SymbolTable_UnknownReported (Sym1);
20113 : }
20114 : else
20115 : {
20116 : /* avoid dangling else. */
20117 20106 : combinedtok = M2LexBuf_MakeVirtual2Tok (destok, ptrtok);
20118 20106 : if (SymbolTable_IsPointer (Type1))
20119 : {
20120 20104 : Type2 = SymbolTable_GetSType (Type1);
20121 20104 : Sym2 = SymbolTable_MakeTemporary (ptrtok, SymbolTable_LeftValue);
20122 : /*
20123 : Ok must reference by address
20124 : - but we contain the type of the referenced entity
20125 : */
20126 20104 : MarkAsRead (rw);
20127 20104 : SymbolTable_PutVarPointerCheck (Sym1, true);
20128 20104 : CheckPointerThroughNil (ptrtok, Sym1);
20129 20104 : if ((SymbolTable_GetMode (Sym1)) == SymbolTable_LeftValue)
20130 : {
20131 510 : rw = SymbolTable_NulSym;
20132 510 : SymbolTable_PutLeftValueFrontBackType (Sym2, Type2, Type1);
20133 510 : GenQuadO (ptrtok, M2Quads_IndrXOp, Sym2, Type1, Sym1, false); /* Sym2 := *Sym1. */
20134 : }
20135 : else
20136 : {
20137 19594 : SymbolTable_PutLeftValueFrontBackType (Sym2, Type2, SymbolTable_NulSym);
20138 19594 : GenQuadO (ptrtok, M2Quads_BecomesOp, Sym2, SymbolTable_NulSym, Sym1, false); /* Sym2 := Sym1. */
20139 : }
20140 : /* We should check this for Sym2 later on (pointer via NIL). */
20141 20104 : SymbolTable_PutVarPointerCheck (Sym2, true);
20142 20104 : PushTFrwtok (Sym2, Type2, rw, combinedtok);
20143 20104 : DebugLocation (combinedtok, (const char *) "pointer expression", 18);
20144 : }
20145 2 : else if ((SymbolTable_IsHiddenType (Type1)) && ((SymbolTable_GetModuleScope (Type1)) != (SymbolTable_GetCurrentModuleScope ())))
20146 : {
20147 : /* avoid dangling else. */
20148 2 : M2MetaError_MetaErrorT1 (ptrtok, (const char *) "{%1Ead} is declared with an opaque type from a different module and cannot be dereferenced", 90, Sym1);
20149 2 : MarkAsRead (rw);
20150 2 : BuildDesignatorPointerError (Type1, rw, combinedtok, (const char *) "bad opaque pointer dereference", 30);
20151 : }
20152 : else
20153 : {
20154 : /* avoid dangling else. */
20155 0 : M2MetaError_MetaError2 ((const char *) "{%1Ead} is not a pointer type but a {%2dv}", 42, Sym1, Type1);
20156 0 : MarkAsRead (rw);
20157 0 : BuildDesignatorPointerError (Type1, rw, combinedtok, (const char *) "bad pointer dereference", 23);
20158 : }
20159 : }
20160 20106 : }
20161 :
20162 :
20163 : /*
20164 : BuildNulExpression - Builds a nul expression on the stack.
20165 : The Stack:
20166 :
20167 : Entry Exit
20168 :
20169 : <- Ptr
20170 : Empty +------------+
20171 : | NulSym |
20172 : |------------|
20173 : tokpos is the position of the RETURN token.
20174 : */
20175 :
20176 852 : extern "C" void M2Quads_BuildNulExpression (unsigned int tokpos)
20177 : {
20178 852 : M2Quads_PushTtok (static_cast<unsigned int> (SymbolTable_NulSym), tokpos);
20179 852 : }
20180 :
20181 :
20182 : /*
20183 : BuildSetStart - Pushes a Bitset type on the stack.
20184 :
20185 : The Stack:
20186 :
20187 : Entry Exit
20188 :
20189 : Ptr -> <- Ptr
20190 :
20191 : Empty +--------------+
20192 : | Bitset |
20193 : |--------------|
20194 : */
20195 :
20196 0 : extern "C" void M2Quads_BuildSetStart (unsigned int tokpos)
20197 : {
20198 0 : M2Quads_PushTtok (M2Bitset_Bitset, tokpos);
20199 0 : }
20200 :
20201 :
20202 : /*
20203 : BuildSetEnd - pops the set value and type from the stack
20204 : and pushes the value,type pair.
20205 :
20206 : Entry Exit
20207 :
20208 : Ptr ->
20209 : +--------------+
20210 : | Set Value | <- Ptr
20211 : |--------------| +--------------+
20212 : | Set Type | | Value | Type |
20213 : |--------------| |--------------|
20214 : */
20215 :
20216 0 : extern "C" void M2Quads_BuildSetEnd (void)
20217 : {
20218 0 : unsigned int valuepos;
20219 0 : unsigned int typepos;
20220 0 : unsigned int combined;
20221 0 : unsigned int value;
20222 0 : unsigned int type;
20223 :
20224 0 : M2Quads_PopTtok (&value, &valuepos);
20225 0 : M2Quads_PopTtok (&type, &typepos);
20226 0 : combined = M2LexBuf_MakeVirtual2Tok (typepos, valuepos);
20227 0 : M2Quads_PushTFtok (value, type, combined);
20228 0 : M2Debug_Assert (SymbolTable_IsSet (type));
20229 0 : }
20230 :
20231 :
20232 : /*
20233 : BuildEmptySet - Builds an empty set on the stack.
20234 : The Stack:
20235 :
20236 : Entry Exit
20237 :
20238 : <- Ptr
20239 : +-------------+
20240 : Ptr -> | Value |
20241 : +-----------+ |-------------|
20242 : | SetType | | SetType |
20243 : |-----------| |-------------|
20244 :
20245 : tokpos points to the opening '{'.
20246 : */
20247 :
20248 0 : extern "C" void M2Quads_BuildEmptySet (unsigned int tokpos)
20249 : {
20250 0 : NameKey_Name n;
20251 0 : unsigned int typepos;
20252 0 : unsigned int Type;
20253 0 : unsigned int NulSet;
20254 :
20255 0 : M2Quads_PopTtok (&Type, &typepos); /* type of set we are building */
20256 0 : if ((Type == SymbolTable_NulSym) && M2Options_Pim)
20257 : {
20258 : /* allowed generic {} in PIM Modula-2 */
20259 0 : typepos = tokpos;
20260 : }
20261 0 : else if (SymbolTable_IsUnknown (Type))
20262 : {
20263 : /* avoid dangling else. */
20264 : /* Spellcheck. */
20265 0 : M2MetaError_MetaError1 ((const char *) "set type {%1a} is undefined {%1&s}", 34, Type);
20266 0 : SymbolTable_UnknownReported (Type);
20267 0 : Type = M2Bitset_Bitset;
20268 : }
20269 0 : else if (! (SymbolTable_IsSet (SymbolTable_SkipType (Type))))
20270 : {
20271 : /* avoid dangling else. */
20272 0 : M2MetaError_MetaError1 ((const char *) "expecting a set type {%1a} and not a {%1d}", 42, Type);
20273 0 : Type = M2Bitset_Bitset;
20274 : }
20275 : else
20276 : {
20277 : /* avoid dangling else. */
20278 0 : Type = SymbolTable_SkipType (Type);
20279 0 : M2Debug_Assert (Type != SymbolTable_NulSym);
20280 : }
20281 0 : NulSet = SymbolTable_MakeTemporary (typepos, SymbolTable_ImmediateValue);
20282 0 : SymbolTable_PutVar (NulSet, Type);
20283 0 : SymbolTable_PutConstSet (NulSet);
20284 0 : if (M2Options_CompilerDebugging)
20285 : {
20286 0 : n = SymbolTable_GetSymName (Type);
20287 0 : M2Printf_printf1 ((const char *) "set type = %a\\n", 15, (const unsigned char *) &n, (sizeof (n)-1));
20288 : }
20289 0 : M2ALU_PushNulSet (Type); /* onto the ALU stack */
20290 0 : SymbolTable_PopValue (NulSet); /* ALU -> symbol table */
20291 : /* and now construct the M2Quads stack as defined by the comments above */
20292 0 : M2Quads_PushTtok (Type, typepos);
20293 0 : M2Quads_PushTtok (NulSet, typepos);
20294 0 : if (M2Options_CompilerDebugging)
20295 : {
20296 0 : n = SymbolTable_GetSymName (Type);
20297 0 : M2Printf_printf2 ((const char *) "Type = %a (%d) built empty set\\n", 34, (const unsigned char *) &n, (sizeof (n)-1), (const unsigned char *) &Type, (sizeof (Type)-1));
20298 0 : M2Quads_DisplayStack (); /* Debugging info */
20299 : }
20300 0 : }
20301 :
20302 :
20303 : /*
20304 : BuildInclRange - includes a set range with a set.
20305 :
20306 :
20307 : Entry Exit
20308 : ===== ====
20309 :
20310 :
20311 : Ptr ->
20312 : +------------+
20313 : | El2 |
20314 : |------------|
20315 : | El1 | <- Ptr
20316 : |------------| +-------------------+
20317 : | Set Value | | Value + {El1..El2}|
20318 : |------------| |-------------------|
20319 :
20320 : No quadruples produced as the range info is contained within
20321 : the set value.
20322 : */
20323 :
20324 0 : extern "C" void M2Quads_BuildInclRange (void)
20325 : {
20326 0 : NameKey_Name n;
20327 0 : unsigned int el1;
20328 0 : unsigned int el2;
20329 0 : unsigned int value;
20330 :
20331 0 : M2Quads_PopT (&el2);
20332 0 : SafeCheckWithField ();
20333 0 : M2Quads_PopT (&el1);
20334 0 : SafeCheckWithField ();
20335 0 : M2Quads_PopT (&value);
20336 0 : if (! (SymbolTable_IsConstSet (value)))
20337 : {
20338 0 : n = SymbolTable_GetSymName (el1);
20339 0 : M2Error_WriteFormat1 ((const char *) "can only add bit ranges to a constant set, %a is not a constant set", 67, (const unsigned char *) &n, (sizeof (n)-1));
20340 : }
20341 0 : if ((SymbolTable_IsConst (el1)) && (SymbolTable_IsConst (el2)))
20342 : {
20343 0 : SymbolTable_PushValue (value); /* onto ALU stack */
20344 0 : M2ALU_AddBitRange (M2LexBuf_GetTokenNo (), el1, el2); /* onto ALU stack */
20345 0 : SymbolTable_PopValue (value); /* ALU -> symboltable */
20346 : }
20347 : else
20348 : {
20349 0 : if (! (SymbolTable_IsConst (el1)))
20350 : {
20351 0 : n = SymbolTable_GetSymName (el1);
20352 0 : M2Error_WriteFormat1 ((const char *) "must use constants as ranges when defining a set constant, problem with the low value %a", 88, (const unsigned char *) &n, (sizeof (n)-1));
20353 : }
20354 0 : if (! (SymbolTable_IsConst (el2)))
20355 : {
20356 0 : n = SymbolTable_GetSymName (el2);
20357 0 : M2Error_WriteFormat1 ((const char *) "must use constants as ranges when defining a set constant, problem with the high value %a", 89, (const unsigned char *) &n, (sizeof (n)-1));
20358 : }
20359 : }
20360 0 : M2Quads_PushT (value);
20361 0 : }
20362 :
20363 :
20364 : /*
20365 : BuildInclBit - includes a bit into the set.
20366 :
20367 : Entry Exit
20368 : ===== ====
20369 :
20370 :
20371 : Ptr ->
20372 : +------------+
20373 : | Element | <- Ptr
20374 : |------------| +------------+
20375 : | Value | | Value |
20376 : |------------| |------------|
20377 :
20378 : */
20379 :
20380 12100 : extern "C" void M2Quads_BuildInclBit (void)
20381 : {
20382 12100 : unsigned int tok;
20383 12100 : unsigned int el;
20384 12100 : unsigned int value;
20385 12100 : unsigned int t;
20386 :
20387 12100 : SafeCheckWithField ();
20388 12100 : M2Quads_PopT (&el);
20389 12100 : M2Quads_PopT (&value);
20390 12100 : tok = M2LexBuf_GetTokenNo ();
20391 12100 : if (SymbolTable_IsConst (el))
20392 : {
20393 11966 : SymbolTable_PushValue (value); /* onto ALU stack */
20394 11966 : M2ALU_AddBit (tok, el); /* onto ALU stack */
20395 11966 : SymbolTable_PopValue (value); /* ALU -> symboltable */
20396 : }
20397 : else
20398 : {
20399 134 : if ((SymbolTable_GetMode (el)) == SymbolTable_LeftValue)
20400 : {
20401 0 : t = SymbolTable_MakeTemporary (tok, SymbolTable_RightValue);
20402 0 : SymbolTable_PutVar (t, SymbolTable_GetSType (el));
20403 0 : CheckPointerThroughNil (tok, el);
20404 0 : doIndrX (tok, t, el);
20405 0 : el = t;
20406 : }
20407 134 : if (SymbolTable_IsConst (value))
20408 : {
20409 : /* Move constant or record field into a variable to achieve the include. */
20410 134 : t = SymbolTable_MakeTemporary (tok, SymbolTable_RightValue);
20411 134 : SymbolTable_PutVar (t, SymbolTable_GetSType (value));
20412 134 : GenQuad (M2Quads_BecomesOp, t, SymbolTable_NulSym, value);
20413 134 : value = t;
20414 : }
20415 134 : GenQuad (M2Quads_InclOp, value, SymbolTable_NulSym, el);
20416 : }
20417 12100 : M2Quads_PushT (value);
20418 12100 : }
20419 :
20420 :
20421 : /*
20422 : SilentBuildConstructor - places NulSym into the constructor fifo queue.
20423 : */
20424 :
20425 0 : extern "C" void M2Quads_SilentBuildConstructor (void)
20426 : {
20427 0 : FifoQueue_PutConstructorIntoFifoQueue (SymbolTable_NulSym);
20428 0 : }
20429 :
20430 :
20431 : /*
20432 : SilentBuildConstructorStart - removes an entry from the constructor fifo queue.
20433 : */
20434 :
20435 25984 : extern "C" void M2Quads_SilentBuildConstructorStart (void)
20436 : {
20437 25984 : unsigned int constValue;
20438 :
20439 25984 : FifoQueue_GetConstructorFromFifoQueue (&constValue);
20440 25984 : }
20441 :
20442 :
20443 : /*
20444 : BuildConstructor - builds a constructor.
20445 : Stack
20446 :
20447 : Entry Exit
20448 :
20449 : Ptr ->
20450 : +------------+
20451 : | Type | <- Ptr
20452 : |------------+
20453 : */
20454 :
20455 37178 : extern "C" void M2Quads_BuildConstructor (unsigned int tokcbrpos)
20456 : {
20457 37178 : unsigned int tok;
20458 37178 : unsigned int constValue;
20459 37178 : unsigned int type;
20460 :
20461 37178 : M2Quads_PopTtok (&type, &tok);
20462 37178 : constValue = SymbolTable_MakeTemporary (tok, SymbolTable_ImmediateValue);
20463 37178 : SymbolTable_PutVar (constValue, type);
20464 37178 : SymbolTable_PutConstructor (constValue);
20465 37178 : SymbolTable_PushValue (constValue);
20466 37178 : if (type == SymbolTable_NulSym)
20467 : {
20468 6 : M2MetaError_MetaErrorT0 (tokcbrpos, (const char *) "{%E}constructor requires a type before the opening %{", 53);
20469 : }
20470 : else
20471 : {
20472 37172 : M2ALU_ChangeToConstructor (tok, type);
20473 37172 : SymbolTable_PutConstructorFrom (constValue, type);
20474 37172 : SymbolTable_PopValue (constValue);
20475 37172 : FifoQueue_PutConstructorIntoFifoQueue (constValue);
20476 : }
20477 37178 : PushConstructor (type);
20478 37178 : }
20479 :
20480 :
20481 : /*
20482 : BuildConstructorStart - builds a constructor.
20483 : Stack
20484 :
20485 : Entry Exit
20486 :
20487 : Ptr -> <- Ptr
20488 : +------------+ +----------------+
20489 : | Type | | ConstructorSym |
20490 : |------------+ |----------------|
20491 : */
20492 :
20493 11182 : extern "C" void M2Quads_BuildConstructorStart (unsigned int cbratokpos)
20494 : {
20495 11182 : unsigned int typepos;
20496 11182 : unsigned int constValue;
20497 11182 : unsigned int type;
20498 :
20499 11182 : M2Quads_PopTtok (&type, &typepos); /* we ignore the type as we already have the constructor symbol from pass C */
20500 11182 : FifoQueue_GetConstructorFromFifoQueue (&constValue); /* we ignore the type as we already have the constructor symbol from pass C */
20501 11182 : if (type != (SymbolTable_GetSType (constValue)))
20502 : {
20503 0 : M2MetaError_MetaErrorT3 (cbratokpos, (const char *) "{%E}the constructor type is {%1ad} and this is different from the constant {%2ad} which has a type {%2tad}", 106, type, constValue, constValue);
20504 : }
20505 11182 : M2Quads_PushTtok (constValue, cbratokpos);
20506 11182 : PushConstructor (type);
20507 11182 : }
20508 :
20509 :
20510 : /*
20511 : BuildConstructorEnd - removes the current constructor frame from the
20512 : constructor stack (it does not effect the quad
20513 : stack)
20514 :
20515 : Entry Exit
20516 :
20517 : Ptr -> <- Ptr
20518 : +------------+ +------------+
20519 : | const | | const |
20520 : |------------| |------------|
20521 :
20522 : startpos is the start of the constructor, either the typename or '{'
20523 : cbratokpos is the '}'.
20524 : */
20525 :
20526 11182 : extern "C" void M2Quads_BuildConstructorEnd (unsigned int startpos, unsigned int cbratokpos)
20527 : {
20528 11182 : unsigned int value;
20529 11182 : unsigned int valtok;
20530 :
20531 11182 : if (DebugTokPos)
20532 : {
20533 : M2Error_WarnStringAt (DynamicStrings_InitString ((const char *) "startpos", 8), startpos);
20534 : M2Error_WarnStringAt (DynamicStrings_InitString ((const char *) "cbratokpos", 10), cbratokpos);
20535 : }
20536 11182 : M2Quads_PopTtok (&value, &valtok);
20537 11182 : if (DebugTokPos)
20538 : {
20539 : M2Error_WarnStringAt (DynamicStrings_InitString ((const char *) "value valtok", 12), valtok);
20540 : }
20541 11182 : valtok = M2LexBuf_MakeVirtual2Tok (startpos, cbratokpos);
20542 11182 : SymbolTable_PutDeclared (valtok, value);
20543 11182 : M2Quads_PushTtok (value, valtok); /* Use valtok as we now know it was a constructor. */
20544 11182 : M2Quads_PopConstructor (); /* Use valtok as we now know it was a constructor. */
20545 11182 : if (DebugTokPos)
20546 : {
20547 : M2Error_WarnStringAt (DynamicStrings_InitString ((const char *) "aggregate constant", 18), valtok);
20548 : }
20549 11182 : }
20550 :
20551 :
20552 : /*
20553 : NextConstructorField - increments the top of constructor stacks index by one.
20554 : */
20555 :
20556 35164 : extern "C" void M2Quads_NextConstructorField (void)
20557 : {
20558 35164 : M2Quads_ConstructorFrame c;
20559 :
20560 35164 : c = static_cast<M2Quads_ConstructorFrame> (M2StackAddress_PeepAddress (ConstructorStack, 1));
20561 35164 : c->index += 1;
20562 35164 : }
20563 :
20564 :
20565 : /*
20566 : BuildTypeForConstructor - pushes the type implied by the current constructor.
20567 : If no constructor is currently being built then
20568 : it Pushes a Bitset type.
20569 : */
20570 :
20571 1728 : extern "C" void M2Quads_BuildTypeForConstructor (unsigned int tokpos)
20572 : {
20573 1728 : M2Quads_ConstructorFrame c;
20574 :
20575 1728 : if ((M2StackAddress_NoOfItemsInStackAddress (ConstructorStack)) == 0)
20576 : {
20577 660 : M2Quads_PushTtok (M2Bitset_Bitset, tokpos);
20578 : }
20579 : else
20580 : {
20581 1068 : c = static_cast<M2Quads_ConstructorFrame> (M2StackAddress_PeepAddress (ConstructorStack, 1));
20582 1068 : if ((SymbolTable_IsArray (c->type)) || (SymbolTable_IsSet (c->type)))
20583 : {
20584 972 : M2Quads_PushTtok (SymbolTable_GetSType (c->type), tokpos);
20585 : }
20586 96 : else if (SymbolTable_IsRecord (c->type))
20587 : {
20588 : /* avoid dangling else. */
20589 96 : M2Quads_PushTtok (SymbolTable_GetSType (SymbolTable_GetNth (c->type, c->index)), tokpos);
20590 : }
20591 : else
20592 : {
20593 : /* avoid dangling else. */
20594 0 : M2MetaError_MetaError1 ((const char *) "{%1ad} is not a set, record or array type which is expected when constructing an aggregate entity", 97, c->type);
20595 : }
20596 : }
20597 1728 : }
20598 :
20599 :
20600 : /*
20601 : BuildComponentValue - builds a component value.
20602 :
20603 : Entry Exit
20604 :
20605 : Ptr -> <- Ptr
20606 :
20607 :
20608 : +------------+ +------------+
20609 : | const | | const |
20610 : |------------| |------------|
20611 : */
20612 :
20613 26114 : extern "C" void M2Quads_BuildComponentValue (void)
20614 : {
20615 26114 : unsigned int e1tok;
20616 26114 : unsigned int e2tok;
20617 26114 : unsigned int consttok;
20618 26114 : unsigned int virtpos;
20619 26114 : unsigned int const_;
20620 26114 : unsigned int e1;
20621 26114 : unsigned int e2;
20622 26114 : NameKey_Name nuldotdot;
20623 26114 : NameKey_Name nulby;
20624 :
20625 26114 : M2Quads_PopT (&nulby);
20626 26114 : if (nulby == M2Reserved_NulTok)
20627 : {
20628 26084 : M2Quads_PopT (&nuldotdot);
20629 26084 : if (nuldotdot == M2Reserved_NulTok)
20630 : {
20631 25842 : M2Quads_PopTtok (&e1, &e1tok);
20632 25842 : M2Quads_PopTtok (&const_, &consttok);
20633 25842 : const_ = AddFieldTo (const_, e1, consttok, e1tok);
20634 25842 : PushTFrwtok (const_, SymbolTable_GetSType (const_), static_cast<unsigned int> (SymbolTable_NulSym), M2LexBuf_MakeVirtual2Tok (consttok, e1tok));
20635 : }
20636 : else
20637 : {
20638 242 : M2Quads_PopTtok (&e2, &e2tok);
20639 242 : M2Quads_PopTtok (&e1, &e1tok);
20640 242 : M2Quads_PopTtok (&const_, &consttok);
20641 242 : SymbolTable_PushValue (const_);
20642 242 : M2ALU_AddBitRange (M2LexBuf_MakeVirtual2Tok (e1tok, e2tok), e1, e2);
20643 242 : SymbolTable_PopValue (const_);
20644 242 : PushTFrwtok (const_, SymbolTable_GetSType (const_), static_cast<unsigned int> (SymbolTable_NulSym), M2LexBuf_MakeVirtual2Tok (consttok, e2tok));
20645 : }
20646 : }
20647 : else
20648 : {
20649 30 : M2Quads_PopTtok (&e1, &e1tok);
20650 30 : M2Quads_PopT (&nuldotdot);
20651 30 : if (nuldotdot == M2Reserved_NulTok)
20652 : {
20653 30 : M2Quads_PopTtok (&e2, &e2tok);
20654 30 : M2Quads_PopTtok (&const_, &consttok);
20655 30 : SymbolTable_PushValue (const_);
20656 30 : M2ALU_AddElements (M2LexBuf_MakeVirtual2Tok (e1tok, e2tok), e2, e1);
20657 30 : SymbolTable_PopValue (const_);
20658 30 : PushTFrwtok (const_, SymbolTable_GetSType (const_), static_cast<unsigned int> (SymbolTable_NulSym), M2LexBuf_MakeVirtual2Tok (consttok, e2tok));
20659 : }
20660 : else
20661 : {
20662 0 : M2Quads_PopTtok (&e2, &e2tok);
20663 0 : M2Quads_PopTtok (&e1, &e1tok);
20664 0 : M2Quads_PopTtok (&const_, &consttok);
20665 0 : consttok = M2LexBuf_MakeVirtual2Tok (consttok, e2tok);
20666 0 : M2MetaError_MetaErrorT1 (consttok, (const char *) "the constant {%E1a} must be either an array constructor or a set constructor", 76, const_);
20667 0 : PushTFrwtok (const_, SymbolTable_GetSType (const_), static_cast<unsigned int> (SymbolTable_NulSym), consttok);
20668 : }
20669 : }
20670 26114 : }
20671 :
20672 :
20673 : /*
20674 : PopConstructor - removes the top constructor from the top of stack.
20675 : */
20676 :
20677 48360 : extern "C" void M2Quads_PopConstructor (void)
20678 : {
20679 48360 : M2Quads_ConstructorFrame c;
20680 :
20681 48360 : c = static_cast<M2Quads_ConstructorFrame> (M2StackAddress_PopAddress (ConstructorStack));
20682 48360 : Storage_DEALLOCATE ((void **) &c, sizeof (M2Quads__T1));
20683 48360 : }
20684 :
20685 :
20686 : /*
20687 : BuildNot - Builds a NOT operation from the quad stack.
20688 : The Stack is expected to contain:
20689 :
20690 :
20691 : Entry Exit
20692 : ===== ====
20693 :
20694 : Ptr -> <- Ptr
20695 : +------------+ +------------+
20696 : | t | f | | f | t |
20697 : |------------| |------------|
20698 : */
20699 :
20700 4980 : extern "C" void M2Quads_BuildNot (unsigned int notTokPos)
20701 : {
20702 4980 : unsigned int combinedTok;
20703 4980 : unsigned int exprTokPos;
20704 4980 : unsigned int t;
20705 4980 : unsigned int f;
20706 :
20707 4980 : CheckBooleanId ();
20708 4980 : PopBooltok (&t, &f, &exprTokPos);
20709 4980 : combinedTok = M2LexBuf_MakeVirtualTok (notTokPos, notTokPos, exprTokPos);
20710 4980 : PushBooltok (f, t, combinedTok);
20711 4980 : }
20712 :
20713 :
20714 : /*
20715 : RecordOp - Records the operator passed on the stack.
20716 : This is called when a boolean operator is found in an
20717 : expression. It is called just after the lhs has been built
20718 : and pushed to the quad stack and prior to the rhs build.
20719 : It checks to see if AND OR or equality tests are required.
20720 : It will short circuit AND and OR expressions. It also
20721 : converts a lhs to a boolean variable if an xor comparison
20722 : is about to be performed.
20723 :
20724 : Checks for AND operator or OR operator
20725 : if either of these operators are found then BackPatching
20726 : takes place.
20727 : The Expected Stack:
20728 :
20729 : Entry Exit
20730 :
20731 : Ptr -> <- Ptr
20732 : +-------------+ +-------------+
20733 : | OperatorTok | | OperatorTok |
20734 : |-------------| |-------------|
20735 : | t | f | | t | f |
20736 : |-------------| |-------------|
20737 :
20738 :
20739 : If OperatorTok=AndTok
20740 : Then
20741 : BackPatch(f, NextQuad)
20742 : Elsif OperatorTok=OrTok
20743 : Then
20744 : BackPatch(t, NextQuad)
20745 : End
20746 : */
20747 :
20748 106143 : extern "C" void M2Quads_RecordOp (void)
20749 : {
20750 106143 : NameKey_Name Op;
20751 106143 : unsigned int tokno;
20752 106143 : unsigned int t;
20753 106143 : unsigned int f;
20754 :
20755 106143 : M2Quads_PopTtok (&Op, &tokno);
20756 106143 : if ((Op == M2Reserved_AndTok) || (Op == M2Reserved_AmbersandTok))
20757 : {
20758 9808 : CheckBooleanId ();
20759 9808 : PopBool (&t, &f);
20760 9808 : BackPatch (t, NextQuad);
20761 9808 : PushBool (0, f);
20762 : }
20763 96335 : else if (Op == M2Reserved_OrTok)
20764 : {
20765 : /* avoid dangling else. */
20766 3630 : CheckBooleanId ();
20767 3630 : PopBool (&t, &f);
20768 3630 : BackPatch (f, NextQuad);
20769 3630 : PushBool (t, 0);
20770 : }
20771 92705 : else if ((IsBoolean (1)) && ((((Op == M2Reserved_EqualTok) || (Op == M2Reserved_LessGreaterTok)) || (Op == M2Reserved_HashTok)) || (Op == M2Reserved_InTok)))
20772 : {
20773 : /* avoid dangling else. */
20774 52 : ConvertBooleanToVariable (tokno, 1);
20775 : }
20776 106143 : M2Quads_PushTtok (Op, tokno);
20777 106143 : }
20778 :
20779 :
20780 : /*
20781 : BuildRelOp - Builds a relative operation from the quad stack.
20782 : The Stack is expected to contain:
20783 :
20784 :
20785 : Entry Exit
20786 : ===== ====
20787 :
20788 : Ptr ->
20789 : +------------+
20790 : | e1 |
20791 : |------------| <- Ptr
20792 : | Operator |
20793 : |------------| +------------+
20794 : | e2 | | t | f |
20795 : |------------| |------------|
20796 :
20797 :
20798 : Quadruples Produced
20799 :
20800 : q IFOperator e2 e1 TrueExit ; e2 e1 since
20801 : q+1 GotoOp FalseExit ; relation > etc
20802 : ; requires order.
20803 : */
20804 :
20805 92296 : extern "C" void M2Quads_BuildRelOp (unsigned int optokpos)
20806 : {
20807 92296 : unsigned int combinedTok;
20808 92296 : unsigned int rightpos;
20809 92296 : unsigned int leftpos;
20810 92296 : NameKey_Name Op;
20811 92296 : unsigned int t;
20812 92296 : unsigned int rightType;
20813 92296 : unsigned int leftType;
20814 92296 : unsigned int right;
20815 92296 : unsigned int left;
20816 92296 : DynamicStrings_String s;
20817 :
20818 92296 : if (M2Options_CompilerDebugging)
20819 : {
20820 0 : M2Quads_DisplayStack (); /* Debugging info */
20821 : }
20822 92296 : if (((M2Quads_IsInConstExpression ()) && (IsBoolean (1))) && (IsBoolean (3)))
20823 : {
20824 : /*
20825 : we allow # and = to be used with Boolean expressions.
20826 : we do not allow > < >= <= though. We only examine
20827 : this case if we are in a const expression as there will be
20828 : no dereferencing of operands.
20829 : */
20830 0 : BuildRelOpFromBoolean (optokpos);
20831 : }
20832 : else
20833 : {
20834 92296 : if (IsBoolean (1))
20835 : {
20836 64 : ConvertBooleanToVariable (OperandTtok (1), 1);
20837 : }
20838 92296 : if (IsBoolean (3))
20839 : {
20840 0 : ConvertBooleanToVariable (OperandTtok (3), 3);
20841 : }
20842 92296 : M2Quads_PopTFtok (&right, &rightType, &rightpos);
20843 92296 : M2Quads_PopT (&Op);
20844 92296 : M2Quads_PopTFtok (&left, &leftType, &leftpos);
20845 92296 : CheckVariableOrConstantOrProcedure (rightpos, right);
20846 92296 : CheckVariableOrConstantOrProcedure (leftpos, left);
20847 92296 : combinedTok = M2LexBuf_MakeVirtualTok (optokpos, leftpos, rightpos);
20848 92296 : if ((left != SymbolTable_NulSym) && (right != SymbolTable_NulSym))
20849 : {
20850 : /* BuildRange will check the expression later on once gcc knows about all data types. */
20851 92296 : BuildRange (M2Range_InitTypesExpressionCheck (combinedTok, left, right, true, Op == M2Reserved_InTok));
20852 : }
20853 : /* Must dereference LeftValue operands. */
20854 92296 : if ((SymbolTable_GetMode (right)) == SymbolTable_LeftValue)
20855 : {
20856 1936 : t = SymbolTable_MakeTemporary (rightpos, SymbolTable_RightValue);
20857 1936 : SymbolTable_PutVar (t, SymbolTable_GetSType (right));
20858 1936 : CheckPointerThroughNil (rightpos, right);
20859 1936 : doIndrX (rightpos, t, right);
20860 1936 : right = t;
20861 : }
20862 92296 : if ((SymbolTable_GetMode (left)) == SymbolTable_LeftValue)
20863 : {
20864 6401 : t = SymbolTable_MakeTemporary (leftpos, SymbolTable_RightValue);
20865 6401 : SymbolTable_PutVar (t, SymbolTable_GetSType (left));
20866 6401 : CheckPointerThroughNil (leftpos, left);
20867 6401 : doIndrX (leftpos, t, left);
20868 6401 : left = t;
20869 : }
20870 92296 : if (DebugTokPos)
20871 : {
20872 : s = DynamicStrings_InitStringCharStar (NameKey_KeyToCharStar (M2LexBuf_GetTokenName (Op)));
20873 : M2Error_WarnStringAt (s, optokpos);
20874 : s = DynamicStrings_InitString ((const char *) "left", 4);
20875 : M2Error_WarnStringAt (s, leftpos);
20876 : s = DynamicStrings_InitString ((const char *) "right", 5);
20877 : M2Error_WarnStringAt (s, rightpos);
20878 : s = DynamicStrings_InitString ((const char *) "caret", 5);
20879 : M2Error_WarnStringAt (s, optokpos);
20880 : s = DynamicStrings_InitString ((const char *) "combined", 8);
20881 : M2Error_WarnStringAt (s, combinedTok);
20882 : }
20883 92296 : GenQuadOtok (combinedTok, MakeOp (Op), left, right, 0, false, leftpos, rightpos, M2LexBuf_UnknownTokenNo); /* True Exit */
20884 92296 : GenQuadO (combinedTok, M2Quads_GotoOp, SymbolTable_NulSym, SymbolTable_NulSym, 0, false); /* False Exit */
20885 92296 : PushBooltok (NextQuad-2, NextQuad-1, combinedTok); /* False Exit */
20886 : }
20887 92296 : }
20888 :
20889 :
20890 : /*
20891 : BuildBinaryOp - Builds a binary operation from the quad stack.
20892 : Be aware that this procedure will check for
20893 : the overloading of the bitset operators + - \ *.
20894 : So do NOT call this procedure if you are building
20895 : a reference to an array which has a bitset type or
20896 : the address arithmetic will be wrongly coersed into
20897 : logical ORs.
20898 :
20899 : The Stack is expected to contain:
20900 :
20901 :
20902 : Entry Exit
20903 : ===== ====
20904 :
20905 : Ptr ->
20906 : +------------+
20907 : | Sym1 |
20908 : |------------|
20909 : | Operator | <- Ptr
20910 : |------------| +------------+
20911 : | Sym2 | | Temporary |
20912 : |------------| |------------|
20913 :
20914 :
20915 : Quadruples Produced
20916 :
20917 : q Operator Temporary Sym1 Sym2
20918 :
20919 :
20920 : OR
20921 :
20922 :
20923 : Entry Exit
20924 : ===== ====
20925 :
20926 : Ptr ->
20927 : +------------+
20928 : | T1 | F1 |
20929 : |------------|
20930 : | OrTok | <- Ptr
20931 : |------------| +------------+
20932 : | T2 | F2 | | T1+T2| F1 |
20933 : |------------| |------------|
20934 :
20935 :
20936 : Quadruples Produced
20937 :
20938 : */
20939 :
20940 74142 : extern "C" void M2Quads_BuildBinaryOp (void)
20941 : {
20942 74142 : doBuildBinaryOp (true, true);
20943 74034 : }
20944 :
20945 :
20946 : /*
20947 : BuildUnaryOp - Builds a unary operation from the quad stack.
20948 : The Stack is expected to contain:
20949 :
20950 :
20951 : Entry Exit
20952 : ===== ====
20953 :
20954 : Ptr ->
20955 : +------------+
20956 : | Sym |
20957 : |------------| +------------+
20958 : | Operator | | Temporary | <- Ptr
20959 : |------------| |------------|
20960 :
20961 :
20962 : Quadruples Produced
20963 :
20964 : q Operator Temporary _ Sym
20965 :
20966 : */
20967 :
20968 21408 : extern "C" void M2Quads_BuildUnaryOp (void)
20969 : {
20970 21408 : unsigned int sympos;
20971 21408 : unsigned int tokpos;
20972 21408 : NameKey_Name Tok;
20973 21408 : unsigned int type;
20974 21408 : unsigned int Sym;
20975 21408 : unsigned int SymT;
20976 21408 : unsigned int r;
20977 21408 : unsigned int t;
20978 :
20979 21408 : PopTrwtok (&Sym, &r, &sympos);
20980 21408 : M2Quads_PopTtok (&Tok, &tokpos);
20981 21408 : if (Tok == M2Reserved_MinusTok)
20982 : {
20983 21252 : MarkAsRead (r);
20984 21252 : type = M2Base_NegateType (SymbolTable_GetSType (Sym)); /* , sympos */
20985 21252 : tokpos = M2LexBuf_MakeVirtualTok (tokpos, tokpos, sympos);
20986 42504 : t = SymbolTable_MakeTemporary (tokpos, AreConstant (SymbolTable_IsConst (Sym)));
20987 21252 : SymbolTable_PutVar (t, type);
20988 : /*
20989 : variables must have a type and REAL/LONGREAL constants must
20990 : be typed
20991 : */
20992 21252 : if (! (SymbolTable_IsConst (Sym)))
20993 : {
20994 : /* avoid gcc warning by using compound statement even if not strictly necessary. */
20995 1002 : if ((type != SymbolTable_NulSym) && (SymbolTable_IsSet (SymbolTable_SkipType (type))))
20996 : {} /* empty. */
20997 : /* do not dereference set variables */
20998 924 : else if ((SymbolTable_GetMode (Sym)) == SymbolTable_LeftValue)
20999 : {
21000 : /* avoid dangling else. */
21001 : /* dereference symbols which are not sets and which are variables */
21002 0 : SymT = SymbolTable_MakeTemporary (sympos, SymbolTable_RightValue);
21003 0 : SymbolTable_PutVar (SymT, SymbolTable_GetSType (Sym));
21004 0 : CheckPointerThroughNil (sympos, Sym);
21005 0 : doIndrX (sympos, SymT, Sym);
21006 0 : Sym = SymT;
21007 : }
21008 : }
21009 21252 : GenQuadO (tokpos, M2Quads_NegateOp, t, SymbolTable_NulSym, Sym, true);
21010 21252 : M2Quads_PushTtok (t, tokpos);
21011 : }
21012 156 : else if (Tok == M2Reserved_PlusTok)
21013 : {
21014 : /* avoid dangling else. */
21015 156 : tokpos = M2LexBuf_MakeVirtualTok (tokpos, tokpos, sympos);
21016 156 : PushTrwtok (Sym, r, tokpos);
21017 : }
21018 : else
21019 : {
21020 : /* avoid dangling else. */
21021 0 : M2MetaError_MetaErrorNT1 (tokpos, (const char *) "expecting an unary operator, seen {%Ek%a}", 41, Tok);
21022 : }
21023 21408 : }
21024 :
21025 :
21026 : /*
21027 : OperandT - returns the ident operand stored in the true position on the boolean stack.
21028 : */
21029 :
21030 214541580 : extern "C" unsigned int M2Quads_OperandT (unsigned int pos)
21031 : {
21032 214541580 : M2Debug_Assert (! (IsBoolean (pos)));
21033 214541580 : return OperandTno (pos);
21034 : /* static analysis guarentees a RETURN statement will be used before here. */
21035 : __builtin_unreachable ();
21036 : }
21037 :
21038 :
21039 : /*
21040 : OperandF - returns the ident operand stored in the false position on the boolean stack.
21041 : */
21042 :
21043 178228 : extern "C" unsigned int M2Quads_OperandF (unsigned int pos)
21044 : {
21045 178228 : M2Debug_Assert (! (IsBoolean (pos)));
21046 178228 : return OperandFno (pos);
21047 : /* static analysis guarentees a RETURN statement will be used before here. */
21048 : __builtin_unreachable ();
21049 : }
21050 :
21051 :
21052 : /*
21053 : PushTF - Push a True and False numbers onto the True/False stack.
21054 : True and False are assumed to contain Symbols or Ident etc.
21055 : */
21056 :
21057 15994640 : extern "C" void M2Quads_PushTF (unsigned int True, unsigned int False)
21058 : {
21059 15994640 : M2Quads_BoolFrame f;
21060 :
21061 15994640 : f = newBoolFrame ();
21062 15994640 : f->TrueExit = static_cast<unsigned int> (True);
21063 15994640 : f->FalseExit = static_cast<unsigned int> (False);
21064 15994640 : M2StackAddress_PushAddress (BoolStack, reinterpret_cast <void *> (f));
21065 15994640 : }
21066 :
21067 :
21068 : /*
21069 : PopTF - Pop a True and False number from the True/False stack.
21070 : True and False are assumed to contain Symbols or Ident etc.
21071 : */
21072 :
21073 10767703 : extern "C" void M2Quads_PopTF (unsigned int *True, unsigned int *False)
21074 : {
21075 10767703 : M2Quads_BoolFrame f;
21076 :
21077 10767703 : f = static_cast<M2Quads_BoolFrame> (M2StackAddress_PopAddress (BoolStack));
21078 10767703 : (*True) = static_cast<unsigned int> (f->TrueExit);
21079 10767703 : (*False) = static_cast<unsigned int> (f->FalseExit);
21080 10767703 : M2Debug_Assert (! f->BooleanOp);
21081 10767703 : Storage_DEALLOCATE ((void **) &f, sizeof (M2Quads__T2));
21082 10767703 : }
21083 :
21084 :
21085 : /*
21086 : PushT - Push an item onto the stack in the T (true) position.
21087 : */
21088 :
21089 99242185 : extern "C" void M2Quads_PushT (unsigned int True)
21090 : {
21091 99242185 : M2Quads_BoolFrame f;
21092 :
21093 99242185 : f = newBoolFrame ();
21094 99242185 : f->TrueExit = static_cast<unsigned int> (True);
21095 99242185 : M2StackAddress_PushAddress (BoolStack, reinterpret_cast <void *> (f));
21096 99242185 : }
21097 :
21098 :
21099 : /*
21100 : PopT - Pops the T value from the stack.
21101 : */
21102 :
21103 146412772 : extern "C" void M2Quads_PopT (unsigned int *True)
21104 : {
21105 146412772 : M2Quads_BoolFrame f;
21106 :
21107 146412772 : f = static_cast<M2Quads_BoolFrame> (M2StackAddress_PopAddress (BoolStack));
21108 146412766 : (*True) = static_cast<unsigned int> (f->TrueExit);
21109 146412766 : M2Debug_Assert (! f->BooleanOp);
21110 146412766 : Storage_DEALLOCATE ((void **) &f, sizeof (M2Quads__T2));
21111 146412766 : }
21112 :
21113 :
21114 : /*
21115 : PushTtok - Push an item onto the stack in the T (true) position,
21116 : it is assummed to be a token and its token location is recorded.
21117 : */
21118 :
21119 78853375 : extern "C" void M2Quads_PushTtok (unsigned int True, unsigned int tokno)
21120 : {
21121 78853375 : M2Quads_BoolFrame f;
21122 :
21123 : /* PrintTokenNo (tokno) ; */
21124 78853375 : f = newBoolFrame ();
21125 78853375 : f->TrueExit = static_cast<unsigned int> (True);
21126 78853375 : f->tokenno = tokno;
21127 78853375 : M2StackAddress_PushAddress (BoolStack, reinterpret_cast <void *> (f));
21128 78853375 : }
21129 :
21130 :
21131 : /*
21132 : PushTFtok - Push an item onto the stack in the T (true) position,
21133 : it is assummed to be a token and its token location is recorded.
21134 : */
21135 :
21136 157509383 : extern "C" void M2Quads_PushTFtok (unsigned int True, unsigned int False, unsigned int tokno)
21137 : {
21138 157509383 : M2Quads_BoolFrame f;
21139 :
21140 157509383 : f = newBoolFrame ();
21141 157509383 : f->TrueExit = static_cast<unsigned int> (True);
21142 157509383 : f->FalseExit = static_cast<unsigned int> (False);
21143 157509383 : f->tokenno = tokno;
21144 157509383 : M2StackAddress_PushAddress (BoolStack, reinterpret_cast <void *> (f));
21145 157509383 : }
21146 :
21147 :
21148 : /*
21149 : PopTFtok - Pop T/F/tok from the stack.
21150 : */
21151 :
21152 9521079 : extern "C" void M2Quads_PopTFtok (unsigned int *True, unsigned int *False, unsigned int *tokno)
21153 : {
21154 9521079 : M2Quads_BoolFrame f;
21155 :
21156 9521079 : f = static_cast<M2Quads_BoolFrame> (M2StackAddress_PopAddress (BoolStack));
21157 9521079 : (*True) = static_cast<unsigned int> (f->TrueExit);
21158 9521079 : (*False) = static_cast<unsigned int> (f->FalseExit);
21159 9521079 : (*tokno) = f->tokenno;
21160 9521079 : }
21161 :
21162 :
21163 : /*
21164 : PushTFAtok - Push T/F/A/tok to the stack.
21165 : */
21166 :
21167 54 : extern "C" void M2Quads_PushTFAtok (unsigned int True, unsigned int False, unsigned int Array, unsigned int tokno)
21168 : {
21169 54 : M2Quads_BoolFrame f;
21170 :
21171 54 : f = newBoolFrame ();
21172 54 : f->TrueExit = static_cast<unsigned int> (True);
21173 54 : f->FalseExit = static_cast<unsigned int> (False);
21174 54 : f->Unbounded = static_cast<unsigned int> (Array);
21175 54 : f->tokenno = tokno;
21176 54 : M2StackAddress_PushAddress (BoolStack, reinterpret_cast <void *> (f));
21177 54 : }
21178 :
21179 :
21180 : /*
21181 : PopTtok - Pops the T value from the stack and token position.
21182 : */
21183 :
21184 117890707 : extern "C" void M2Quads_PopTtok (unsigned int *True, unsigned int *tok)
21185 : {
21186 117890707 : M2Quads_BoolFrame f;
21187 :
21188 117890707 : f = static_cast<M2Quads_BoolFrame> (M2StackAddress_PopAddress (BoolStack));
21189 117890707 : (*True) = static_cast<unsigned int> (f->TrueExit);
21190 117890707 : (*tok) = f->tokenno;
21191 117890707 : M2Debug_Assert (! f->BooleanOp);
21192 117890707 : Storage_DEALLOCATE ((void **) &f, sizeof (M2Quads__T2));
21193 117890707 : }
21194 :
21195 :
21196 : /*
21197 : PushTFn - Push a True and False numbers onto the True/False stack.
21198 : True and False are assumed to contain Symbols or Ident etc.
21199 : */
21200 :
21201 0 : extern "C" void M2Quads_PushTFn (unsigned int True, unsigned int False, unsigned int n)
21202 : {
21203 0 : M2Quads_BoolFrame f;
21204 :
21205 0 : f = newBoolFrame ();
21206 0 : f->TrueExit = static_cast<unsigned int> (True);
21207 0 : f->FalseExit = static_cast<unsigned int> (False);
21208 0 : f->name = static_cast<unsigned int> (n);
21209 0 : M2StackAddress_PushAddress (BoolStack, reinterpret_cast <void *> (f));
21210 0 : }
21211 :
21212 :
21213 : /*
21214 : PushTFntok - Push a True and False numbers onto the True/False stack.
21215 : True and False are assumed to contain Symbols or Ident etc.
21216 : */
21217 :
21218 666251 : extern "C" void M2Quads_PushTFntok (unsigned int True, unsigned int False, unsigned int n, unsigned int tokno)
21219 : {
21220 666251 : M2Quads_BoolFrame f;
21221 :
21222 666251 : f = newBoolFrame ();
21223 666251 : f->TrueExit = static_cast<unsigned int> (True);
21224 666251 : f->FalseExit = static_cast<unsigned int> (False);
21225 666251 : f->name = static_cast<unsigned int> (n);
21226 666251 : f->tokenno = tokno;
21227 666251 : M2StackAddress_PushAddress (BoolStack, reinterpret_cast <void *> (f));
21228 666251 : }
21229 :
21230 :
21231 : /*
21232 : PopTFn - Pop a True and False number from the True/False stack.
21233 : True and False are assumed to contain Symbols or Ident etc.
21234 : */
21235 :
21236 0 : extern "C" void M2Quads_PopTFn (unsigned int *True, unsigned int *False, unsigned int *n)
21237 : {
21238 0 : M2Quads_BoolFrame f;
21239 :
21240 0 : f = static_cast<M2Quads_BoolFrame> (M2StackAddress_PopAddress (BoolStack));
21241 0 : (*True) = static_cast<unsigned int> (f->TrueExit);
21242 0 : (*False) = static_cast<unsigned int> (f->FalseExit);
21243 0 : (*n) = static_cast<unsigned int> (f->name);
21244 0 : M2Debug_Assert (! f->BooleanOp);
21245 0 : Storage_DEALLOCATE ((void **) &f, sizeof (M2Quads__T2));
21246 0 : }
21247 :
21248 :
21249 : /*
21250 : PopNothing - pops the top element on the boolean stack.
21251 : */
21252 :
21253 66611387 : extern "C" void M2Quads_PopNothing (void)
21254 : {
21255 66611387 : M2Quads_BoolFrame f;
21256 :
21257 66611387 : f = static_cast<M2Quads_BoolFrame> (M2StackAddress_PopAddress (BoolStack));
21258 66611387 : Storage_DEALLOCATE ((void **) &f, sizeof (M2Quads__T2));
21259 66611387 : }
21260 :
21261 :
21262 : /*
21263 : PopN - pops multiple elements from the BoolStack.
21264 : */
21265 :
21266 12788262 : extern "C" void M2Quads_PopN (unsigned int n)
21267 : {
21268 48464878 : while (n > 0)
21269 : {
21270 35676616 : M2Quads_PopNothing ();
21271 35676616 : n -= 1;
21272 : }
21273 12788262 : }
21274 :
21275 :
21276 : /*
21277 : PushTFA - Push True, False, Array, numbers onto the
21278 : True/False stack. True and False are assumed to
21279 : contain Symbols or Ident etc.
21280 : */
21281 :
21282 0 : extern "C" void M2Quads_PushTFA (unsigned int True, unsigned int False, unsigned int Array)
21283 : {
21284 0 : M2Quads_BoolFrame f;
21285 :
21286 0 : f = newBoolFrame ();
21287 0 : f->TrueExit = static_cast<unsigned int> (True);
21288 0 : f->FalseExit = static_cast<unsigned int> (False);
21289 0 : f->Unbounded = static_cast<unsigned int> (Array);
21290 0 : M2StackAddress_PushAddress (BoolStack, reinterpret_cast <void *> (f));
21291 0 : }
21292 :
21293 :
21294 : /*
21295 : OperandTok - returns the token associated with pos, on the stack.
21296 : */
21297 :
21298 57053235 : extern "C" unsigned int M2Quads_OperandTok (unsigned int pos)
21299 : {
21300 57053235 : M2Debug_Assert (! (IsBoolean (pos)));
21301 57053235 : return static_cast<unsigned int> (OperandTtok (pos));
21302 : /* static analysis guarentees a RETURN statement will be used before here. */
21303 : __builtin_unreachable ();
21304 : }
21305 :
21306 :
21307 : /*
21308 : OperandA - returns possible array symbol associated with the ident
21309 : operand stored on the boolean stack.
21310 : */
21311 :
21312 2266341 : extern "C" unsigned int M2Quads_OperandA (unsigned int pos)
21313 : {
21314 2266341 : M2Quads_BoolFrame f;
21315 :
21316 2266341 : M2Debug_Assert (pos > 0);
21317 2266341 : M2Debug_Assert (! (IsBoolean (pos)));
21318 2266341 : f = static_cast<M2Quads_BoolFrame> (M2StackAddress_PeepAddress (BoolStack, pos));
21319 2266341 : return static_cast<unsigned int> (f->Unbounded);
21320 : /* static analysis guarentees a RETURN statement will be used before here. */
21321 : __builtin_unreachable ();
21322 : }
21323 :
21324 :
21325 : /*
21326 : OperandAnno - returns the annotation string associated with the
21327 : position, n, on the stack.
21328 : */
21329 :
21330 0 : extern "C" DynamicStrings_String M2Quads_OperandAnno (unsigned int n)
21331 : {
21332 0 : M2Quads_BoolFrame f;
21333 :
21334 0 : f = static_cast<M2Quads_BoolFrame> (M2StackAddress_PeepAddress (BoolStack, n));
21335 0 : return f->Annotation;
21336 : /* static analysis guarentees a RETURN statement will be used before here. */
21337 : __builtin_unreachable ();
21338 : }
21339 :
21340 :
21341 : /*
21342 : Annotate - annotate the top of stack.
21343 : */
21344 :
21345 126176844 : extern "C" void M2Quads_Annotate (const char *a_, unsigned int _a_high)
21346 : {
21347 126176844 : M2Quads_BoolFrame f;
21348 126176844 : char a[_a_high+1];
21349 :
21350 : /* make a local copy of each unbounded array. */
21351 126176844 : memcpy (a, a_, _a_high+1);
21352 :
21353 0 : if ((DebugStackOn && M2Options_CompilerDebugging) && ((M2StackAddress_NoOfItemsInStackAddress (BoolStack)) > 0))
21354 : {
21355 0 : f = static_cast<M2Quads_BoolFrame> (M2StackAddress_PeepAddress (BoolStack, 1)); /* top of stack */
21356 0 : if (f->Annotation != NULL) /* top of stack */
21357 : {
21358 0 : f->Annotation = DynamicStrings_KillString (f->Annotation);
21359 : }
21360 0 : f->Annotation = DynamicStrings_InitString ((const char *) a, _a_high);
21361 : }
21362 126176844 : }
21363 :
21364 :
21365 : /*
21366 : DisplayStack - displays the compile time symbol stack.
21367 : */
21368 :
21369 20562167 : extern "C" void M2Quads_DisplayStack (void)
21370 : {
21371 20562167 : if (DebugStackOn && M2Options_CompilerDebugging)
21372 : {
21373 0 : M2DebugStack_DebugStack (M2StackAddress_NoOfItemsInStackAddress (BoolStack), (M2DebugStack_ProcedureWord) {(M2DebugStack_ProcedureWord_t) OperandTno}, (M2DebugStack_ProcedureWord) {(M2DebugStack_ProcedureWord_t) OperandFno}, (M2DebugStack_ProcedureWord) {(M2DebugStack_ProcedureWord_t) M2Quads_OperandA}, (M2DebugStack_ProcedureWord) {(M2DebugStack_ProcedureWord_t) OperandD}, (M2DebugStack_ProcedureWord) {(M2DebugStack_ProcedureWord_t) OperandRW}, (M2DebugStack_ProcedureWord) {(M2DebugStack_ProcedureWord_t) M2Quads_OperandTok}, (M2DebugStack_ProcedureString) {(M2DebugStack_ProcedureString_t) M2Quads_OperandAnno});
21374 : }
21375 20562167 : }
21376 :
21377 :
21378 : /*
21379 : Top - returns the no of items held in the stack.
21380 : */
21381 :
21382 91630811 : extern "C" unsigned int M2Quads_Top (void)
21383 : {
21384 91630811 : return M2StackAddress_NoOfItemsInStackAddress (BoolStack);
21385 : /* static analysis guarentees a RETURN statement will be used before here. */
21386 : __builtin_unreachable ();
21387 : }
21388 :
21389 :
21390 : /*
21391 : DupFrame - duplicate the top of stack and push the new frame.
21392 : */
21393 :
21394 0 : extern "C" void M2Quads_DupFrame (void)
21395 : {
21396 0 : M2Quads_BoolFrame f;
21397 0 : M2Quads_BoolFrame newf;
21398 :
21399 0 : f = static_cast<M2Quads_BoolFrame> (M2StackAddress_PopAddress (BoolStack));
21400 0 : M2StackAddress_PushAddress (BoolStack, reinterpret_cast <void *> (f));
21401 0 : newf = newBoolFrame ();
21402 0 : (*newf) = (*f);
21403 0 : M2StackAddress_PushAddress (BoolStack, reinterpret_cast <void *> (newf));
21404 0 : }
21405 :
21406 :
21407 : /*
21408 : WriteOperand - displays the operands name, symbol id and mode of addressing.
21409 : */
21410 :
21411 0 : extern "C" void M2Quads_WriteOperand (unsigned int Sym)
21412 : {
21413 0 : NameKey_Name n;
21414 :
21415 0 : if (Sym == SymbolTable_NulSym)
21416 : {
21417 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "<nulsym>", 8);
21418 : }
21419 : else
21420 : {
21421 0 : n = SymbolTable_GetSymName (Sym);
21422 0 : M2Printf_fprintf1 (M2LangDump_GetDumpFile (), (const char *) "%a", 2, (const unsigned char *) &n, (sizeof (n)-1));
21423 0 : if ((SymbolTable_IsVar (Sym)) || (SymbolTable_IsConst (Sym)))
21424 : {
21425 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "[", 1);
21426 0 : WriteMode (SymbolTable_GetMode (Sym));
21427 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "]", 1);
21428 : }
21429 0 : M2Printf_fprintf1 (M2LangDump_GetDumpFile (), (const char *) "(%d)", 4, (const unsigned char *) &Sym, (sizeof (Sym)-1));
21430 0 : if (SymbolConversion_GccKnowsAbout (Sym))
21431 : {
21432 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "[gcc]", 5);
21433 : }
21434 : }
21435 0 : }
21436 :
21437 :
21438 : /*
21439 : BeginVarient - begin a varient record.
21440 : */
21441 :
21442 3048 : extern "C" void M2Quads_BeginVarient (void)
21443 : {
21444 3048 : unsigned int r;
21445 3048 : unsigned int v;
21446 :
21447 3048 : r = GetRecordOrField ();
21448 6096 : M2Debug_Assert ((SymbolTable_IsRecord (r)) || (SymbolTable_IsFieldVarient (r)));
21449 3048 : v = GetRecordOrField ();
21450 3048 : M2Debug_Assert (SymbolTable_IsVarient (v));
21451 3048 : BuildRange (M2Range_InitCaseBounds (M2CaseList_PushCase (r, v, SymbolTable_NulSym)));
21452 3048 : }
21453 :
21454 :
21455 : /*
21456 : EndVarient - end a varient record.
21457 : */
21458 :
21459 3048 : extern "C" void M2Quads_EndVarient (void)
21460 : {
21461 3048 : M2CaseList_PopCase ();
21462 3048 : }
21463 :
21464 :
21465 : /*
21466 : ElseVarient - associate an ELSE clause with a varient record.
21467 : */
21468 :
21469 114 : extern "C" void M2Quads_ElseVarient (void)
21470 : {
21471 114 : unsigned int f;
21472 :
21473 114 : f = GetRecordOrField ();
21474 114 : M2Debug_Assert (SymbolTable_IsFieldVarient (f));
21475 114 : M2CaseList_ElseCase (f);
21476 114 : }
21477 :
21478 :
21479 : /*
21480 : BeginVarientList - begin an ident list containing ranges belonging to a
21481 : varient list.
21482 : */
21483 :
21484 6096 : extern "C" void M2Quads_BeginVarientList (void)
21485 : {
21486 6096 : unsigned int f;
21487 :
21488 6096 : f = GetRecordOrField ();
21489 6096 : M2Debug_Assert (SymbolTable_IsFieldVarient (f));
21490 6096 : M2CaseList_BeginCaseList (f);
21491 6096 : }
21492 :
21493 :
21494 : /*
21495 : EndVarientList - end a range list for a varient field.
21496 : */
21497 :
21498 6096 : extern "C" void M2Quads_EndVarientList (void)
21499 : {
21500 6096 : M2CaseList_EndCaseList ();
21501 6096 : }
21502 :
21503 :
21504 : /*
21505 : AddRecordToList - adds the record held on the top of stack to the
21506 : list of records and varient fields.
21507 : */
21508 :
21509 3048 : extern "C" void M2Quads_AddRecordToList (void)
21510 : {
21511 3048 : unsigned int r;
21512 3048 : unsigned int n;
21513 :
21514 3048 : r = static_cast<unsigned int> (M2Quads_OperandT (1));
21515 6096 : M2Debug_Assert ((SymbolTable_IsRecord (r)) || (SymbolTable_IsFieldVarient (r)));
21516 : /*
21517 : r might be a field varient if the declaration consists of nested
21518 : varients. However ISO TSIZE can only utilise record types, we store
21519 : a varient field anyway as the next pass would not know whether to
21520 : ignore a varient field.
21521 : */
21522 3048 : Lists_PutItemIntoList (VarientFields, r);
21523 3048 : if (DebugVarients)
21524 : {
21525 : n = Lists_NoOfItemsInList (VarientFields);
21526 : if (SymbolTable_IsRecord (r))
21527 : {
21528 : M2Printf_printf2 ((const char *) "in list: record %d is %d\\n", 26, (const unsigned char *) &n, (sizeof (n)-1), (const unsigned char *) &r, (sizeof (r)-1));
21529 : }
21530 : else
21531 : {
21532 : M2Printf_printf2 ((const char *) "in list: varient field %d is %d\\n", 33, (const unsigned char *) &n, (sizeof (n)-1), (const unsigned char *) &r, (sizeof (r)-1));
21533 : }
21534 : }
21535 3048 : }
21536 :
21537 :
21538 : /*
21539 : AddVarientToList - adds varient held on the top of stack to the list.
21540 : */
21541 :
21542 3048 : extern "C" void M2Quads_AddVarientToList (void)
21543 : {
21544 3048 : unsigned int v;
21545 3048 : unsigned int n;
21546 :
21547 3048 : v = static_cast<unsigned int> (M2Quads_OperandT (1));
21548 3048 : M2Debug_Assert (SymbolTable_IsVarient (v));
21549 3048 : Lists_PutItemIntoList (VarientFields, v);
21550 3048 : if (DebugVarients)
21551 : {
21552 : n = Lists_NoOfItemsInList (VarientFields);
21553 : M2Printf_printf2 ((const char *) "in list: varient %d is %d\\n", 27, (const unsigned char *) &n, (sizeof (n)-1), (const unsigned char *) &v, (sizeof (v)-1));
21554 : }
21555 3048 : }
21556 :
21557 :
21558 : /*
21559 : AddVarientFieldToList - adds varient field, f, to the list of all varient
21560 : fields created.
21561 : */
21562 :
21563 6210 : extern "C" void M2Quads_AddVarientFieldToList (unsigned int f)
21564 : {
21565 6210 : unsigned int n;
21566 :
21567 6210 : M2Debug_Assert (SymbolTable_IsFieldVarient (f));
21568 6210 : Lists_PutItemIntoList (VarientFields, f);
21569 6210 : if (DebugVarients)
21570 : {
21571 : n = Lists_NoOfItemsInList (VarientFields);
21572 : M2Printf_printf2 ((const char *) "in list: varient field %d is %d\\n", 33, (const unsigned char *) &n, (sizeof (n)-1), (const unsigned char *) &f, (sizeof (f)-1));
21573 : }
21574 6210 : }
21575 :
21576 :
21577 : /*
21578 : AddVarientRange - creates a range from the top two contant expressions
21579 : on the stack which are recorded with the current
21580 : varient field. The stack is unaltered.
21581 : */
21582 :
21583 0 : extern "C" void M2Quads_AddVarientRange (void)
21584 : {
21585 0 : unsigned int r1;
21586 0 : unsigned int r2;
21587 :
21588 0 : M2Quads_PopT (&r2);
21589 0 : M2Quads_PopT (&r1);
21590 0 : M2CaseList_AddRange (r1, r2, M2LexBuf_GetTokenNo ());
21591 0 : }
21592 :
21593 :
21594 : /*
21595 : AddVarientEquality - adds the contant expression on the top of the stack
21596 : to the current varient field being recorded.
21597 : The stack is unaltered.
21598 : */
21599 :
21600 6138 : extern "C" void M2Quads_AddVarientEquality (void)
21601 : {
21602 6138 : unsigned int r1;
21603 :
21604 6138 : M2Quads_PopT (&r1);
21605 6138 : M2CaseList_AddRange (r1, SymbolTable_NulSym, M2LexBuf_GetTokenNo ());
21606 6138 : }
21607 :
21608 :
21609 : /*
21610 : BuildCodeOn - generates a quadruple declaring that code should be
21611 : emmitted from henceforth.
21612 :
21613 : The Stack is unnaffected.
21614 : */
21615 :
21616 0 : extern "C" void M2Quads_BuildCodeOn (void)
21617 : {
21618 0 : GenQuad (M2Quads_CodeOnOp, SymbolTable_NulSym, SymbolTable_NulSym, SymbolTable_NulSym);
21619 0 : }
21620 :
21621 :
21622 : /*
21623 : BuildCodeOff - generates a quadruple declaring that code should not be
21624 : emmitted from henceforth.
21625 :
21626 : The Stack is unnaffected.
21627 : */
21628 :
21629 0 : extern "C" void M2Quads_BuildCodeOff (void)
21630 : {
21631 0 : GenQuad (M2Quads_CodeOffOp, SymbolTable_NulSym, SymbolTable_NulSym, SymbolTable_NulSym);
21632 0 : }
21633 :
21634 :
21635 : /*
21636 : BuildProfileOn - generates a quadruple declaring that profile timings
21637 : should be emmitted from henceforth.
21638 :
21639 : The Stack is unnaffected.
21640 : */
21641 :
21642 0 : extern "C" void M2Quads_BuildProfileOn (void)
21643 : {
21644 0 : GenQuad (M2Quads_ProfileOnOp, SymbolTable_NulSym, SymbolTable_NulSym, SymbolTable_NulSym);
21645 0 : }
21646 :
21647 0 : extern "C" void M2Quads_BuildProfileOff (void)
21648 : {
21649 : /*
21650 : BuildProfileOn - generates a quadruple declaring that profile timings
21651 : should be emmitted from henceforth.
21652 :
21653 : The Stack is unnaffected.
21654 : */
21655 0 : GenQuad (M2Quads_ProfileOffOp, SymbolTable_NulSym, SymbolTable_NulSym, SymbolTable_NulSym);
21656 0 : }
21657 :
21658 :
21659 : /*
21660 : BuildOptimizeOn - generates a quadruple declaring that optimization
21661 : should occur from henceforth.
21662 :
21663 : The Stack is unnaffected.
21664 : */
21665 :
21666 0 : extern "C" void M2Quads_BuildOptimizeOn (void)
21667 : {
21668 0 : GenQuad (M2Quads_OptimizeOnOp, SymbolTable_NulSym, SymbolTable_NulSym, SymbolTable_NulSym);
21669 0 : }
21670 :
21671 :
21672 : /*
21673 : BuildOptimizeOff - generates a quadruple declaring that optimization
21674 : should not occur from henceforth.
21675 :
21676 : The Stack is unnaffected.
21677 : */
21678 :
21679 0 : extern "C" void M2Quads_BuildOptimizeOff (void)
21680 : {
21681 0 : GenQuad (M2Quads_OptimizeOffOp, SymbolTable_NulSym, SymbolTable_NulSym, SymbolTable_NulSym);
21682 0 : }
21683 :
21684 :
21685 : /*
21686 : BuildAsm - builds an Inline pseudo quadruple operator.
21687 : The inline interface, Sym, is stored as the operand
21688 : to the operator InlineOp.
21689 :
21690 : The stack is expected to contain:
21691 :
21692 :
21693 : Entry Exit
21694 : ===== ====
21695 :
21696 : Ptr ->
21697 : +--------------+
21698 : | Sym | Empty
21699 : |--------------|
21700 : */
21701 :
21702 27 : extern "C" void M2Quads_BuildAsm (unsigned int tok)
21703 : {
21704 27 : unsigned int Sym;
21705 :
21706 27 : M2Quads_PopT (&Sym);
21707 27 : GenQuadO (tok, M2Quads_InlineOp, SymbolTable_NulSym, SymbolTable_NulSym, Sym, false);
21708 27 : }
21709 :
21710 :
21711 : /*
21712 : BuildLineNo - builds a LineNumberOp pseudo quadruple operator.
21713 : This quadruple indicates which source line has been
21714 : processed, these quadruples are only generated if we
21715 : are producing runtime debugging information.
21716 :
21717 : The stack is not affected, read or altered in any way.
21718 :
21719 :
21720 : Entry Exit
21721 : ===== ====
21722 :
21723 : Ptr -> <- Ptr
21724 : */
21725 :
21726 0 : extern "C" void M2Quads_BuildLineNo (void)
21727 : {
21728 0 : NameKey_Name filename;
21729 0 : M2Quads_QuadFrame f;
21730 :
21731 0 : if (((NextQuad != Head) && (M2Options_GenerateLineDebug || M2Options_GenerateDebugging)) && false)
21732 : {
21733 : filename = NameKey_makekey (DynamicStrings_string (M2LexBuf_GetFileName ()));
21734 : f = GetQF (NextQuad-1);
21735 : if (! ((f->Operator == M2Quads_LineNumberOp) && (f->Operand1 == ((unsigned int ) (filename)))))
21736 : {
21737 : GenQuad (M2Quads_LineNumberOp, (unsigned int ) (filename), SymbolTable_NulSym, (unsigned int ) (M2LexBuf_GetLineNo ()));
21738 : }
21739 : }
21740 0 : }
21741 :
21742 :
21743 : /*
21744 : PushLineNo - pushes the current file and line number to the stack.
21745 : */
21746 :
21747 5220 : extern "C" void M2Quads_PushLineNo (void)
21748 : {
21749 5220 : PushLineNote (InitLineNote (NameKey_makekey (DynamicStrings_string (M2LexBuf_GetFileName ())), M2LexBuf_GetLineNo ()));
21750 5220 : }
21751 :
21752 :
21753 : /*
21754 : BuildStmtNote - builds a StatementNoteOp pseudo quadruple operator.
21755 : This quadruple indicates which source line has been
21756 : processed and it represents the start of a statement
21757 : sequence.
21758 : It differs from LineNumberOp in that multiple successive
21759 : LineNumberOps will be removed and the final one is attached to
21760 : the next real GCC tree. Whereas a StatementNoteOp is always left
21761 : alone. Depending upon the debugging level it will issue a nop
21762 : instruction to ensure that the gdb single step will step into
21763 : this line. Practically it allows pedalogical debugging to
21764 : occur when there is syntax sugar such as:
21765 :
21766 :
21767 : END step
21768 : END step
21769 : END ; step
21770 : a := 1 ; step
21771 :
21772 : REPEAT step
21773 : i := 1 step
21774 :
21775 : The stack is not affected, read or altered in any way.
21776 :
21777 :
21778 : Entry Exit
21779 : ===== ====
21780 :
21781 : Ptr -> <- Ptr
21782 : */
21783 :
21784 545218 : extern "C" void M2Quads_BuildStmtNote (int offset)
21785 : {
21786 545218 : int tokenno;
21787 :
21788 545218 : if (NextQuad != Head)
21789 : {
21790 545218 : tokenno = offset;
21791 545218 : tokenno += M2LexBuf_GetTokenNo ();
21792 545218 : BuildStmtNoteTok ((unsigned int ) (tokenno));
21793 : }
21794 545218 : }
21795 :
21796 :
21797 : /*
21798 : LoopAnalysis - checks whether an infinite loop exists.
21799 : */
21800 :
21801 410599 : extern "C" void M2Quads_LoopAnalysis (unsigned int Scope, unsigned int Current, unsigned int End)
21802 : {
21803 410599 : M2Quads_QuadOperator op;
21804 410599 : unsigned int op1;
21805 410599 : unsigned int op2;
21806 410599 : unsigned int op3;
21807 :
21808 410599 : if (M2Options_Pedantic)
21809 : {
21810 11442 : while ((Current <= End) && (Current != 0))
21811 : {
21812 9990 : M2Quads_GetQuad (Current, &op, &op1, &op2, &op3);
21813 9990 : if ((op == M2Quads_GotoOp) || (M2Quads_IsConditional (Current)))
21814 : {
21815 114 : if (op3 <= Current)
21816 : {
21817 : /* found a loop - ie a branch which goes back in quadruple numbers */
21818 24 : if (IsInfiniteLoop (Current))
21819 : {
21820 0 : M2MetaError_MetaErrorT1 (M2Quads_QuadToTokenNo (op3), (const char *) "it is very likely (although not absolutely certain) that the top of an infinite loop exists here in {%1Wad}", 107, Scope);
21821 0 : M2MetaError_MetaErrorT1 (M2Quads_QuadToTokenNo (Current), (const char *) "and the bottom of the infinite loop is ends here in {%1Wad} or alternatively a component of this loop is never executed", 119, Scope);
21822 : }
21823 : /*
21824 : WarnStringAt(InitString('it is very likely (although not absolutely certain) that the top of an infinite loop is here'),
21825 : QuadToTokenNo(op3)) ;
21826 : WarnStringAt(InitString('and the bottom of the infinite loop is ends here or alternatively a component of this loop is never executed'),
21827 : QuadToTokenNo(Current))
21828 : */
21829 : }
21830 : }
21831 9990 : Current = M2Quads_GetNextQuad (Current);
21832 : }
21833 : }
21834 410599 : }
21835 :
21836 :
21837 : /*
21838 : ForLoopAnalysis - checks all the FOR loops for index variable manipulation
21839 : and dangerous usage outside the loop.
21840 : */
21841 :
21842 14662 : extern "C" void M2Quads_ForLoopAnalysis (void)
21843 : {
21844 14662 : unsigned int i;
21845 14662 : unsigned int n;
21846 14662 : M2Quads_ForLoopInfo forDesc;
21847 :
21848 14662 : if (M2Options_Pedantic)
21849 : {
21850 108 : n = Indexing_HighIndice (ForInfo);
21851 108 : i = 1;
21852 216 : while (i <= n)
21853 : {
21854 0 : forDesc = static_cast<M2Quads_ForLoopInfo> (Indexing_GetIndice (ForInfo, i));
21855 0 : CheckForIndex (forDesc);
21856 0 : i += 1;
21857 : }
21858 : }
21859 14662 : }
21860 :
21861 :
21862 : /*
21863 : BuildSizeCheckStart - switches off all quadruple generation if the function SIZE or HIGH
21864 : is being "called". This should be done as SIZE only requires the
21865 : actual type of the expression, not its value. Consider the problem of
21866 : SIZE(UninitializedPointer^) which is quite legal and it must
21867 : also be safe!
21868 : ISO Modula-2 also allows HIGH(a[0]) for a two dimensional array
21869 : and there is no need to compute a[0], we just need to follow the
21870 : type and count dimensions. However if SIZE(a) or HIGH(a) occurs
21871 : and, a, is an unbounded array then we turn on quadruple generation.
21872 :
21873 : The Stack is expected to contain:
21874 :
21875 :
21876 : Entry Exit
21877 : ===== ====
21878 :
21879 : Ptr -> <- Ptr
21880 : +----------------------+ +----------------------+
21881 : | ProcSym | Type | tok | | ProcSym | Type | tok |
21882 : |----------------------| |----------------------|
21883 : */
21884 :
21885 192720 : extern "C" void M2Quads_BuildSizeCheckStart (void)
21886 : {
21887 192720 : unsigned int ProcSym;
21888 192720 : unsigned int Type;
21889 192720 : unsigned int tok;
21890 :
21891 192720 : M2Quads_PopTFtok (&ProcSym, &Type, &tok);
21892 192720 : if (((ProcSym == M2Size_Size) || (ProcSym == M2System_TSize)) || (ProcSym == M2System_TBitSize))
21893 : {
21894 9235 : QuadrupleGeneration = false;
21895 9235 : BuildingSize = true;
21896 : }
21897 183485 : else if (ProcSym == M2Base_High)
21898 : {
21899 : /* avoid dangling else. */
21900 2978 : QuadrupleGeneration = false;
21901 2978 : BuildingHigh = true;
21902 : }
21903 192720 : M2Quads_PushTFtok (ProcSym, Type, tok);
21904 192720 : }
21905 :
21906 :
21907 : /*
21908 : BackPatchSubrangesAndOptParam - runs through all the quadruples and finds SubrangeLow or SubrangeHigh
21909 : quadruples and replaces it by an assignment to the Low or High component
21910 : of the subrange type.
21911 :
21912 : Input:
21913 : SubrangeLow op1 op3 op3 is a subrange
21914 :
21915 : Output:
21916 : Becomes op1 low
21917 :
21918 : Input:
21919 : SubrangeHigh op1 op3 op3 is a subrange
21920 :
21921 : Output:
21922 : Becomes op1 high
21923 :
21924 : Input:
21925 : OptParam op1 op2 op3
21926 :
21927 : Output:
21928 : Param op1 op2 GetOptArgInit(op3)
21929 : */
21930 :
21931 14662 : extern "C" void M2Quads_BackPatchSubrangesAndOptParam (void)
21932 : {
21933 14662 : M2Quads_QuadFrame f;
21934 14662 : unsigned int q;
21935 :
21936 14662 : q = M2Quads_GetFirstQuad ();
21937 14662 : if (q != 0)
21938 : {
21939 6259579 : do {
21940 6259579 : f = GetQF (q);
21941 6259579 : switch (f->Operator)
21942 : {
21943 306 : case M2Quads_SubrangeLowOp:
21944 306 : f->Operand3 = CollectLow (f->Operand3);
21945 306 : f->Operator = M2Quads_BecomesOp;
21946 306 : f->ConstExpr = false;
21947 306 : break;
21948 :
21949 562 : case M2Quads_SubrangeHighOp:
21950 562 : f->Operand3 = CollectHigh (f->Operand3);
21951 562 : f->Operator = M2Quads_BecomesOp;
21952 562 : f->ConstExpr = false;
21953 562 : break;
21954 :
21955 3626 : case M2Quads_OptParamOp:
21956 3626 : f->Operand3 = SymbolTable_GetOptArgInit (f->Operand3);
21957 3626 : f->Operator = M2Quads_ParamOp;
21958 3626 : break;
21959 :
21960 :
21961 : default:
21962 : break;
21963 : }
21964 6259579 : q = f->Next;
21965 6259579 : } while (! (q == 0));
21966 : }
21967 14662 : }
21968 :
21969 :
21970 : /*
21971 : WriteOperator - writes the name of the quadruple operator.
21972 : */
21973 :
21974 0 : extern "C" void M2Quads_WriteOperator (M2Quads_QuadOperator Operator)
21975 : {
21976 0 : switch (Operator)
21977 : {
21978 0 : case M2Quads_ArithAddOp:
21979 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "Arith + ", 18);
21980 0 : break;
21981 :
21982 0 : case M2Quads_InitAddressOp:
21983 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "InitAddress ", 18);
21984 0 : break;
21985 :
21986 0 : case M2Quads_LastForIteratorOp:
21987 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "LastForIterator ", 18);
21988 0 : break;
21989 :
21990 0 : case M2Quads_LogicalOrOp:
21991 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "Or ", 18);
21992 0 : break;
21993 :
21994 0 : case M2Quads_LogicalAndOp:
21995 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "And ", 18);
21996 0 : break;
21997 :
21998 0 : case M2Quads_LogicalXorOp:
21999 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "Xor ", 18);
22000 0 : break;
22001 :
22002 0 : case M2Quads_LogicalDiffOp:
22003 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "Ldiff ", 18);
22004 0 : break;
22005 :
22006 0 : case M2Quads_LogicalShiftOp:
22007 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "Shift ", 18);
22008 0 : break;
22009 :
22010 0 : case M2Quads_LogicalRotateOp:
22011 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "Rotate ", 18);
22012 0 : break;
22013 :
22014 0 : case M2Quads_BecomesOp:
22015 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "Becomes ", 18);
22016 0 : break;
22017 :
22018 0 : case M2Quads_IndrXOp:
22019 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "IndrX ", 18);
22020 0 : break;
22021 :
22022 0 : case M2Quads_XIndrOp:
22023 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "XIndr ", 18);
22024 0 : break;
22025 :
22026 0 : case M2Quads_ArrayOp:
22027 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "Array ", 18);
22028 0 : break;
22029 :
22030 0 : case M2Quads_ElementSizeOp:
22031 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "ElementSize ", 18);
22032 0 : break;
22033 :
22034 0 : case M2Quads_RecordFieldOp:
22035 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "RecordField ", 18);
22036 0 : break;
22037 :
22038 0 : case M2Quads_AddrOp:
22039 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "Addr ", 18);
22040 0 : break;
22041 :
22042 0 : case M2Quads_SizeOp:
22043 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "Size ", 18);
22044 0 : break;
22045 :
22046 0 : case M2Quads_IfInOp:
22047 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "If IN ", 18);
22048 0 : break;
22049 :
22050 0 : case M2Quads_IfNotInOp:
22051 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "If NOT IN ", 18);
22052 0 : break;
22053 :
22054 0 : case M2Quads_IfNotEquOp:
22055 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "If <> ", 18);
22056 0 : break;
22057 :
22058 0 : case M2Quads_IfEquOp:
22059 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "If = ", 18);
22060 0 : break;
22061 :
22062 0 : case M2Quads_IfLessEquOp:
22063 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "If <= ", 18);
22064 0 : break;
22065 :
22066 0 : case M2Quads_IfGreEquOp:
22067 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "If >= ", 18);
22068 0 : break;
22069 :
22070 0 : case M2Quads_IfGreOp:
22071 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "If > ", 18);
22072 0 : break;
22073 :
22074 0 : case M2Quads_IfLessOp:
22075 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "If < ", 18);
22076 0 : break;
22077 :
22078 0 : case M2Quads_GotoOp:
22079 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "Goto ", 18);
22080 0 : break;
22081 :
22082 0 : case M2Quads_DummyOp:
22083 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "Dummy ", 18);
22084 0 : break;
22085 :
22086 0 : case M2Quads_ModuleScopeOp:
22087 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "ModuleScopeOp ", 18);
22088 0 : break;
22089 :
22090 0 : case M2Quads_StartDefFileOp:
22091 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "StartDefFile ", 18);
22092 0 : break;
22093 :
22094 0 : case M2Quads_StartModFileOp:
22095 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "StartModFile ", 18);
22096 0 : break;
22097 :
22098 0 : case M2Quads_EndFileOp:
22099 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "EndFileOp ", 18);
22100 0 : break;
22101 :
22102 0 : case M2Quads_InitStartOp:
22103 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "InitStart ", 18);
22104 0 : break;
22105 :
22106 0 : case M2Quads_InitEndOp:
22107 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "InitEnd ", 18);
22108 0 : break;
22109 :
22110 0 : case M2Quads_FinallyStartOp:
22111 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "FinallyStart ", 18);
22112 0 : break;
22113 :
22114 0 : case M2Quads_FinallyEndOp:
22115 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "FinallyEnd ", 18);
22116 0 : break;
22117 :
22118 0 : case M2Quads_RetryOp:
22119 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "Retry ", 18);
22120 0 : break;
22121 :
22122 0 : case M2Quads_TryOp:
22123 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "Try ", 18);
22124 0 : break;
22125 :
22126 0 : case M2Quads_ThrowOp:
22127 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "Throw ", 18);
22128 0 : break;
22129 :
22130 0 : case M2Quads_CatchBeginOp:
22131 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "CatchBegin ", 18);
22132 0 : break;
22133 :
22134 0 : case M2Quads_CatchEndOp:
22135 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "CatchEnd ", 18);
22136 0 : break;
22137 :
22138 0 : case M2Quads_AddOp:
22139 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "+ ", 18);
22140 0 : break;
22141 :
22142 0 : case M2Quads_SubOp:
22143 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "- ", 18);
22144 0 : break;
22145 :
22146 0 : case M2Quads_DivM2Op:
22147 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "DIV M2 ", 18);
22148 0 : break;
22149 :
22150 0 : case M2Quads_ModM2Op:
22151 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "MOD M2 ", 18);
22152 0 : break;
22153 :
22154 0 : case M2Quads_DivCeilOp:
22155 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "DIV ceil ", 18);
22156 0 : break;
22157 :
22158 0 : case M2Quads_ModCeilOp:
22159 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "MOD ceil ", 18);
22160 0 : break;
22161 :
22162 0 : case M2Quads_DivFloorOp:
22163 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "DIV floor ", 18);
22164 0 : break;
22165 :
22166 0 : case M2Quads_ModFloorOp:
22167 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "MOD floor ", 18);
22168 0 : break;
22169 :
22170 0 : case M2Quads_DivTruncOp:
22171 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "DIV trunc ", 18);
22172 0 : break;
22173 :
22174 0 : case M2Quads_ModTruncOp:
22175 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "MOD trunc ", 18);
22176 0 : break;
22177 :
22178 0 : case M2Quads_MultOp:
22179 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "* ", 18);
22180 0 : break;
22181 :
22182 0 : case M2Quads_NegateOp:
22183 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "Negate ", 18);
22184 0 : break;
22185 :
22186 0 : case M2Quads_InclOp:
22187 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "Incl ", 18);
22188 0 : break;
22189 :
22190 0 : case M2Quads_ExclOp:
22191 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "Excl ", 18);
22192 0 : break;
22193 :
22194 0 : case M2Quads_ReturnOp:
22195 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "Return ", 18);
22196 0 : break;
22197 :
22198 0 : case M2Quads_ReturnValueOp:
22199 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "ReturnValue ", 18);
22200 0 : break;
22201 :
22202 0 : case M2Quads_FunctValueOp:
22203 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "FunctValue ", 18);
22204 0 : break;
22205 :
22206 0 : case M2Quads_CallOp:
22207 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "Call ", 18);
22208 0 : break;
22209 :
22210 0 : case M2Quads_ParamOp:
22211 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "Param ", 18);
22212 0 : break;
22213 :
22214 0 : case M2Quads_OptParamOp:
22215 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "OptParam ", 18);
22216 0 : break;
22217 :
22218 0 : case M2Quads_NewLocalVarOp:
22219 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "NewLocalVar ", 18);
22220 0 : break;
22221 :
22222 0 : case M2Quads_KillLocalVarOp:
22223 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "KillLocalVar ", 18);
22224 0 : break;
22225 :
22226 0 : case M2Quads_ProcedureScopeOp:
22227 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "ProcedureScope ", 18);
22228 0 : break;
22229 :
22230 0 : case M2Quads_UnboundedOp:
22231 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "Unbounded ", 18);
22232 0 : break;
22233 :
22234 0 : case M2Quads_CoerceOp:
22235 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "Coerce ", 18);
22236 0 : break;
22237 :
22238 0 : case M2Quads_ConvertOp:
22239 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "Convert ", 18);
22240 0 : break;
22241 :
22242 0 : case M2Quads_CastOp:
22243 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "Cast ", 18);
22244 0 : break;
22245 :
22246 0 : case M2Quads_HighOp:
22247 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "High ", 18);
22248 0 : break;
22249 :
22250 0 : case M2Quads_CodeOnOp:
22251 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "CodeOn ", 18);
22252 0 : break;
22253 :
22254 0 : case M2Quads_CodeOffOp:
22255 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "CodeOff ", 18);
22256 0 : break;
22257 :
22258 0 : case M2Quads_ProfileOnOp:
22259 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "ProfileOn ", 18);
22260 0 : break;
22261 :
22262 0 : case M2Quads_ProfileOffOp:
22263 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "ProfileOff ", 18);
22264 0 : break;
22265 :
22266 0 : case M2Quads_OptimizeOnOp:
22267 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "OptimizeOn ", 18);
22268 0 : break;
22269 :
22270 0 : case M2Quads_OptimizeOffOp:
22271 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "OptimizeOff ", 18);
22272 0 : break;
22273 :
22274 0 : case M2Quads_InlineOp:
22275 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "Inline ", 18);
22276 0 : break;
22277 :
22278 0 : case M2Quads_StatementNoteOp:
22279 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "StatementNote ", 18);
22280 0 : break;
22281 :
22282 0 : case M2Quads_LineNumberOp:
22283 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "LineNumber ", 18);
22284 0 : break;
22285 :
22286 0 : case M2Quads_BuiltinConstOp:
22287 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "BuiltinConst ", 18);
22288 0 : break;
22289 :
22290 0 : case M2Quads_BuiltinTypeInfoOp:
22291 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "BuiltinTypeInfo ", 18);
22292 0 : break;
22293 :
22294 0 : case M2Quads_StandardFunctionOp:
22295 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "StandardFunction ", 18);
22296 0 : break;
22297 :
22298 0 : case M2Quads_SavePriorityOp:
22299 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "SavePriority ", 18);
22300 0 : break;
22301 :
22302 0 : case M2Quads_RestorePriorityOp:
22303 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "RestorePriority ", 18);
22304 0 : break;
22305 :
22306 0 : case M2Quads_RangeCheckOp:
22307 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "RangeCheck ", 18);
22308 0 : break;
22309 :
22310 0 : case M2Quads_ErrorOp:
22311 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "Error ", 18);
22312 0 : break;
22313 :
22314 0 : case M2Quads_SaveExceptionOp:
22315 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "SaveException ", 18);
22316 0 : break;
22317 :
22318 0 : case M2Quads_RestoreExceptionOp:
22319 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "RestoreException ", 18);
22320 0 : break;
22321 :
22322 0 : case M2Quads_StringConvertCnulOp:
22323 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "StringConvertCnul ", 18);
22324 0 : break;
22325 :
22326 0 : case M2Quads_StringConvertM2nulOp:
22327 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "StringConvertM2nul", 18);
22328 0 : break;
22329 :
22330 0 : case M2Quads_StringLengthOp:
22331 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "StringLength ", 18);
22332 0 : break;
22333 :
22334 0 : case M2Quads_SubrangeHighOp:
22335 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "SubrangeHigh ", 18);
22336 0 : break;
22337 :
22338 0 : case M2Quads_SubrangeLowOp:
22339 0 : M2Printf_fprintf0 (M2LangDump_GetDumpFile (), (const char *) "SubrangeLow ", 18);
22340 0 : break;
22341 :
22342 :
22343 0 : default:
22344 0 : M2Error_InternalError ((const char *) "operator not expected", 21);
22345 0 : break;
22346 : }
22347 0 : }
22348 :
22349 :
22350 : /*
22351 : PushAutoOn - push the auto flag and then set it to TRUE.
22352 : Any call to ident in the parser will result in the token being pushed.
22353 : */
22354 :
22355 64160209 : extern "C" void M2Quads_PushAutoOn (void)
22356 : {
22357 64160209 : M2StackWord_PushWord (AutoStack, static_cast<unsigned int> (IsAutoOn));
22358 64160209 : IsAutoOn = true;
22359 64160209 : }
22360 :
22361 :
22362 : /*
22363 : PushAutoOff - push the auto flag and then set it to FALSE.
22364 : */
22365 :
22366 120049063 : extern "C" void M2Quads_PushAutoOff (void)
22367 : {
22368 120049063 : M2StackWord_PushWord (AutoStack, static_cast<unsigned int> (IsAutoOn));
22369 120049063 : IsAutoOn = false;
22370 120049063 : }
22371 :
22372 :
22373 : /*
22374 : IsAutoPushOn - returns the value of the current Auto ident push flag.
22375 : */
22376 :
22377 574374050 : extern "C" bool M2Quads_IsAutoPushOn (void)
22378 : {
22379 574374050 : return IsAutoOn;
22380 : /* static analysis guarentees a RETURN statement will be used before here. */
22381 : __builtin_unreachable ();
22382 : }
22383 :
22384 :
22385 : /*
22386 : PopAuto - restores the previous value of the Auto flag.
22387 : */
22388 :
22389 184184494 : extern "C" void M2Quads_PopAuto (void)
22390 : {
22391 184184494 : IsAutoOn = static_cast<bool> (M2StackWord_PopWord (AutoStack));
22392 184184494 : }
22393 :
22394 :
22395 : /*
22396 : MustCheckOverflow - returns TRUE if the quadruple should test for overflow.
22397 : */
22398 :
22399 544051 : extern "C" bool M2Quads_MustCheckOverflow (unsigned int q)
22400 : {
22401 544051 : M2Quads_QuadFrame f;
22402 :
22403 544051 : f = GetQF (q);
22404 544051 : return f->CheckOverflow;
22405 : /* static analysis guarentees a RETURN statement will be used before here. */
22406 : __builtin_unreachable ();
22407 : }
22408 :
22409 :
22410 : /*
22411 : PushInConstExpression - push the InConstExpression flag and then set it to TRUE.
22412 : */
22413 :
22414 1253896 : extern "C" void M2Quads_PushInConstExpression (void)
22415 : {
22416 1253896 : M2StackWord_PushWord (ConstExprStack, static_cast<unsigned int> (InConstExpression));
22417 1253896 : InConstExpression = true;
22418 1253896 : }
22419 :
22420 :
22421 : /*
22422 : PopInConstExpression - restores the previous value of the InConstExpression.
22423 : */
22424 :
22425 1253872 : extern "C" void M2Quads_PopInConstExpression (void)
22426 : {
22427 1253872 : InConstExpression = static_cast<bool> (M2StackWord_PopWord (ConstExprStack));
22428 1253872 : }
22429 :
22430 :
22431 : /*
22432 : IsInConstExpression - returns the value of the InConstExpression.
22433 : */
22434 :
22435 99674 : extern "C" bool M2Quads_IsInConstExpression (void)
22436 : {
22437 99674 : return InConstExpression;
22438 : /* static analysis guarentees a RETURN statement will be used before here. */
22439 : __builtin_unreachable ();
22440 : }
22441 :
22442 :
22443 : /*
22444 : PushInConstParameters - push the InConstParameters flag and then set it to TRUE.
22445 : */
22446 :
22447 1726 : extern "C" void M2Quads_PushInConstParameters (void)
22448 : {
22449 1726 : M2StackWord_PushWord (ConstParamStack, static_cast<unsigned int> (InConstParameters));
22450 1726 : InConstParameters = true;
22451 1726 : }
22452 :
22453 :
22454 : /*
22455 : PopInConstParameters - restores the previous value of the InConstParameters.
22456 : */
22457 :
22458 1726 : extern "C" void M2Quads_PopInConstParameters (void)
22459 : {
22460 1726 : InConstParameters = static_cast<bool> (M2StackWord_PopWord (ConstParamStack));
22461 1726 : }
22462 :
22463 :
22464 : /*
22465 : IsInConstParameters - returns the value of the InConstParameters.
22466 : */
22467 :
22468 92636 : extern "C" bool M2Quads_IsInConstParameters (void)
22469 : {
22470 92636 : return InConstParameters;
22471 : /* static analysis guarentees a RETURN statement will be used before here. */
22472 : __builtin_unreachable ();
22473 : }
22474 :
22475 :
22476 : /*
22477 : BuildAsmElement - the stack is expected to contain:
22478 :
22479 :
22480 : Entry Exit
22481 : ===== ====
22482 :
22483 : Ptr ->
22484 : +------------------+
22485 : | expr | tokpos |
22486 : |------------------|
22487 : | str |
22488 : |------------------|
22489 : | name |
22490 : |------------------| +------------------+
22491 : | CurrentInterface | | CurrentInterface |
22492 : |------------------| |------------------|
22493 : | CurrentAsm | | CurrentAsm |
22494 : |------------------| |------------------|
22495 : | n | | n |
22496 : |------------------| |------------------|
22497 : */
22498 :
22499 33 : extern "C" void M2Quads_BuildAsmElement (bool input, bool output)
22500 : {
22501 33 : DynamicStrings_String s;
22502 33 : unsigned int n;
22503 33 : unsigned int str;
22504 33 : unsigned int expr;
22505 33 : unsigned int tokpos;
22506 33 : unsigned int CurrentInterface;
22507 33 : unsigned int CurrentAsm;
22508 33 : unsigned int name;
22509 :
22510 33 : M2Quads_PopTtok (&expr, &tokpos);
22511 33 : M2Quads_PopT (&str);
22512 33 : M2Quads_PopT (&name);
22513 33 : M2Quads_PopT (&CurrentInterface);
22514 33 : M2Quads_PopT (&CurrentAsm);
22515 66 : M2Debug_Assert ((SymbolTable_IsGnuAsm (CurrentAsm)) || (SymbolTable_IsGnuAsmVolatile (CurrentAsm)));
22516 33 : M2Quads_PopT (&n);
22517 33 : n += 1;
22518 33 : if (CurrentInterface == SymbolTable_NulSym)
22519 : {
22520 30 : CurrentInterface = SymbolTable_MakeRegInterface ();
22521 : }
22522 33 : if (input)
22523 : {
22524 18 : SymbolTable_PutRegInterface (tokpos, CurrentInterface, n, name, str, expr, NextQuad, 0);
22525 18 : if (DebugAsmTokPos)
22526 : {
22527 : s = DynamicStrings_InitString ((const char *) "input expression", 16);
22528 : M2Error_WarnStringAt (s, tokpos);
22529 : }
22530 : }
22531 33 : if (output)
22532 : {
22533 15 : SymbolTable_PutRegInterface (tokpos, CurrentInterface, n, name, str, expr, 0, NextQuad);
22534 15 : if (DebugAsmTokPos)
22535 : {
22536 : s = DynamicStrings_InitString ((const char *) "output expression", 17);
22537 : M2Error_WarnStringAt (s, tokpos);
22538 : }
22539 : }
22540 33 : M2Quads_PushT (n);
22541 33 : M2Quads_PushT (CurrentAsm);
22542 33 : M2Quads_PushT (CurrentInterface);
22543 33 : }
22544 :
22545 :
22546 : /*
22547 : BuildAsmTrash - the stack is expected to contain:
22548 :
22549 :
22550 : Entry Exit
22551 : ===== ====
22552 :
22553 : Ptr ->
22554 : +------------------+
22555 : | expr | tokpos |
22556 : |------------------| +------------------+
22557 : | CurrentInterface | | CurrentInterface |
22558 : |------------------| |------------------|
22559 : | CurrentAsm | | CurrentAsm |
22560 : |------------------| |------------------|
22561 : | n | | n |
22562 : |------------------| |------------------|
22563 : */
22564 :
22565 3 : extern "C" void M2Quads_BuildAsmTrash (void)
22566 : {
22567 3 : unsigned int n;
22568 3 : unsigned int expr;
22569 3 : unsigned int tokpos;
22570 3 : unsigned int CurrentInterface;
22571 3 : unsigned int CurrentAsm;
22572 :
22573 3 : M2Quads_PopTtok (&expr, &tokpos);
22574 3 : M2Quads_PopT (&CurrentInterface);
22575 3 : M2Quads_PopT (&CurrentAsm);
22576 6 : M2Debug_Assert ((SymbolTable_IsGnuAsm (CurrentAsm)) || (SymbolTable_IsGnuAsmVolatile (CurrentAsm)));
22577 3 : M2Quads_PopT (&n);
22578 3 : n += 1;
22579 3 : if (CurrentInterface == SymbolTable_NulSym)
22580 : {
22581 3 : CurrentInterface = SymbolTable_MakeRegInterface ();
22582 : }
22583 3 : SymbolTable_PutRegInterface (tokpos, CurrentInterface, n, NameKey_NulName, SymbolTable_NulSym, expr, 0, NextQuad);
22584 3 : M2Quads_PushT (n);
22585 3 : M2Quads_PushT (CurrentAsm);
22586 3 : M2Quads_PushT (CurrentInterface);
22587 3 : }
22588 :
22589 :
22590 : /*
22591 : GetQuadTrash - return the symbol associated with the trashed operand.
22592 : */
22593 :
22594 260 : extern "C" unsigned int M2Quads_GetQuadTrash (unsigned int quad)
22595 : {
22596 260 : M2Quads_QuadFrame f;
22597 :
22598 260 : f = GetQF (quad);
22599 260 : LastQuadNo = quad;
22600 260 : return f->Trash;
22601 : /* static analysis guarentees a RETURN statement will be used before here. */
22602 : __builtin_unreachable ();
22603 : }
22604 :
22605 15674 : extern "C" void _M2_M2Quads_init (__attribute__((unused)) int argc, __attribute__((unused)) char *argv[], __attribute__((unused)) char *envp[])
22606 : {
22607 15674 : Init ();
22608 15674 : }
22609 :
22610 0 : extern "C" void _M2_M2Quads_fini (__attribute__((unused)) int argc, __attribute__((unused)) char *argv[], __attribute__((unused)) char *envp[])
22611 : {
22612 0 : }
|