Line data Source code
1 : /* do not edit automatically generated by mc from M2GenGCC. */
2 : /* M2GenGCC.mod convert the quadruples into GCC trees.
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 "Gmcrts.h"
43 : #if defined(__cplusplus)
44 : # undef NULL
45 : # define NULL 0
46 : #endif
47 : #define _M2GenGCC_C
48 :
49 : #include "GM2GenGCC.h"
50 : # include "GSYSTEM.h"
51 : # include "GSymbolTable.h"
52 : # include "Gm2tree.h"
53 : # include "Ggcctypes.h"
54 : # include "GM2Batch.h"
55 : # include "GM2LexBuf.h"
56 : # include "GM2Code.h"
57 : # include "GM2Debug.h"
58 : # include "GM2Error.h"
59 : # include "GM2MetaError.h"
60 : # include "GM2Options.h"
61 : # include "GM2Printf.h"
62 : # include "GM2Quiet.h"
63 : # include "GM2Base.h"
64 : # include "GM2Bitset.h"
65 : # include "GNameKey.h"
66 : # include "GDynamicStrings.h"
67 : # include "GFormatStrings.h"
68 : # include "GM2System.h"
69 : # include "GM2FileName.h"
70 : # include "GSymbolConversion.h"
71 : # include "GM2StackWord.h"
72 : # include "GLists.h"
73 : # include "GM2ALU.h"
74 : # include "GM2GCCDeclare.h"
75 : # include "GM2Range.h"
76 : # include "Gm2builtins.h"
77 : # include "Gm2expr.h"
78 : # include "Gm2decl.h"
79 : # include "Gm2statement.h"
80 : # include "Gm2type.h"
81 : # include "Gm2block.h"
82 : # include "Gm2misc.h"
83 : # include "Gm2convert.h"
84 : # include "Gm2except.h"
85 : # include "GM2Quads.h"
86 : # include "GM2Check.h"
87 : # include "GM2SSA.h"
88 : # include "GM2Optimize.h"
89 : # include "GM2BasicBlock.h"
90 :
91 : # define Debugging false
92 : # define PriorityDebugging false
93 : # define CascadedDebugging false
94 : typedef struct M2GenGCC_UnaryProcedure_p M2GenGCC_UnaryProcedure;
95 :
96 : typedef struct M2GenGCC_ProcedureCardinal_p M2GenGCC_ProcedureCardinal;
97 :
98 : typedef struct M2GenGCC_BinaryFunction_p M2GenGCC_BinaryFunction;
99 :
100 : typedef struct M2GenGCC_UnaryFunction_p M2GenGCC_UnaryFunction;
101 :
102 : # define Verbose false
103 : # define DebugTokPos false
104 : # define DebugTokPos false
105 : typedef void (*M2GenGCC_UnaryProcedure_t) (unsigned int);
106 : struct M2GenGCC_UnaryProcedure_p { M2GenGCC_UnaryProcedure_t proc; };
107 :
108 : typedef void (*M2GenGCC_ProcedureCardinal_t) (unsigned int);
109 : struct M2GenGCC_ProcedureCardinal_p { M2GenGCC_ProcedureCardinal_t proc; };
110 :
111 : typedef tree (*M2GenGCC_BinaryFunction_t) (location_t, tree, tree);
112 : struct M2GenGCC_BinaryFunction_p { M2GenGCC_BinaryFunction_t proc; };
113 :
114 : typedef tree (*M2GenGCC_UnaryFunction_t) (location_t, tree);
115 : struct M2GenGCC_UnaryFunction_p { M2GenGCC_UnaryFunction_t proc; };
116 :
117 : static unsigned int Memset;
118 : static unsigned int Memcpy;
119 : static unsigned int CurrentQuadToken;
120 : static unsigned int UnboundedLabelNo;
121 : static unsigned int LastLine;
122 : static M2Quads_QuadOperator LastOperator;
123 : static M2StackWord_StackOfWord ScopeStack;
124 : static bool NoChange;
125 : static unsigned int SetTemporaryNo;
126 : static unsigned int BreakQuad;
127 : static tree tryBlock;
128 : static tree handlerBlock;
129 :
130 : /*
131 : ConvertQuadsToTree - runs through the quadruple list and converts it into
132 : the GCC tree structure.
133 : */
134 :
135 : extern "C" void M2GenGCC_ConvertQuadsToTree (unsigned int Start, unsigned int End);
136 :
137 : /*
138 : ResolveConstantExpressions - resolves constant expressions from the quadruple list.
139 : It returns TRUE if one or more constants were folded.
140 : When a constant symbol value is solved, the call back
141 : p(sym) is invoked.
142 : */
143 :
144 : extern "C" bool M2GenGCC_ResolveConstantExpressions (M2GCCDeclare_WalkAction p, M2BasicBlock_BasicBlock bb);
145 :
146 : /*
147 : GetHighFromUnbounded - returns a Tree containing the value of
148 : param.HIGH.
149 : */
150 :
151 : extern "C" tree M2GenGCC_GetHighFromUnbounded (location_t location, unsigned int dim, unsigned int param);
152 :
153 : /*
154 : StringToChar - if type=Char and str is a string (of size <= 1)
155 : then convert the string into a character constant.
156 : */
157 :
158 : extern "C" tree M2GenGCC_StringToChar (tree t, unsigned int type, unsigned int str);
159 :
160 : /*
161 : LValueToGenericPtr - returns a Tree representing symbol, sym.
162 : It coerces a lvalue into an internal pointer type
163 : */
164 :
165 : extern "C" tree M2GenGCC_LValueToGenericPtr (location_t location, unsigned int sym);
166 :
167 : /*
168 : ZConstToTypedConst - checks whether op1 and op2 are constants and
169 : coerces, t, appropriately.
170 : */
171 :
172 : extern "C" tree M2GenGCC_ZConstToTypedConst (tree t, unsigned int op1, unsigned int op2);
173 :
174 : /*
175 : PrepareCopyString - returns two trees:
176 : length number of bytes to be copied (including the nul if room)
177 : srcTreeType the new string type (with the extra nul character).
178 :
179 : Pre condition: destStrType the dest type string.
180 : src is the original string (without a nul)
181 : to be copied.
182 : Post condition: TRUE or FALSE is returned.
183 : if true length and srcTreeType will be assigned
184 : else length is set to the maximum length to be
185 : copied and srcTree is set to the max length
186 : which fits in dest.
187 : */
188 :
189 : extern "C" bool M2GenGCC_PrepareCopyString (unsigned int tokenno, tree *length, tree *srcTree, unsigned int src, unsigned int destStrType);
190 :
191 : /*
192 : ErrorMessageDecl - emit an error message together with declaration fragments of left
193 : and right if they are parameters or variables.
194 : */
195 :
196 : static void ErrorMessageDecl (unsigned int tok, const char *message_, unsigned int _message_high, unsigned int left, unsigned int right, bool iserror);
197 :
198 : /*
199 : IsExportedGcc - returns TRUE if this symbol should be (as far as the middle/backend of GCC)
200 : is concerned, exported.
201 : */
202 :
203 : static bool IsExportedGcc (unsigned int sym);
204 :
205 : /*
206 : IsCompilingMainModule -
207 : */
208 :
209 : static bool IsCompilingMainModule (unsigned int sym);
210 :
211 : /*
212 : CodeLastForIterator - call PerformLastForIterator allowing for
213 : a non constant last iterator value.
214 : */
215 :
216 : static void CodeLastForIterator (unsigned int quad);
217 :
218 : /*
219 : FoldLastForIterator - call PerformLastForIterator providing
220 : all operands are constant and are known by GCC.
221 : */
222 :
223 : static void FoldLastForIterator (unsigned int quad, M2GCCDeclare_WalkAction p);
224 : static void PerformLastForIterator (unsigned int quad, M2GCCDeclare_WalkAction p, bool constant);
225 :
226 : /*
227 : CodeStatement - A multi-way decision call depending on the current
228 : quadruple.
229 : */
230 :
231 : static void CodeStatement (unsigned int q);
232 :
233 : /*
234 : FindSize - given a Modula-2 symbol sym return a gcc tree
235 : constant representing the storage size in bytes.
236 : */
237 :
238 : static tree FindSize (unsigned int tokenno, unsigned int sym);
239 :
240 : /*
241 : FindType - returns the type of, Sym, if Sym is a TYPE then return Sym otherwise return GetType(Sym)
242 : */
243 :
244 : static unsigned int FindType (unsigned int Sym);
245 :
246 : /*
247 : BuildTreeFromInterface - generates a GCC tree from an interface definition.
248 : */
249 :
250 : static tree BuildTreeFromInterface (unsigned int sym);
251 :
252 : /*
253 : BuildTrashTreeFromInterface - generates a GCC string tree from an interface definition.
254 : */
255 :
256 : static tree BuildTrashTreeFromInterface (unsigned int sym);
257 :
258 : /*
259 : CodeInline - InlineOp is a quadruple which has the following format:
260 :
261 : InlineOp NulSym NulSym Sym
262 : */
263 :
264 : static void CodeInline (unsigned int quad);
265 :
266 : /*
267 : FoldStatementNote - set CurrentQuadToken to tokennno.
268 : */
269 :
270 : static void FoldStatementNote (unsigned int tokenno);
271 :
272 : /*
273 : CodeStatementNote - set CurrentQuadToken to tokennno and
274 : add a statement note.
275 : */
276 :
277 : static void CodeStatementNote (unsigned int tokenno);
278 :
279 : /*
280 : FoldRange - attempts to fold the range test.
281 : --fixme-- complete this.
282 : */
283 :
284 : static void FoldRange (unsigned int tokenno, unsigned int quad, unsigned int rangeno);
285 :
286 : /*
287 : CodeSaveException - op1 := op3(TRUE)
288 : */
289 :
290 : static void CodeSaveException (unsigned int des, unsigned int exceptionProcedure);
291 :
292 : /*
293 : CodeRestoreException - op1 := op3(op1).
294 : */
295 :
296 : static void CodeRestoreException (unsigned int des, unsigned int exceptionProcedure);
297 :
298 : /*
299 : PushScope -
300 : */
301 :
302 : static void PushScope (unsigned int sym);
303 :
304 : /*
305 : PopScope -
306 : */
307 :
308 : static void PopScope (void);
309 :
310 : /*
311 : GetActiveScope -
312 : */
313 :
314 : static unsigned int GetActiveScope (void);
315 :
316 : /*
317 : GetCurrentScopeDescription - returns a description of the current scope.
318 : */
319 :
320 : static DynamicStrings_String GetCurrentScopeDescription (void);
321 :
322 : /*
323 : CodeRange - encode the range test associated with op3.
324 : */
325 :
326 : static void CodeRange (unsigned int rangeId);
327 :
328 : /*
329 : CodeError - encode the error test associated with op3.
330 : */
331 :
332 : static void CodeError (unsigned int errorId);
333 :
334 : /*
335 : CodeModuleScope - ModuleScopeOp is a quadruple which has the following
336 : format:
337 :
338 : ModuleScopeOp _ _ moduleSym
339 :
340 : Its purpose is to reset the source file to another
341 : file, hence all line numbers emitted with the
342 : generated code will be relative to this source file.
343 : */
344 :
345 : static void CodeModuleScope (unsigned int moduleSym);
346 :
347 : /*
348 : CodeStartModFile - StartModFileOp is a quadruple which has the following
349 : format:
350 :
351 : StartModFileOp _ _ moduleSym
352 :
353 : A new source file has been encountered therefore
354 : set LastLine to 1.
355 : Call pushGlobalScope.
356 : */
357 :
358 : static void CodeStartModFile (unsigned int moduleSym);
359 :
360 : /*
361 : CodeStartDefFile - StartDefFileOp is a quadruple with the following
362 : format:
363 :
364 : StartDefFileOp _ _ moduleSym
365 :
366 : A new source file has been encountered therefore
367 : set LastLine to 1.
368 : Call pushGlobalScope.
369 : */
370 :
371 : static void CodeStartDefFile (unsigned int moduleSym);
372 :
373 : /*
374 : CodeEndFile - pops the GlobalScope.
375 : */
376 :
377 : static void CodeEndFile (void);
378 :
379 : /*
380 : CallInnerInit - produce a call to inner module initialization routine.
381 : */
382 :
383 : static void CallInnerInit (unsigned int moduleSym);
384 :
385 : /*
386 : CallInnerFinally - produce a call to inner module finalization routine.
387 : */
388 :
389 : static void CallInnerFinally (unsigned int moduleSym);
390 :
391 : /*
392 : CodeInitStart - emits starting code before the main BEGIN END of the
393 : current module.
394 : */
395 :
396 : static void CodeInitStart (unsigned int moduleSym, bool CompilingMainModule);
397 :
398 : /*
399 : CodeInitEnd - emits terminating code after the main BEGIN END of the
400 : current module.
401 : */
402 :
403 : static void CodeInitEnd (unsigned int moduleSym, bool CompilingMainModule);
404 :
405 : /*
406 : CodeFinallyStart - emits starting code before the main BEGIN END of the
407 : current module.
408 : */
409 :
410 : static void CodeFinallyStart (unsigned int moduleSym, bool CompilingMainModule);
411 :
412 : /*
413 : CodeFinallyEnd - emits terminating code after the main BEGIN END of the
414 : current module. It also creates the scaffold if the
415 : cflag was not present.
416 : */
417 :
418 : static void CodeFinallyEnd (unsigned int moduleSym, bool CompilingMainModule);
419 :
420 : /*
421 : GetAddressOfUnbounded - returns the address of the unbounded array contents.
422 : */
423 :
424 : static tree GetAddressOfUnbounded (location_t location, unsigned int param);
425 :
426 : /*
427 : GetSizeOfHighFromUnbounded - returns a Tree containing the value of
428 : param.HIGH * sizeof(unboundedType).
429 : The number of legal bytes this array
430 : occupies.
431 : */
432 :
433 : static tree GetSizeOfHighFromUnbounded (unsigned int tokenno, unsigned int param);
434 :
435 : /*
436 : MaybeDebugBuiltinAlloca - if DebugBuiltins is set
437 : then call Builtins.alloca_trace
438 : else call Builtins.alloca.
439 : */
440 :
441 : static tree MaybeDebugBuiltinAlloca (location_t location, unsigned int tok, tree high);
442 :
443 : /*
444 : MaybeDebugBuiltinMemcpy - if DebugBuiltins is set
445 : then call memcpy
446 : else call Builtins.memcpy.
447 : */
448 :
449 : static tree MaybeDebugBuiltinMemcpy (location_t location, tree src, tree dest, tree nbytes);
450 :
451 : /*
452 : MakeCopyUse - make a copy of the unbounded array and alter all references
453 : from the old unbounded array to the new unbounded array.
454 : The parameter, param, contains a RECORD
455 : ArrayAddress: ADDRESS ;
456 : ArrayHigh : CARDINAL ;
457 : END
458 : we simply declare a new array of size, ArrayHigh
459 : and set ArrayAddress to the address of the copy.
460 :
461 : Remember ArrayHigh == sizeof(Array)-sizeof(typeof(array))
462 : so we add 1 for the size and add 1 for a possible <nul>
463 : */
464 :
465 : static void MakeCopyUse (unsigned int tokenno, unsigned int param);
466 :
467 : /*
468 : GetParamAddress - returns the address of parameter, param.
469 : */
470 :
471 : static tree GetParamAddress (location_t location, unsigned int proc, unsigned int param);
472 :
473 : /*
474 : IsUnboundedWrittenTo - returns TRUE if the unbounded parameter
475 : might be written to, or if -funbounded-by-reference
476 : was _not_ specified.
477 : */
478 :
479 : static bool IsUnboundedWrittenTo (unsigned int proc, unsigned int param);
480 :
481 : /*
482 : GetParamSize - returns the size in bytes of, param.
483 : */
484 :
485 : static tree GetParamSize (unsigned int tokenno, unsigned int param);
486 :
487 : /*
488 : DoIsIntersection - jumps to, tLabel, if the ranges i1..i2 j1..j2 overlap
489 : else jump to, fLabel.
490 : */
491 :
492 : static void DoIsIntersection (unsigned int tokenno, tree ta, tree tb, tree tc, tree td, DynamicStrings_String tLabel, DynamicStrings_String fLabel);
493 :
494 : /*
495 : BuildCascadedIfThenElsif - mustCheck contains a list of variables which
496 : must be checked against the address of (proc, param, i).
497 : If the address matches we make a copy of the unbounded
498 : parameter (proc, param) and quit further checking.
499 : */
500 :
501 : static void BuildCascadedIfThenElsif (unsigned int tokenno, Lists_List mustCheck, unsigned int proc, unsigned int param);
502 :
503 : /*
504 : CheckUnboundedNonVarParameter - if non var unbounded parameter is written to
505 : then
506 : make a copy of the contents of this parameter
507 : and use the copy
508 : else if param
509 : is type compatible with any parameter, symv
510 : and at runtime its address matches symv
511 : then
512 : make a copy of the contents of this parameter
513 : and use the copy
514 : fi
515 : */
516 :
517 : static void CheckUnboundedNonVarParameter (unsigned int tokenno, Lists_List trashed, unsigned int proc, unsigned int param);
518 :
519 : /*
520 : IsParameterWritten - returns TRUE if a parameter, sym, is written to.
521 : */
522 :
523 : static bool IsParameterWritten (unsigned int proc, unsigned int sym);
524 :
525 : /*
526 : SaveNonVarUnboundedParameters - for each var parameter, symv, do
527 : not just unbounded var parameters, but _all_
528 : parameters
529 : if symv is written to
530 : then
531 : add symv to a compile list
532 : fi
533 : done
534 :
535 : for each parameter of procedure, symu, do
536 : if non var unbounded parameter is written to
537 : then
538 : make a copy of the contents of this parameter
539 : and use the copy
540 : else if
541 : symu is type compatible with any parameter, symv
542 : and at runtime its address matches symv
543 : then
544 : make a copy of the contents of this parameter
545 : and use the copy
546 : fi
547 : done
548 : */
549 :
550 : static void SaveNonVarUnboundedParameters (unsigned int tokenno, unsigned int proc);
551 :
552 : /*
553 : AutoInitVariable -
554 : */
555 :
556 : static void AutoInitVariable (location_t location, unsigned int sym);
557 :
558 : /*
559 : AutoInitialize - scope will be a procedure, module or defimp. All pointer
560 : variables are assigned to NIL.
561 : */
562 :
563 : static void AutoInitialize (location_t location, unsigned int scope);
564 :
565 : /*
566 : CodeNewLocalVar - Builds a new frame on the stack to contain the procedure
567 : local variables.
568 : */
569 :
570 : static void CodeNewLocalVar (unsigned int tokenno, unsigned int CurrentProcedure);
571 :
572 : /*
573 : CodeKillLocalVar - removes local variables and returns to previous scope.
574 : */
575 :
576 : static void CodeKillLocalVar (unsigned int CurrentProcedure);
577 :
578 : /*
579 : CodeProcedureScope - start a procedure scope for CurrentProcedure.
580 : */
581 :
582 : static void CodeProcedureScope (unsigned int CurrentProcedure);
583 :
584 : /*
585 : CodeReturnValue - places the operand into the return value space
586 : allocated by the function call.
587 : */
588 :
589 : static void CodeReturnValue (unsigned int quad);
590 :
591 : /*
592 : CodeCall - determines whether the procedure call is a direct call
593 : or an indirect procedure call.
594 : */
595 :
596 : static void CodeCall (unsigned int tokenno, unsigned int procedure);
597 :
598 : /*
599 : UseBuiltin - returns a Tree containing the builtin function
600 : and parameters. It should only be called if
601 : CanUseBuiltin or IsProcedureBuiltinAvailable returns TRUE.
602 : */
603 :
604 : static tree UseBuiltin (unsigned int tokenno, unsigned int Sym);
605 :
606 : /*
607 : CodeDirectCall - calls a function/procedure.
608 : */
609 :
610 : static tree CodeDirectCall (unsigned int tokenno, unsigned int procedure);
611 :
612 : /*
613 : CodeIndirectCall - calls a function/procedure indirectly.
614 : */
615 :
616 : static tree CodeIndirectCall (unsigned int tokenno, unsigned int ProcVar);
617 :
618 : /*
619 : ConvertTo - convert gcc tree, t, (which currently represents Modula-2 op3) into
620 : a symbol of, type.
621 : */
622 :
623 : static tree ConvertTo (tree t, unsigned int type, unsigned int op3);
624 :
625 : /*
626 : ConvertRHS - convert (t, rhs) into, type. (t, rhs) refer to the
627 : same entity t is a GCC Tree and, rhs, is a Modula-2
628 : symbol. It checks for char and strings
629 : first and then the remaining types.
630 : */
631 :
632 : static tree ConvertRHS (tree t, unsigned int type, unsigned int rhs);
633 :
634 : /*
635 : IsCoerceableParameter - returns TRUE if symbol, sym, is a
636 : coerceable parameter.
637 : */
638 :
639 : static bool IsCoerceableParameter (unsigned int sym);
640 :
641 : /*
642 : IsConstProcedure - returns TRUE if, p, is a const procedure.
643 : */
644 :
645 : static bool IsConstProcedure (unsigned int p);
646 :
647 : /*
648 : IsConstant - returns TRUE if symbol, p, is either a const or procedure.
649 : */
650 :
651 : static bool IsConstant (unsigned int p);
652 :
653 : /*
654 : CheckConvertCoerceParameter - ensure that actual parameter is the same as the nth of callee.
655 : */
656 :
657 : static tree CheckConvertCoerceParameter (unsigned int tokenno, unsigned int nth, unsigned int callee, unsigned int actual);
658 :
659 : /*
660 : CheckConstant - checks to see whether we should declare the constant.
661 : */
662 :
663 : static tree CheckConstant (unsigned int tokenno, unsigned int des, unsigned int expr);
664 :
665 : /*
666 : CodeMakeAdr - code the function MAKEADR.
667 : */
668 :
669 : static void CodeMakeAdr (unsigned int q, unsigned int op1, unsigned int op2, unsigned int op3);
670 :
671 : /*
672 : CodeBuiltinFunction - attempts to inline a function. Currently it only
673 : inlines the SYSTEM function MAKEADR.
674 : */
675 :
676 : static void CodeBuiltinFunction (unsigned int q, unsigned int nth, unsigned int func, unsigned int parameter);
677 :
678 : /*
679 : FoldMakeAdr - attempts to fold the function MAKEADR.
680 : */
681 :
682 : static void FoldMakeAdr (unsigned int tokenno, M2GCCDeclare_WalkAction p, unsigned int q, unsigned int op1, unsigned int op2, unsigned int op3);
683 :
684 : /*
685 : doParam - builds the parameter, op3, which is to be passed to
686 : procedure, op2. The number of the parameter is op1.
687 : */
688 :
689 : static void doParam (unsigned int paramtok, unsigned int quad, unsigned int op1, unsigned int op2, unsigned int op3);
690 :
691 : /*
692 : FoldBuiltin - attempts to fold the gcc builtin function.
693 : */
694 :
695 : static void FoldBuiltin (unsigned int tokenno, M2GCCDeclare_WalkAction p, unsigned int q);
696 :
697 : /*
698 : FoldBuiltinFunction - attempts to inline a function. Currently it only
699 : inlines the SYSTEM function MAKEADR.
700 : */
701 :
702 : static void FoldBuiltinFunction (unsigned int tokenno, M2GCCDeclare_WalkAction p, unsigned int q, unsigned int op1, unsigned int op2, unsigned int op3);
703 :
704 : /*
705 : CodeParam - builds a parameter list.
706 : Note that we can ignore ModeOfAddr as any lvalue will
707 : have been created in a preceeding quadruple.
708 : */
709 :
710 : static void CodeParam (unsigned int quad);
711 :
712 : /*
713 : Replace - replace the entry for sym in the double entry bookkeeping with sym/tree.
714 : */
715 :
716 : static void Replace (unsigned int sym, tree gcc);
717 :
718 : /*
719 : CodeFunctValue - retrieves the function return value and assigns it
720 : into a variable.
721 : */
722 :
723 : static void CodeFunctValue (location_t location, unsigned int op1);
724 :
725 : /*
726 : FoldStringLength -
727 : */
728 :
729 : static void FoldStringLength (unsigned int quad, M2GCCDeclare_WalkAction p);
730 :
731 : /*
732 : FoldStringConvertM2nul - attempt to assign the des with the string contents from expr.
733 : It also marks the des as a m2 string which must be nul terminated.
734 : The front end uses double book keeping and it is easier to have
735 : different m2 string symbols each of which map onto a slightly different
736 : gcc string tree.
737 : */
738 :
739 : static void FoldStringConvertM2nul (unsigned int quad, M2GCCDeclare_WalkAction p);
740 :
741 : /*
742 : FoldStringConvertCnul -attempt to assign the des with the string contents from expr.
743 : It also marks the des as a C string which must be nul terminated.
744 : */
745 :
746 : static void FoldStringConvertCnul (unsigned int quad, M2GCCDeclare_WalkAction p);
747 : static void CodeAddr (unsigned int tokenno, unsigned int quad, unsigned int op1, unsigned int op3);
748 : static void FoldBecomes (M2GCCDeclare_WalkAction p, M2BasicBlock_BasicBlock bb, unsigned int quad);
749 :
750 : /*
751 : TryDeclareConst -
752 : */
753 :
754 : static void TryDeclareConst (unsigned int tokenno, unsigned int sym);
755 :
756 : /*
757 : RemoveQuad - remove quad and ensure p (des) is called.
758 : */
759 :
760 : static void RemoveQuad (M2GCCDeclare_WalkAction p, unsigned int des, unsigned int quad);
761 :
762 : /*
763 : DeclaredOperandsBecomes -
764 : */
765 :
766 : static bool DeclaredOperandsBecomes (M2GCCDeclare_WalkAction p, unsigned int quad);
767 :
768 : /*
769 : TypeCheckBecomes - returns TRUE if the type check succeeds.
770 : */
771 :
772 : static bool TypeCheckBecomes (M2GCCDeclare_WalkAction p, unsigned int quad);
773 :
774 : /*
775 : PerformFoldBecomes - attempts to fold quad. It propagates constant strings
776 : and attempts to declare des providing it is a constant
777 : and expr is resolved.
778 : */
779 :
780 : static void PerformFoldBecomes (M2GCCDeclare_WalkAction p, unsigned int quad);
781 :
782 : /*
783 : CodeTry - starts building a GCC 'try' node.
784 : */
785 :
786 : static void CodeTry (void);
787 :
788 : /*
789 : CodeThrow - builds a GCC 'throw' node.
790 : */
791 :
792 : static void CodeThrow (unsigned int value);
793 : static void CodeRetry (unsigned int destQuad);
794 : static void CodeCatchBegin (void);
795 : static void CodeCatchEnd (void);
796 :
797 : /*
798 : DescribeTypeError -
799 : */
800 :
801 : static void DescribeTypeError (unsigned int token, unsigned int op1, unsigned int op2);
802 :
803 : /*
804 : DefaultConvertGM2 - provides a simple mapping between
805 : front end data types and GCC equivalents.
806 : This is only used to aid assignment of
807 : typed constants.
808 : */
809 :
810 : static tree DefaultConvertGM2 (unsigned int sym);
811 :
812 : /*
813 : FoldConstBecomes - returns a Tree containing op3.
814 : The tree will have been folded and
815 : type converted if necessary.
816 : */
817 :
818 : static tree FoldConstBecomes (unsigned int tokenno, unsigned int op1, unsigned int op3);
819 :
820 : /*
821 : checkArrayElements - return TRUE if des or expr are not arrays.
822 : If they are arrays and have different number of
823 : elements return FALSE, otherwise TRUE.
824 : */
825 :
826 : static bool checkArrayElements (unsigned int des, unsigned int expr, unsigned int virtpos, unsigned int despos, unsigned int exprpos);
827 :
828 : /*
829 : CodeInitAddress -
830 : */
831 :
832 : static void CodeInitAddress (unsigned int quad, unsigned int op1, unsigned int op2, unsigned int op3);
833 :
834 : /*
835 : checkRecordTypes - returns TRUE if des is not a record or if the record
836 : is the same type as expr.
837 : */
838 :
839 : static bool checkRecordTypes (unsigned int des, unsigned int expr, unsigned int virtpos);
840 :
841 : /*
842 : checkIncorrectMeta - checks to see if des and expr are assignment compatible is allows
843 : generic system types to be assigned.
844 : */
845 :
846 : static bool checkIncorrectMeta (unsigned int des, unsigned int expr, unsigned int virtpos);
847 :
848 : /*
849 : checkBecomes - returns TRUE if the checks pass.
850 : */
851 :
852 : static bool checkBecomes (unsigned int des, unsigned int expr, unsigned int virtpos, unsigned int despos, unsigned int exprpos);
853 :
854 : /*
855 : checkDeclare - checks to see if sym is declared and if it is not then declare it.
856 : */
857 :
858 : static void checkDeclare (unsigned int sym);
859 :
860 : /*
861 : PerformCodeBecomes -
862 : */
863 :
864 : static void PerformCodeBecomes (location_t location, unsigned int virtpos, unsigned int des, unsigned int expr);
865 :
866 : /*
867 : IsSystemTypeBecomes - return TRUE if expr should be copied using
868 : memcpy into des. If des or expr are generic
869 : system types and expr is not constant then
870 : this is true.
871 : */
872 :
873 : static bool IsSystemTypeBecomes (unsigned int des, unsigned int expr);
874 : static void CodeBecomes (unsigned int quad);
875 :
876 : /*
877 : getrvalue -
878 : */
879 :
880 : static tree getrvalue (location_t location, unsigned int expr, unsigned int type, bool islvalue);
881 :
882 : /*
883 : LValueToGenericPtrOrConvert - if sym is an lvalue then convert to pointer type
884 : else convert to type, type. Return the converted tree.
885 : */
886 :
887 : static tree LValueToGenericPtrOrConvert (unsigned int sym, tree type);
888 :
889 : /*
890 : FoldBinary - check whether we can fold the binop operation.
891 : */
892 :
893 : static void FoldBinary (unsigned int tokenno, M2GCCDeclare_WalkAction p, m2expr_BuildBinProcedure binop, unsigned int quad, unsigned int op1, unsigned int op2, unsigned int op3);
894 :
895 : /*
896 : ConvertBinaryOperands -
897 : */
898 :
899 : static void ConvertBinaryOperands (location_t location, tree *tl, tree *tr, unsigned int type, unsigned int op2, unsigned int op3);
900 :
901 : /*
902 : CodeBinaryCheck - encode a binary arithmetic operation.
903 : */
904 :
905 : static void CodeBinaryCheck (m2expr_BuildBinCheckProcedure binop, unsigned int quad);
906 :
907 : /*
908 : MixTypesBinary - depending upon overflowCheck do not check pointer arithmetic.
909 : */
910 :
911 : static unsigned int MixTypesBinary (unsigned int left, unsigned int right, unsigned int tokpos, bool overflowCheck);
912 :
913 : /*
914 : CodeBinary - encode a binary arithmetic operation.
915 : */
916 :
917 : static void CodeBinary (m2expr_BuildBinProcedure binop, unsigned int quad);
918 :
919 : /*
920 : NoWalkProcedure -
921 : */
922 :
923 : static void NoWalkProcedure (unsigned int param __attribute__((unused)));
924 :
925 : /*
926 : CheckBinaryExpressionTypes - returns TRUE if all expression checks pass.
927 : If the expression check fails quad is removed,
928 : the walk procedure (des) is called and NoChange is
929 : set to FALSE.
930 : */
931 :
932 : static bool CheckBinaryExpressionTypes (unsigned int quad, M2GCCDeclare_WalkAction p);
933 :
934 : /*
935 : CheckElementSetTypes - returns TRUE if all expression checks pass.
936 : If the expression check fails quad is removed,
937 : the walk procedure (des) is called and NoChange is
938 : set to FALSE.
939 : */
940 :
941 : static bool CheckElementSetTypes (unsigned int quad);
942 :
943 : /*
944 : CodeBinarySet - encode a binary set AND arithmetic operation.
945 : Set operands may be longer than a word.
946 : */
947 :
948 : static void CodeBinarySet (M2GenGCC_ProcedureCardinal constp, M2GenGCC_BinaryFunction binfunc, NameKey_Name wideprocname, unsigned int quad);
949 :
950 : /*
951 : MakeTemporarySetName - returns a Name using the template _Tset%d.
952 : */
953 :
954 : static NameKey_Name MakeTemporarySetName (void);
955 :
956 : /*
957 : SetWideBinary -
958 : */
959 :
960 : static void SetWideBinary (unsigned int tokenno, NameKey_Name wideprocname, unsigned int settype, unsigned int des, unsigned int left, unsigned int right);
961 :
962 : /*
963 : SetWideBinaryLibrary - call wideprocname (des, left, right) passing des, left, right
964 : as an array of byte.
965 : */
966 :
967 : static void SetWideBinaryLibrary (unsigned int tokenno, NameKey_Name wideprocname, unsigned int settype, unsigned int des, unsigned int left, unsigned int right);
968 :
969 : /*
970 : SetWideBinaryBuiltin - build an builtin wideset NOT operation.
971 : */
972 :
973 : static void SetWideBinaryBuiltin (unsigned int tokenno, M2GenGCC_BinaryFunction binfunc, unsigned int des, unsigned int left, unsigned int right);
974 :
975 : /*
976 : SetNarrowBinary - create tree consisting of:
977 : result := binfunc (left, right)
978 : result, left and right can be lvalues.
979 : */
980 :
981 : static void SetNarrowBinary (location_t location, M2GenGCC_BinaryFunction binfunc, unsigned int settype, unsigned int result, unsigned int left, unsigned int right);
982 :
983 : /*
984 : CreateSetArrayParam - return a gcc tree containing value contained in an unbounded
985 : array parameter.
986 : */
987 :
988 : static tree CreateSetArrayParam (location_t location, unsigned int tokenno, unsigned int value, unsigned int param);
989 :
990 : /*
991 : CheckUnaryOperand - checks to see whether operand is using a generic type.
992 : */
993 :
994 : static bool CheckUnaryOperand (unsigned int quad, unsigned int operand);
995 :
996 : /*
997 : UnaryOperand - returns TRUE if operand is acceptable for
998 : unary operator: + -. If FALSE
999 : is returned, an error message will be generated
1000 : and the quad is deleted.
1001 : */
1002 :
1003 : static bool UnaryOperand (unsigned int quad, unsigned int operand);
1004 :
1005 : /*
1006 : CheckBinaryOperand - checks to see whether operand is using a generic type.
1007 : */
1008 :
1009 : static bool CheckBinaryOperand (unsigned int quad, bool isleft, unsigned int operand, bool result);
1010 :
1011 : /*
1012 : BinaryOperands - returns TRUE if, l, and, r, are acceptable for
1013 : binary operator: + - / * and friends. If FALSE
1014 : is returned, an error message will be generated
1015 : and the, quad, is deleted.
1016 : */
1017 :
1018 : static bool BinaryOperands (unsigned int quad, unsigned int l, unsigned int r);
1019 :
1020 : /*
1021 : IsConstStr - returns TRUE if sym is a constant string or a char constant.
1022 : */
1023 :
1024 : static bool IsConstStr (unsigned int sym);
1025 :
1026 : /*
1027 : IsConstStrKnown - returns TRUE if sym is a constant string or a char constant
1028 : which is known.
1029 : */
1030 :
1031 : static bool IsConstStrKnown (unsigned int sym);
1032 :
1033 : /*
1034 : GetStr - return a string containing a constant string value associated with sym.
1035 : A nul char constant will return an empty string.
1036 : */
1037 :
1038 : static DynamicStrings_String GetStr (unsigned int tokenno, unsigned int sym);
1039 :
1040 : /*
1041 : FoldAdd - check addition for constant folding. It checks for conststrings
1042 : overloading the +.
1043 : */
1044 :
1045 : static void FoldAdd (unsigned int tokenno, M2GCCDeclare_WalkAction p, unsigned int quad, unsigned int op1, unsigned int op2, unsigned int op3);
1046 :
1047 : /*
1048 : FoldArithAdd - check arithmetic addition for constant folding.
1049 : */
1050 :
1051 : static void FoldArithAdd (unsigned int tokenno, M2GCCDeclare_WalkAction p, unsigned int quad, unsigned int op1, unsigned int op2, unsigned int op3);
1052 :
1053 : /*
1054 : CodeAddChecked - code an addition instruction, determine whether checking
1055 : is required.
1056 : */
1057 :
1058 : static void CodeAddChecked (unsigned int quad, unsigned int left, unsigned int right);
1059 :
1060 : /*
1061 : CodeAddCheck - encode addition but check for overflow.
1062 : */
1063 :
1064 : static void CodeAddCheck (unsigned int quad, unsigned int left, unsigned int right);
1065 :
1066 : /*
1067 : CodeAdd - encode addition.
1068 : */
1069 :
1070 : static void CodeAdd (unsigned int quad, unsigned int left, unsigned int right);
1071 :
1072 : /*
1073 : FoldSub - check subtraction for constant folding.
1074 : */
1075 :
1076 : static void FoldSub (unsigned int tokenno, M2GCCDeclare_WalkAction p, unsigned int quad, unsigned int op1, unsigned int op2, unsigned int op3);
1077 :
1078 : /*
1079 : CodeSubChecked - code a subtract instruction, determine whether checking
1080 : is required.
1081 : */
1082 :
1083 : static void CodeSubChecked (unsigned int quad, unsigned int left, unsigned int right);
1084 :
1085 : /*
1086 : CodeSubCheck - encode subtraction but check for overflow.
1087 : */
1088 :
1089 : static void CodeSubCheck (unsigned int quad, unsigned int left, unsigned int right);
1090 :
1091 : /*
1092 : CodeSub - encode subtraction.
1093 : */
1094 :
1095 : static void CodeSub (unsigned int quad, unsigned int left, unsigned int right);
1096 :
1097 : /*
1098 : FoldMult - check multiplication for constant folding.
1099 : */
1100 :
1101 : static void FoldMult (unsigned int tokenno, M2GCCDeclare_WalkAction p, unsigned int quad, unsigned int op1, unsigned int op2, unsigned int op3);
1102 :
1103 : /*
1104 : CodeMultChecked - code a multiplication instruction, determine whether checking
1105 : is required.
1106 : */
1107 :
1108 : static void CodeMultChecked (unsigned int quad, unsigned int left, unsigned int right);
1109 :
1110 : /*
1111 : CodeMultCheck - encode multiplication but check for overflow.
1112 : */
1113 :
1114 : static void CodeMultCheck (unsigned int quad, unsigned int left, unsigned int right);
1115 :
1116 : /*
1117 : CodeMult - encode multiplication.
1118 : */
1119 :
1120 : static void CodeMult (unsigned int quad, unsigned int left, unsigned int right);
1121 :
1122 : /*
1123 : CodeDivM2Checked - code a divide instruction, determine whether checking
1124 : is required.
1125 : */
1126 :
1127 : static void CodeDivM2Checked (unsigned int quad, unsigned int left, unsigned int right);
1128 :
1129 : /*
1130 : CodeDivM2Check - encode addition but check for overflow.
1131 : */
1132 :
1133 : static void CodeDivM2Check (unsigned int quad, unsigned int left, unsigned int right);
1134 :
1135 : /*
1136 : CodeModM2Checked - code a modulus instruction, determine whether checking
1137 : is required.
1138 : */
1139 :
1140 : static void CodeModM2Checked (unsigned int quad, unsigned int left, unsigned int right);
1141 :
1142 : /*
1143 : CodeModM2Check - encode addition but check for overflow.
1144 : */
1145 :
1146 : static void CodeModM2Check (unsigned int quad, unsigned int left, unsigned int right);
1147 :
1148 : /*
1149 : BinaryOperandRealFamily -
1150 : */
1151 :
1152 : static bool BinaryOperandRealFamily (unsigned int op);
1153 :
1154 : /*
1155 : FoldDivM2 - check division for constant folding.
1156 : */
1157 :
1158 : static void FoldDivM2 (unsigned int tokenno, M2GCCDeclare_WalkAction p, unsigned int quad, unsigned int op1, unsigned int op2, unsigned int op3);
1159 :
1160 : /*
1161 : CodeDivM2 - encode division.
1162 : */
1163 :
1164 : static void CodeDivM2 (unsigned int quad, unsigned int left, unsigned int right);
1165 :
1166 : /*
1167 : FoldModM2 - check modulus for constant folding.
1168 : */
1169 :
1170 : static void FoldModM2 (unsigned int tokenno, M2GCCDeclare_WalkAction p, unsigned int quad, unsigned int op1, unsigned int op2, unsigned int op3);
1171 :
1172 : /*
1173 : CodeModM2 - encode modulus.
1174 : */
1175 :
1176 : static void CodeModM2 (unsigned int quad, unsigned int left, unsigned int right);
1177 :
1178 : /*
1179 : FoldDivTrunc - check division for constant folding.
1180 : */
1181 :
1182 : static void FoldDivTrunc (unsigned int tokenno, M2GCCDeclare_WalkAction p, unsigned int quad, unsigned int op1, unsigned int op2, unsigned int op3);
1183 :
1184 : /*
1185 : CodeDivTrunc - encode multiplication.
1186 : */
1187 :
1188 : static void CodeDivTrunc (unsigned int quad, unsigned int left, unsigned int right);
1189 :
1190 : /*
1191 : FoldModTrunc - check modulus for constant folding.
1192 : */
1193 :
1194 : static void FoldModTrunc (unsigned int tokenno, M2GCCDeclare_WalkAction p, unsigned int quad, unsigned int op1, unsigned int op2, unsigned int op3);
1195 :
1196 : /*
1197 : CodeModTrunc - encode modulus.
1198 : */
1199 :
1200 : static void CodeModTrunc (unsigned int quad, unsigned int left, unsigned int right);
1201 :
1202 : /*
1203 : FoldDivCeil - check division for constant folding.
1204 : */
1205 :
1206 : static void FoldDivCeil (unsigned int tokenno, M2GCCDeclare_WalkAction p, unsigned int quad, unsigned int op1, unsigned int op2, unsigned int op3);
1207 :
1208 : /*
1209 : CodeDivCeil - encode multiplication.
1210 : */
1211 :
1212 : static void CodeDivCeil (unsigned int quad, unsigned int left, unsigned int right);
1213 :
1214 : /*
1215 : FoldModCeil - check modulus for constant folding.
1216 : */
1217 :
1218 : static void FoldModCeil (unsigned int tokenno, M2GCCDeclare_WalkAction p, unsigned int quad, unsigned int op1, unsigned int op2, unsigned int op3);
1219 :
1220 : /*
1221 : CodeModCeil - encode multiplication.
1222 : */
1223 :
1224 : static void CodeModCeil (unsigned int quad, unsigned int left, unsigned int right);
1225 :
1226 : /*
1227 : FoldDivFloor - check division for constant folding.
1228 : */
1229 :
1230 : static void FoldDivFloor (unsigned int tokenno, M2GCCDeclare_WalkAction p, unsigned int quad, unsigned int op1, unsigned int op2, unsigned int op3);
1231 :
1232 : /*
1233 : CodeDivFloor - encode multiplication.
1234 : */
1235 :
1236 : static void CodeDivFloor (unsigned int quad, unsigned int left, unsigned int right);
1237 :
1238 : /*
1239 : FoldModFloor - check modulus for constant folding.
1240 : */
1241 :
1242 : static void FoldModFloor (unsigned int tokenno, M2GCCDeclare_WalkAction p, unsigned int quad, unsigned int op1, unsigned int op2, unsigned int op3);
1243 :
1244 : /*
1245 : CodeModFloor - encode modulus.
1246 : */
1247 :
1248 : static void CodeModFloor (unsigned int quad, unsigned int left, unsigned int right);
1249 :
1250 : /*
1251 : FoldBuiltinConst -
1252 : */
1253 :
1254 : static void FoldBuiltinConst (unsigned int tokenno, M2GCCDeclare_WalkAction p, unsigned int quad, unsigned int result, unsigned int constDesc);
1255 :
1256 : /*
1257 : FoldBuiltinTypeInfo - attempts to fold a builtin attribute value on type op2.
1258 : */
1259 :
1260 : static void FoldBuiltinTypeInfo (unsigned int tokenno, M2GCCDeclare_WalkAction p, unsigned int quad, unsigned int op1, unsigned int op2, unsigned int op3);
1261 :
1262 : /*
1263 : FoldTBitsize - attempt to fold the standard function SYSTEM.TBITSIZE
1264 : quadruple. If the quadruple is folded it is removed.
1265 : */
1266 :
1267 : static void FoldTBitsize (unsigned int tokenno, M2GCCDeclare_WalkAction p, unsigned int quad, unsigned int res, unsigned int type);
1268 :
1269 : /*
1270 : FoldStandardFunction - attempts to fold a standard function.
1271 : */
1272 :
1273 : static void FoldStandardFunction (unsigned int tokenno, M2GCCDeclare_WalkAction p, unsigned int quad, unsigned int op1, unsigned int op2, unsigned int op3);
1274 :
1275 : /*
1276 : CodeStandardFunction -
1277 : */
1278 :
1279 : static void CodeStandardFunction (unsigned int quad, unsigned int result, unsigned int function, unsigned int param);
1280 :
1281 : /*
1282 : CodeSavePriority - checks to see whether op2 is reachable and is directly accessible
1283 : externally. If so then it saves the current interrupt priority
1284 : in op1 and sets the current priority to that determined by
1285 : appropriate module.
1286 :
1287 : op1 := op3(GetModuleScope(op2))
1288 : */
1289 :
1290 : static void CodeSavePriority (unsigned int oldValue, unsigned int scopeSym, unsigned int procedureSym);
1291 :
1292 : /*
1293 : CodeRestorePriority - checks to see whether op2 is reachable and is directly accessible
1294 : externally. If so then it restores the previous interrupt priority
1295 : held in op1.
1296 :
1297 : op1 := op3(op1)
1298 : */
1299 :
1300 : static void CodeRestorePriority (unsigned int oldValue, unsigned int scopeSym, unsigned int procedureSym);
1301 :
1302 : /*
1303 : FoldBinarySet - attempts to fold set arithmetic it removes the quad if successful.
1304 : */
1305 :
1306 : static void FoldBinarySet (unsigned int tokenno, M2GCCDeclare_WalkAction p, M2GenGCC_ProcedureCardinal op, unsigned int quad, unsigned int op1, unsigned int op2, unsigned int op3);
1307 :
1308 : /*
1309 : FoldSetOr - check whether we can fold a set arithmetic or.
1310 : */
1311 :
1312 : static void FoldSetOr (unsigned int tokenno, M2GCCDeclare_WalkAction p, unsigned int quad, unsigned int op1, unsigned int op2, unsigned int op3);
1313 :
1314 : /*
1315 : CodeSetOr - encode set arithmetic or.
1316 : */
1317 :
1318 : static void CodeSetOr (unsigned int quad);
1319 :
1320 : /*
1321 : FoldSetAnd - check whether we can fold a logical and.
1322 : */
1323 :
1324 : static void FoldSetAnd (unsigned int tokenno, M2GCCDeclare_WalkAction p, unsigned int quad, unsigned int op1, unsigned int op2, unsigned int op3);
1325 :
1326 : /*
1327 : CodeSetAnd - encode set arithmetic and.
1328 : */
1329 :
1330 : static void CodeSetAnd (unsigned int quad);
1331 :
1332 : /*
1333 : CalcHighSetBit - calculate the most significant bit used in a set starting from bit zero.
1334 : */
1335 :
1336 : static tree CalcHighSetBit (location_t location, unsigned int settype);
1337 :
1338 : /*
1339 : CalcBitsInSet - returns the number of minimum number of bits used to represent a set.
1340 : */
1341 :
1342 : static tree CalcBitsInSet (location_t location, unsigned int settype);
1343 :
1344 : /*
1345 : SetWideSetShiftRotate - generate a call:
1346 : M2WIDESET.name (dest, src, HIGHBIT (settype), count).
1347 : */
1348 :
1349 : static void SetWideSetShiftRotate (unsigned int tokenno, NameKey_Name name, unsigned int settype, unsigned int dest, unsigned int src, unsigned int count);
1350 :
1351 : /*
1352 : CodeNarrowSetShift -
1353 : */
1354 :
1355 : static void CodeNarrowSetShift (unsigned int tokenno, unsigned int settype, unsigned int dest, unsigned int src, unsigned int count);
1356 :
1357 : /*
1358 : CodeNarrowSetRotate -
1359 : */
1360 :
1361 : static void CodeNarrowSetRotate (unsigned int tokenno, unsigned int settype, unsigned int dest, unsigned int src, unsigned int count);
1362 :
1363 : /*
1364 : CodeBinarySetShiftRotate - encode a binary set arithmetic operation.
1365 : */
1366 :
1367 : static void CodeBinarySetShiftRotate (unsigned int quad, bool isshift);
1368 :
1369 : /*
1370 : FoldSetShift - check whether we can fold a logical shift.
1371 : */
1372 :
1373 : static void FoldSetShift (unsigned int tokenno, M2GCCDeclare_WalkAction p, unsigned int quad, unsigned int Dest, unsigned int Src, unsigned int ShiftCount);
1374 :
1375 : /*
1376 : CodeSetShift - encode set arithmetic shift.
1377 : */
1378 :
1379 : static void CodeSetShift (unsigned int quad);
1380 :
1381 : /*
1382 : FoldSetRotate - check whether we can fold a logical rotate.
1383 : */
1384 :
1385 : static void FoldSetRotate (unsigned int tokenno, M2GCCDeclare_WalkAction p, unsigned int quad, unsigned int Dest, unsigned int Src, unsigned int RotateCount);
1386 :
1387 : /*
1388 : CodeSetRotate - encode set arithmetic rotate.
1389 : */
1390 :
1391 : static void CodeSetRotate (unsigned int quad);
1392 :
1393 : /*
1394 : CodeSetLogicalDifference - encode set arithmetic logical difference.
1395 : */
1396 :
1397 : static void CodeSetLogicalDifference (unsigned int quad);
1398 :
1399 : /*
1400 : FoldSymmetricDifference - check whether we can fold a logical difference.
1401 : */
1402 :
1403 : static void FoldSymmetricDifference (unsigned int tokenno, M2GCCDeclare_WalkAction p, unsigned int quad, unsigned int op1, unsigned int op2, unsigned int op3);
1404 :
1405 : /*
1406 : CodeSetSymmetricDifference - code set difference.
1407 : A logical xor expression.
1408 : */
1409 :
1410 : static void CodeSetSymmetricDifference (unsigned int quad);
1411 :
1412 : /*
1413 : CodeUnarySet - encode a unary set arithmetic operation.
1414 : Set operands may be longer than a word.
1415 : */
1416 :
1417 : static void CodeUnarySet (M2GenGCC_ProcedureCardinal constop, M2GenGCC_UnaryFunction unfunc, unsigned int tokenno, NameKey_Name wideprocname, unsigned int quad, unsigned int result, unsigned int expr);
1418 :
1419 : /*
1420 : FromM2WIDESETImport - returns M2WIDESET.name.
1421 : */
1422 :
1423 : static unsigned int FromM2WIDESETImport (unsigned int tokenno, NameKey_Name name);
1424 :
1425 : /*
1426 : SetWideUnaryLibrary - call wideprocname (result, expr) passing result and expr
1427 : as an array of byte.
1428 : */
1429 :
1430 : static void SetWideUnaryLibrary (unsigned int tokenno, NameKey_Name wideprocname, unsigned int settype, unsigned int result, unsigned int expr);
1431 :
1432 : /*
1433 : SetWideUnaryBuiltinNot - build an builtin wideset NOT operation.
1434 : */
1435 :
1436 : static void SetWideUnaryBuiltinNot (unsigned int tokenno, unsigned int result, unsigned int expr);
1437 :
1438 : /*
1439 : SetWideUnary - either call the library wideprocname or the builtin
1440 : version depending upon the optimization setting.
1441 : */
1442 :
1443 : static void SetWideUnary (unsigned int tokenno, NameKey_Name wideprocname, unsigned int settype, unsigned int result, unsigned int expr);
1444 :
1445 : /*
1446 : SetNarrowUnary - create tree consisting of:
1447 : result := unfunc (expr)
1448 : result and expr can be lvalues.
1449 : */
1450 :
1451 : static void SetNarrowUnary (location_t location, M2GenGCC_UnaryFunction unfunc, unsigned int settype, unsigned int result, unsigned int expr);
1452 :
1453 : /*
1454 : FoldIncl - check whether we can fold the InclOp.
1455 : result := result + (1 << expr)
1456 : */
1457 :
1458 : static void FoldIncl (unsigned int tokenno, M2GCCDeclare_WalkAction p, unsigned int quad, unsigned int result, unsigned int expr);
1459 :
1460 : /*
1461 : FoldIfLess - check to see if it is possible to evaluate
1462 : if op1 < op2 then goto op3.
1463 : */
1464 :
1465 : static void FoldIfLess (unsigned int tokenno, unsigned int quad, unsigned int left, unsigned int right, unsigned int destQuad);
1466 :
1467 : /*
1468 : FoldIfGre - check to see if it is possible to evaluate
1469 : if op1 > op2 then goto op3.
1470 : */
1471 :
1472 : static void FoldIfGre (unsigned int tokenno, unsigned int quad, unsigned int left, unsigned int right, unsigned int destQuad);
1473 :
1474 : /*
1475 : FoldIfLessEqu - check to see if it is possible to evaluate
1476 : if op1 <= op2 then goto op3.
1477 : */
1478 :
1479 : static void FoldIfLessEqu (unsigned int tokenno, unsigned int quad, unsigned int left, unsigned int right, unsigned int destQuad);
1480 :
1481 : /*
1482 : FoldIfGreEqu - check to see if it is possible to evaluate
1483 : if op1 >= op2 then goto op3.
1484 : */
1485 :
1486 : static void FoldIfGreEqu (unsigned int tokenno, unsigned int quad, unsigned int left, unsigned int right, unsigned int destQuad);
1487 :
1488 : /*
1489 : FoldIfIn - check whether we can fold the IfInOp
1490 : if op1 in op2 then goto op3
1491 : */
1492 :
1493 : static void FoldIfIn (unsigned int tokenno, unsigned int quad, unsigned int left, unsigned int right, unsigned int destQuad);
1494 :
1495 : /*
1496 : FoldIfNotIn - check whether we can fold the IfNotInOp
1497 : if not (op1 in op2) then goto op3
1498 : */
1499 :
1500 : static void FoldIfNotIn (unsigned int tokenno, unsigned int quad, unsigned int left, unsigned int right, unsigned int destQuad);
1501 :
1502 : /*
1503 : FoldIfEqu - check to see if it is possible to evaluate
1504 : if op1 = op2 then goto op3.
1505 : */
1506 :
1507 : static void FoldIfEqu (unsigned int tokenno, unsigned int quad, unsigned int left, unsigned int right, unsigned int destQuad);
1508 :
1509 : /*
1510 : FoldIfNotEqu - check to see if it is possible to evaluate
1511 : if op1 # op2 then goto op3.
1512 : */
1513 :
1514 : static void FoldIfNotEqu (unsigned int tokenno, unsigned int quad, unsigned int left, unsigned int right, unsigned int destQuad);
1515 :
1516 : /*
1517 : GetSetLimits - assigns low and high to the limits of the declared, set.
1518 : */
1519 :
1520 : static void GetSetLimits (unsigned int set, unsigned int *low, unsigned int *high);
1521 :
1522 : /*
1523 : IsElementInRange - returns TRUE if expr references a bit in setvar
1524 : which is in the range [low..high]. If expr is a
1525 : variable it returns TRUE. FALSE is returned if we
1526 : know expr to be out of bounds.
1527 : */
1528 :
1529 : static bool IsElementInRange (unsigned int tokenno, unsigned int settype, unsigned int setvar, unsigned int expr);
1530 :
1531 : /*
1532 : SetElementToBit -
1533 : */
1534 :
1535 : static tree SetElementToBit (location_t location, unsigned int settype, unsigned int expr);
1536 :
1537 : /*
1538 : CodeNarrowIncl - result |= (1 << expr).
1539 : */
1540 :
1541 : static void CodeNarrowIncl (location_t location, unsigned int settype, unsigned int result, unsigned int expr);
1542 :
1543 : /*
1544 : CodeNarrowExcl - result &= (~ (1 << expr)).
1545 : */
1546 :
1547 : static void CodeNarrowExcl (location_t location, unsigned int settype, unsigned int result, unsigned int expr);
1548 :
1549 : /*
1550 : SetWideUnaryBuiltinIncl -
1551 : */
1552 :
1553 : static void SetWideUnaryBuiltinIncl (location_t location, tree dest, tree bitno);
1554 :
1555 : /*
1556 : SetWideUnaryBuiltinExcl -
1557 : */
1558 :
1559 : static void SetWideUnaryBuiltinExcl (location_t location, tree dest, tree bitno);
1560 : static void SetWideUnaryBuiltinInclExcl (unsigned int tokenno, unsigned int settype, unsigned int des, unsigned int expr, bool incl);
1561 :
1562 : /*
1563 : SetWideInclExcl - generates M2WIDESET.procedurename (result, expr).
1564 : */
1565 :
1566 : static void SetWideInclExcl (unsigned int tokenno, unsigned int settype, unsigned int result, unsigned int expr, NameKey_Name procedurename);
1567 :
1568 : /*
1569 : SetWideInclExclLibrary -
1570 : */
1571 :
1572 : static void SetWideInclExclLibrary (unsigned int tokenno, unsigned int settype, unsigned int result, unsigned int expr, NameKey_Name procedurename);
1573 :
1574 : /*
1575 : CodeIncl - encode an InclOp:
1576 : result |= (1 << expr).
1577 : */
1578 :
1579 : static void CodeIncl (unsigned int quad);
1580 :
1581 : /*
1582 : FoldExcl - check whether we can fold the InclOp.
1583 : result &= ~ (1 << expr).
1584 : */
1585 :
1586 : static void FoldExcl (unsigned int tokenno, M2GCCDeclare_WalkAction p, unsigned int quad, unsigned int result, unsigned int expr);
1587 :
1588 : /*
1589 : CodeExcl - encode an ExclOp:
1590 : result &= (~ (1 << expr)).
1591 : */
1592 :
1593 : static void CodeExcl (unsigned int quad);
1594 :
1595 : /*
1596 : FoldUnary - check whether we can fold the unop operation.
1597 : */
1598 :
1599 : static void FoldUnary (unsigned int tokenno, M2GCCDeclare_WalkAction p, m2expr_BuildUnaryProcedure unop, tree ZConstToTypedConst, unsigned int quad, unsigned int result, unsigned int expr);
1600 :
1601 : /*
1602 : FoldUnarySet - check whether we can fold the doOp operation.
1603 : */
1604 :
1605 : static void FoldUnarySet (unsigned int tokenno, M2GCCDeclare_WalkAction p, M2GenGCC_ProcedureCardinal doOp, unsigned int quad, unsigned int result, unsigned int expr);
1606 :
1607 : /*
1608 : CodeUnaryCheck - encode a unary arithmetic operation.
1609 : */
1610 :
1611 : static void CodeUnaryCheck (m2expr_BuildUnaryCheckProcedure unop, tree ZConstToTypedConst, unsigned int quad, unsigned int result, unsigned int expr);
1612 :
1613 : /*
1614 : CodeUnary - encode a unary arithmetic operation.
1615 : */
1616 :
1617 : static void CodeUnary (m2expr_BuildUnaryProcedure unop, tree ZConstToTypedConst, unsigned int quad, unsigned int result, unsigned int expr);
1618 :
1619 : /*
1620 : FoldNegate - check unary negate for constant folding.
1621 : */
1622 :
1623 : static void FoldNegate (unsigned int tokenno, M2GCCDeclare_WalkAction p, unsigned int quad, unsigned int result, unsigned int expr);
1624 :
1625 : /*
1626 : CodeNegateChecked - code a negate instruction, determine whether checking
1627 : is required.
1628 : */
1629 :
1630 : static void CodeNegateChecked (unsigned int quad);
1631 :
1632 : /*
1633 : FoldSize - check unary SIZE for constant folding.
1634 : */
1635 :
1636 : static void FoldSize (unsigned int tokenno, M2GCCDeclare_WalkAction p, unsigned int quad, unsigned int op1, unsigned int op2, unsigned int op3);
1637 :
1638 : /*
1639 : CodeSize - encode the inbuilt SIZE function.
1640 : */
1641 :
1642 : static void CodeSize (unsigned int result, unsigned int sym);
1643 :
1644 : /*
1645 : FoldRecordField - check whether we can fold an RecordFieldOp quadruple.
1646 : Very similar to FoldBinary, except that we need to
1647 : hard code a few parameters to the gcc backend.
1648 : */
1649 :
1650 : static void FoldRecordField (unsigned int tokenno, M2GCCDeclare_WalkAction p, unsigned int quad, unsigned int result, unsigned int record, unsigned int field);
1651 :
1652 : /*
1653 : CodeRecordField - encode a reference to a field within a record.
1654 : */
1655 :
1656 : static void CodeRecordField (unsigned int result, unsigned int record, unsigned int field);
1657 :
1658 : /*
1659 : BuildHighFromChar -
1660 : */
1661 :
1662 : static tree BuildHighFromChar (unsigned int operand);
1663 :
1664 : /*
1665 : SkipToArray -
1666 : */
1667 :
1668 : static unsigned int SkipToArray (unsigned int operand, unsigned int dim);
1669 :
1670 : /*
1671 : BuildHighFromArray -
1672 : */
1673 :
1674 : static tree BuildHighFromArray (unsigned int tokenno, unsigned int dim, unsigned int operand);
1675 :
1676 : /*
1677 : BuildHighFromSetArray -
1678 : */
1679 :
1680 : static tree BuildHighFromSetArray (unsigned int tokenno, unsigned int settype);
1681 :
1682 : /*
1683 : BuildHighFromStaticArray -
1684 : */
1685 :
1686 : static tree BuildHighFromStaticArray (location_t location, unsigned int Type);
1687 :
1688 : /*
1689 : BuildHighFromString -
1690 : */
1691 :
1692 : static tree BuildHighFromString (unsigned int operand);
1693 :
1694 : /*
1695 : ResolveHigh - given an Modula-2 operand, it resolves the HIGH(operand)
1696 : and returns a GCC constant symbol containing the value of
1697 : HIGH(operand).
1698 : */
1699 :
1700 : static tree ResolveHigh (unsigned int tokenno, unsigned int dim, unsigned int operand);
1701 :
1702 : /*
1703 : IsUnboundedArray - return TRUE if symbol is an unbounded array.
1704 : */
1705 :
1706 : static bool IsUnboundedArray (unsigned int sym);
1707 :
1708 : /*
1709 : FoldHigh - if the array is not dynamic then we should be able to
1710 : remove the HighOp quadruple and assign op1 with
1711 : the known compile time HIGH(array).
1712 : */
1713 :
1714 : static void FoldHigh (unsigned int tokenno, M2GCCDeclare_WalkAction p, unsigned int quad, unsigned int op1, unsigned int dim, unsigned int array);
1715 :
1716 : /*
1717 : CodeHigh - encode a unary arithmetic operation.
1718 : */
1719 :
1720 : static void CodeHigh (unsigned int result, unsigned int dim, unsigned int array);
1721 :
1722 : /*
1723 : CodeUnbounded - codes the creation of an unbounded parameter variable.
1724 : result = &array. array can be an lvalue or rvalue.
1725 : */
1726 :
1727 : static void CodeUnbounded (unsigned int result, unsigned int array);
1728 :
1729 : /*
1730 : AreSubrangesKnown - returns TRUE if the subranges values used within, array, are known.
1731 : */
1732 :
1733 : static bool AreSubrangesKnown (unsigned int array);
1734 :
1735 : /*
1736 : CodeArray - res is an lvalue which will point to the array element.
1737 : */
1738 :
1739 : static void CodeArray (unsigned int res, unsigned int index, unsigned int array);
1740 :
1741 : /*
1742 : FoldElementSizeForArray - attempts to calculate the Subscript
1743 : multiplier for the index op3.
1744 : */
1745 :
1746 : static void FoldElementSizeForArray (unsigned int tokenno, unsigned int quad, M2GCCDeclare_WalkAction p, unsigned int result, unsigned int type);
1747 :
1748 : /*
1749 : FoldElementSizeForUnbounded - Unbounded arrays only have one index,
1750 : therefore element size will be the
1751 : TSIZE(Type) where Type is defined as:
1752 : ARRAY OF Type.
1753 : */
1754 :
1755 : static void FoldElementSizeForUnbounded (unsigned int tokenno, unsigned int quad, M2GCCDeclare_WalkAction p, unsigned int result, unsigned int ArrayType);
1756 :
1757 : /*
1758 : FoldElementSize - folds the element size for an ArraySym or UnboundedSym.
1759 : ElementSize returns a constant which defines the
1760 : multiplier to be multiplied by this element index.
1761 : */
1762 :
1763 : static void FoldElementSize (unsigned int tokenno, M2GCCDeclare_WalkAction p, unsigned int quad, unsigned int result, unsigned int type);
1764 :
1765 : /*
1766 : PopKindTree - returns a Tree from M2ALU of the type implied by, op.
1767 : */
1768 :
1769 : static tree PopKindTree (unsigned int op, unsigned int tokenno);
1770 :
1771 : /*
1772 : FoldConvert - attempts to fold expr to type into result
1773 : providing that result and expr are constants.
1774 : If required convert will alter the machine representation
1775 : of expr to comply with type.
1776 : */
1777 :
1778 : static void FoldConvert (unsigned int tokenno, M2GCCDeclare_WalkAction p, unsigned int quad, unsigned int result, unsigned int type, unsigned int expr);
1779 :
1780 : /*
1781 : CodeConvert - Converts, rhs, to, type, placing the result into lhs.
1782 : Convert will, if need be, alter the machine representation
1783 : of op3 to comply with TYPE op2.
1784 : */
1785 :
1786 : static void CodeConvert (unsigned int quad, unsigned int lhs, unsigned int type, unsigned int rhs);
1787 :
1788 : /*
1789 : CodeCoerce - Coerce op3 to type op2 placing the result into
1790 : op1.
1791 : Coerce will NOT alter the machine representation
1792 : of op3 to comply with TYPE op2.
1793 : Therefore it _insists_ that under all circumstances that the
1794 : type sizes of op1 and op3 are the same.
1795 : CONVERT will perform machine manipulation to change variable
1796 : types, coerce does no such thing.
1797 : */
1798 :
1799 : static void CodeCoerce (unsigned int quad, unsigned int op1, unsigned int op2, unsigned int op3);
1800 :
1801 : /*
1802 : FoldCoerce -
1803 : */
1804 :
1805 : static void FoldCoerce (unsigned int tokenno, M2GCCDeclare_WalkAction p, unsigned int quad, unsigned int op1, unsigned int op2, unsigned int op3);
1806 :
1807 : /*
1808 : CanConvert - returns TRUE if we can convert variable, var, to a, type.
1809 : */
1810 :
1811 : static bool CanConvert (unsigned int type, unsigned int var);
1812 :
1813 : /*
1814 : CodeCast - Cast op3 to type op2 placing the result into op1.
1815 : Cast will NOT alter the machine representation
1816 : of op3 to comply with TYPE op2 as long as SIZE(op3)=SIZE(op2).
1817 : If the sizes differ then Convert is called.
1818 : */
1819 :
1820 : static void CodeCast (unsigned int quad, unsigned int op1, unsigned int op2, unsigned int op3);
1821 : static void FoldCast (unsigned int tokenno, M2GCCDeclare_WalkAction p, unsigned int quad, unsigned int op1, unsigned int op2, unsigned int op3);
1822 :
1823 : /*
1824 : CreateLabelProcedureN - creates a label using procedure name and
1825 : an integer.
1826 : */
1827 :
1828 : static DynamicStrings_String CreateLabelProcedureN (unsigned int proc, const char *leader_, unsigned int _leader_high, unsigned int unboundedCount, unsigned int n);
1829 :
1830 : /*
1831 : CreateLabelName - creates a namekey from quadruple, q.
1832 : */
1833 :
1834 : static DynamicStrings_String CreateLabelName (unsigned int q);
1835 :
1836 : /*
1837 : CodeGoto - creates a jump to a labeled quadruple.
1838 : */
1839 :
1840 : static void CodeGoto (unsigned int destquad);
1841 :
1842 : /*
1843 : CheckReferenced - checks to see whether this quadruple requires a label.
1844 : */
1845 :
1846 : static void CheckReferenced (unsigned int quad, M2Quads_QuadOperator op);
1847 :
1848 : /*
1849 : CodeIfSetCondition - code IF left cond right then destquad for set types.
1850 : */
1851 :
1852 : static void CodeIfSetCondition (unsigned int tokenno, unsigned int left, unsigned int right, unsigned int destquad, M2GenGCC_BinaryFunction cond, NameKey_Name procedurename);
1853 :
1854 : /*
1855 : CodeIfSetLess - code IF left < right then destquad for set types.
1856 : */
1857 :
1858 : static void CodeIfSetLess (unsigned int tokenno, unsigned int left, unsigned int right, unsigned int destquad);
1859 :
1860 : /*
1861 : CodeIfSetLessEqu - code IF left <= right then destquad for set types.
1862 : */
1863 :
1864 : static void CodeIfSetLessEqu (unsigned int tokenno, unsigned int left, unsigned int right, unsigned int destquad);
1865 :
1866 : /*
1867 : CodeIfSetGre - code IF left > right then destquad for set types.
1868 : */
1869 :
1870 : static void CodeIfSetGre (unsigned int tokenno, unsigned int left, unsigned int right, unsigned int destquad);
1871 :
1872 : /*
1873 : CodeIfSetGreEqu - code IF left >= right then destquad for set types.
1874 : */
1875 :
1876 : static void CodeIfSetGreEqu (unsigned int tokenno, unsigned int left, unsigned int right, unsigned int destquad);
1877 :
1878 : /*
1879 : PerformCodeIfLess - codes the quadruple if op1 < op2 then goto op3
1880 : */
1881 :
1882 : static void PerformCodeIfLess (unsigned int quad);
1883 :
1884 : /*
1885 : CodeIfLess - codes the quadruple if op1 < op2 then goto op3
1886 : */
1887 :
1888 : static void CodeIfLess (unsigned int quad);
1889 :
1890 : /*
1891 : CodeIfSetEquNarrow -
1892 : */
1893 :
1894 : static void CodeIfSetEquNarrow (location_t location, bool invertCondition, unsigned int settype, tree left, tree right, unsigned int destQuad);
1895 :
1896 : /*
1897 : CallSetWideBoolFunction - return a tree containing a call to
1898 : M2WIDESET.widefuncname (left, right, HIGHBIT (settype)).
1899 : */
1900 :
1901 : static tree CallSetWideBoolFunction (location_t location, unsigned int tokenno, NameKey_Name widefuncname, unsigned int settype, unsigned int left, unsigned int right);
1902 :
1903 : /*
1904 : CodeIfSetEquWide - creates a statement tree:
1905 : if left = right then goto destQuad. The boolean
1906 : invertCondition will check left # right.
1907 : */
1908 :
1909 : static void CodeIfSetEquWide (location_t location, unsigned int tokenno, bool invertCondition, unsigned int settype, unsigned int left, unsigned int right, unsigned int destQuad);
1910 :
1911 : /*
1912 : CodeIfSetEquLower code a comparison between left and right and if true
1913 : jump to destQuad. The invertCondition allows for the inverse test.
1914 : Note that if op1 and op2 are not both constants as this will have been
1915 : evaluated in CodeIfNotEqu.
1916 : */
1917 :
1918 : static void CodeIfSetEquLower (unsigned int tokenno, bool invertCondition, unsigned int left, unsigned int right, unsigned int destQuad);
1919 :
1920 : /*
1921 : CodeIfSetNotEqu - codes if op1 # op2 then goto op3
1922 : */
1923 :
1924 : static void CodeIfSetNotEqu (unsigned int tokenno, unsigned int left, unsigned int right, unsigned int destQuad);
1925 :
1926 : /*
1927 : CodeIfSetEqu - codes if op1 = op2 then goto op3
1928 : */
1929 :
1930 : static void CodeIfSetEqu (unsigned int tokenno, unsigned int left, unsigned int right, unsigned int destQuad);
1931 :
1932 : /*
1933 : PerformCodeIfGre - codes the quadruple if op1 > op2 then goto op3
1934 : */
1935 :
1936 : static void PerformCodeIfGre (unsigned int quad);
1937 :
1938 : /*
1939 : CodeIfGre - codes the quadruple if op1 > op2 then goto op3
1940 : */
1941 :
1942 : static void CodeIfGre (unsigned int quad);
1943 :
1944 : /*
1945 : PerformCodeIfLessEqu - codes the quadruple if op1 <= op2 then goto op3
1946 : */
1947 :
1948 : static void PerformCodeIfLessEqu (unsigned int quad);
1949 :
1950 : /*
1951 : CodeIfLessEqu - codes the quadruple if op1 <= op2 then goto op3
1952 : */
1953 :
1954 : static void CodeIfLessEqu (unsigned int quad);
1955 :
1956 : /*
1957 : PerformCodeIfGreEqu - codes the quadruple if op1 >= op2 then goto op3
1958 : */
1959 :
1960 : static void PerformCodeIfGreEqu (unsigned int quad);
1961 :
1962 : /*
1963 : CodeIfGreEqu - codes the quadruple if op1 >= op2 then goto op3
1964 : */
1965 :
1966 : static void CodeIfGreEqu (unsigned int quad);
1967 :
1968 : /*
1969 : ComparisonMixTypes -
1970 : */
1971 :
1972 : static unsigned int ComparisonMixTypes (unsigned int varleft, unsigned int varright, unsigned int left, unsigned int right, unsigned int tokpos);
1973 :
1974 : /*
1975 : PerformCodeIfEqu -
1976 : */
1977 :
1978 : static void PerformCodeIfEqu (unsigned int quad);
1979 :
1980 : /*
1981 : PerformCodeIfNotEqu -
1982 : */
1983 :
1984 : static void PerformCodeIfNotEqu (unsigned int quad);
1985 :
1986 : /*
1987 : IsValidExpressionRelOp - declare left and right constants (if they are not already declared).
1988 : Check whether left and right are expression compatible.
1989 : */
1990 :
1991 : static bool IsValidExpressionRelOp (unsigned int quad, bool isin);
1992 :
1993 : /*
1994 : CodeIfEqu - codes the quadruple if op1 = op2 then goto op3
1995 : */
1996 :
1997 : static void CodeIfEqu (unsigned int quad);
1998 :
1999 : /*
2000 : CodeIfNotEqu - codes the quadruple if op1 # op2 then goto op3
2001 : */
2002 :
2003 : static void CodeIfNotEqu (unsigned int quad);
2004 :
2005 : /*
2006 : MixTypes3 - returns a type compatible from, low, high, var.
2007 : */
2008 :
2009 : static unsigned int MixTypes3 (unsigned int low, unsigned int high, unsigned int var, unsigned int tokenno);
2010 :
2011 : /*
2012 : BuildIfVarInConstValue - if var in constsetvalue then goto trueexit
2013 : */
2014 :
2015 : static void BuildIfVarInConstValue (location_t location, unsigned int tokenno, M2ALU_PtrToValue constsetvalue, unsigned int var, unsigned int trueexit);
2016 :
2017 : /*
2018 : BuildIfNotVarInConstValue - if not (var in constsetvalue) then goto trueexit
2019 : */
2020 :
2021 : static void BuildIfNotVarInConstValue (location_t location, unsigned int tokenno, unsigned int quad, M2ALU_PtrToValue constsetvalue, unsigned int var, unsigned int trueexit);
2022 :
2023 : /*
2024 : SetWideIfIn - if M2WIDESET.In (set, element) then goto branch end.
2025 : */
2026 :
2027 : static void SetWideIfIn (location_t location, unsigned int tokenno, bool invertCondition, unsigned int settype, unsigned int element, unsigned int set, unsigned int branch);
2028 :
2029 : /*
2030 : CodeNarrowIfIn -
2031 : */
2032 :
2033 : static void CodeNarrowIfIn (location_t location, unsigned int settype, bool invertCondition, unsigned int element, unsigned int set, unsigned int branch);
2034 :
2035 : /*
2036 : CodeIfInLower - code the quadruple: if element in set then goto branch.
2037 : The invertCondition can be set to TRUE to handle CodeIfNotIn.
2038 : */
2039 :
2040 : static void CodeIfInLower (unsigned int tokenno, unsigned int quad, bool invertCondition, unsigned int element, unsigned int set, unsigned int branch);
2041 :
2042 : /*
2043 : PerformCodeIfIn -
2044 : */
2045 :
2046 : static void PerformCodeIfIn (unsigned int quad, bool invert);
2047 :
2048 : /*
2049 : CodeIfIn - code the quadruple: if element in set then goto branch.
2050 : */
2051 :
2052 : static void CodeIfIn (unsigned int quad);
2053 :
2054 : /*
2055 : CodeIfNotIn - code the quadruple: if not (element in set) then goto branch.
2056 : */
2057 :
2058 : static void CodeIfNotIn (unsigned int quad);
2059 : static void CodeIndrX (unsigned int quad);
2060 :
2061 : /*
2062 : CodeXIndr - operands for XIndrOp are: left type right.
2063 : *left = right. The second operand is the type of the data being
2064 : indirectly copied.
2065 : */
2066 :
2067 : static void CodeXIndr (unsigned int quad);
2068 :
2069 : /*
2070 : InitBuiltinSyms -
2071 : */
2072 :
2073 : static void InitBuiltinSyms (unsigned int tok);
2074 :
2075 : /*
2076 : gdbhook - a debugger convenience hook.
2077 : */
2078 :
2079 : static void gdbhook (void);
2080 :
2081 : /*
2082 : BreakWhenQuadTranslated - to be called interactively by gdb.
2083 : */
2084 :
2085 : static void BreakWhenQuadTranslated (unsigned int quad);
2086 :
2087 : /*
2088 : CheckBreak - if quad = BreakQuad then call gdbhook.
2089 : */
2090 :
2091 : static void CheckBreak (unsigned int quad);
2092 :
2093 : /*
2094 : Init -
2095 : */
2096 :
2097 : static void Init (void);
2098 :
2099 :
2100 : /*
2101 : ErrorMessageDecl - emit an error message together with declaration fragments of left
2102 : and right if they are parameters or variables.
2103 : */
2104 :
2105 12 : static void ErrorMessageDecl (unsigned int tok, const char *message_, unsigned int _message_high, unsigned int left, unsigned int right, bool iserror)
2106 : {
2107 12 : char message[_message_high+1];
2108 :
2109 : /* make a local copy of each unbounded array. */
2110 12 : memcpy (message, message_, _message_high+1);
2111 :
2112 12 : M2MetaError_MetaErrorT2 (tok, (const char *) message, _message_high, left, right);
2113 12 : M2MetaError_MetaErrorDecl (left, iserror);
2114 12 : M2MetaError_MetaErrorDecl (right, iserror);
2115 12 : }
2116 :
2117 :
2118 : /*
2119 : IsExportedGcc - returns TRUE if this symbol should be (as far as the middle/backend of GCC)
2120 : is concerned, exported.
2121 : */
2122 :
2123 110259 : static bool IsExportedGcc (unsigned int sym)
2124 : {
2125 110259 : unsigned int scope;
2126 :
2127 : /* Has a procedure been overridden as public? */
2128 110259 : if ((SymbolTable_IsProcedure (sym)) && (SymbolTable_IsPublic (sym)))
2129 : {
2130 : return true;
2131 : }
2132 : /* Check for whole program. */
2133 62011 : if (M2Options_WholeProgram)
2134 : {
2135 15816 : scope = SymbolTable_GetScope (sym);
2136 31632 : while (scope != SymbolTable_NulSym)
2137 : {
2138 15816 : if (SymbolTable_IsDefImp (scope))
2139 : {
2140 15792 : return SymbolTable_IsExported (scope, sym);
2141 : }
2142 24 : else if (SymbolTable_IsModule (scope))
2143 : {
2144 : /* avoid dangling else. */
2145 : return false;
2146 : }
2147 0 : scope = SymbolTable_GetScope (scope);
2148 : }
2149 0 : M2Error_InternalError ((const char *) "expecting scope to eventually reach a module or defimp symbol", 61);
2150 : }
2151 : else
2152 : {
2153 : /* Otherwise it is public if it were exported. */
2154 46195 : return SymbolTable_IsExported (SymbolTable_GetMainModule (), sym);
2155 : }
2156 : ReturnException ("/home/worker/buildworker/tiber-lcov/build/gcc/m2/gm2-compiler/M2GenGCC.def", 20, 1);
2157 : __builtin_unreachable ();
2158 : }
2159 :
2160 :
2161 : /*
2162 : IsCompilingMainModule -
2163 : */
2164 :
2165 198604 : static bool IsCompilingMainModule (unsigned int sym)
2166 : {
2167 339808 : while ((sym != SymbolTable_NulSym) && ((SymbolTable_GetMainModule ()) != sym))
2168 : {
2169 141204 : sym = SymbolTable_GetModuleScope (sym);
2170 : }
2171 198604 : return sym != SymbolTable_NulSym;
2172 : /* static analysis guarentees a RETURN statement will be used before here. */
2173 : __builtin_unreachable ();
2174 : }
2175 :
2176 :
2177 : /*
2178 : CodeLastForIterator - call PerformLastForIterator allowing for
2179 : a non constant last iterator value.
2180 : */
2181 :
2182 840 : static void CodeLastForIterator (unsigned int quad)
2183 : {
2184 0 : PerformLastForIterator (quad, (M2GCCDeclare_WalkAction) {(M2GCCDeclare_WalkAction_t) NoWalkProcedure}, false);
2185 840 : }
2186 :
2187 :
2188 : /*
2189 : FoldLastForIterator - call PerformLastForIterator providing
2190 : all operands are constant and are known by GCC.
2191 : */
2192 :
2193 15326 : static void FoldLastForIterator (unsigned int quad, M2GCCDeclare_WalkAction p)
2194 : {
2195 15326 : M2Quads_QuadOperator op;
2196 15326 : unsigned int e1;
2197 15326 : unsigned int e2;
2198 15326 : unsigned int op1;
2199 15326 : unsigned int tuple;
2200 15326 : unsigned int incr;
2201 :
2202 15326 : M2Quads_GetQuad (quad, &op, &op1, &tuple, &incr);
2203 15326 : M2Debug_Assert (SymbolTable_IsTuple (tuple));
2204 15326 : e1 = SymbolTable_GetNth (tuple, 1);
2205 15326 : e2 = SymbolTable_GetNth (tuple, 2);
2206 15326 : if (((((((SymbolTable_IsConst (op1)) && (SymbolTable_IsConst (e1))) && (SymbolTable_IsConst (e2))) && (SymbolTable_IsConst (incr))) && (SymbolConversion_GccKnowsAbout (e1))) && (SymbolConversion_GccKnowsAbout (e2))) && (SymbolConversion_GccKnowsAbout (incr)))
2207 : {
2208 1722 : PerformLastForIterator (quad, p, true);
2209 : }
2210 15326 : }
2211 :
2212 2562 : static void PerformLastForIterator (unsigned int quad, M2GCCDeclare_WalkAction p, bool constant)
2213 : {
2214 2562 : bool success;
2215 2562 : bool constExpr;
2216 2562 : bool overflowChecking;
2217 2562 : M2Quads_QuadOperator op;
2218 2562 : unsigned int lastpos;
2219 2562 : unsigned int op1pos;
2220 2562 : unsigned int op2pos;
2221 2562 : unsigned int incrpos;
2222 2562 : unsigned int last;
2223 2562 : unsigned int tuple;
2224 2562 : unsigned int incr;
2225 2562 : unsigned int e1;
2226 2562 : unsigned int e2;
2227 2562 : tree lasttree;
2228 2562 : tree e1tree;
2229 2562 : tree e2tree;
2230 2562 : tree expr;
2231 2562 : tree incrtree;
2232 2562 : location_t location;
2233 :
2234 : /*
2235 : FoldLastForIterator - generates code to calculate the last iterator value
2236 : in a for loop. It examines the increment constant
2237 : and generates different code depending whether it is
2238 : negative or positive.
2239 : */
2240 2562 : M2Quads_GetQuadOtok (quad, &lastpos, &op, &last, &tuple, &incr, &overflowChecking, &constExpr, &op1pos, &op2pos, &incrpos);
2241 2562 : M2GCCDeclare_DeclareConstant (incrpos, incr);
2242 2562 : lasttree = SymbolConversion_Mod2Gcc (last);
2243 2562 : success = true;
2244 2562 : if (SymbolTable_IsConst (incr))
2245 : {
2246 : /* avoid dangling else. */
2247 2562 : incrtree = SymbolConversion_Mod2Gcc (incr);
2248 2562 : location = M2LexBuf_TokenToLocation (lastpos);
2249 2562 : e1 = SymbolTable_GetNth (tuple, 1);
2250 2562 : e2 = SymbolTable_GetNth (tuple, 2);
2251 2562 : e1tree = SymbolConversion_Mod2Gcc (e1);
2252 2562 : e2tree = SymbolConversion_Mod2Gcc (e2);
2253 2562 : if ((m2expr_CompareTrees (incrtree, m2expr_GetIntegerZero (location))) == 0)
2254 : {
2255 6 : M2MetaError_MetaErrorT0 (lastpos, (const char *) "the {%kFOR} loop step value must not be zero", 44);
2256 6 : M2MetaError_MetaErrorDecl (incr, true);
2257 6 : NoChange = false;
2258 6 : M2Quads_SubQuad (quad);
2259 6 : success = false;
2260 : }
2261 2556 : else if ((m2expr_CompareTrees (incrtree, m2expr_GetIntegerZero (location))) > 0)
2262 : {
2263 : /* avoid dangling else. */
2264 : /* If incr > 0 then LastIterator := ((e2-e1) DIV incr) * incr + e1. */
2265 2346 : expr = m2expr_BuildSub (location, e2tree, e1tree, false);
2266 2346 : incrtree = m2convert_BuildConvert (location, m2type_GetTreeType (expr), incrtree, false);
2267 2346 : if (m2expr_TreeOverflow (incrtree))
2268 : {
2269 0 : M2MetaError_MetaErrorT0 (lastpos, (const char *) "the intemediate calculation for the last iterator value in the {%kFOR} loop has caused an overflow", 98);
2270 0 : NoChange = false;
2271 0 : M2Quads_SubQuad (quad);
2272 0 : success = false;
2273 : }
2274 : else
2275 : {
2276 2346 : expr = m2expr_BuildDivFloor (location, expr, incrtree, false);
2277 2346 : expr = m2expr_BuildMult (location, expr, incrtree, false);
2278 2346 : expr = m2expr_BuildAdd (location, expr, e1tree, false);
2279 : }
2280 : }
2281 : else
2282 : {
2283 : /* avoid dangling else. */
2284 : /* Else use LastIterator := e1 - ((e1-e2) DIV PositiveBy) * PositiveBy
2285 : to avoid unsigned div signed arithmetic. */
2286 210 : expr = m2expr_BuildSub (location, e1tree, e2tree, false);
2287 210 : incrtree = m2convert_BuildConvert (location, m2type_GetM2ZType (), incrtree, false);
2288 210 : incrtree = m2expr_BuildNegate (location, incrtree, false);
2289 210 : incrtree = m2convert_BuildConvert (location, m2type_GetTreeType (expr), incrtree, false);
2290 210 : if (m2expr_TreeOverflow (incrtree))
2291 : {
2292 0 : M2MetaError_MetaErrorT0 (lastpos, (const char *) "the intemediate calculation for the last iterator value in the {%kFOR} loop has caused an overflow", 98);
2293 0 : NoChange = false;
2294 0 : M2Quads_SubQuad (quad);
2295 0 : success = false;
2296 : }
2297 : else
2298 : {
2299 210 : expr = m2expr_BuildSub (location, e1tree, e2tree, false);
2300 210 : expr = m2expr_BuildDivFloor (location, expr, incrtree, false);
2301 210 : expr = m2expr_BuildMult (location, expr, incrtree, false);
2302 210 : expr = m2expr_BuildSub (location, e1tree, expr, false);
2303 : }
2304 : }
2305 2562 : if (success)
2306 : {
2307 : /* avoid gcc warning by using compound statement even if not strictly necessary. */
2308 2556 : if (SymbolTable_IsConst (last))
2309 : {
2310 1716 : SymbolConversion_AddModGcc (last, expr);
2311 1716 : (*p.proc) (last);
2312 1716 : NoChange = false;
2313 1716 : M2Quads_SubQuad (quad);
2314 : }
2315 : else
2316 : {
2317 840 : M2Debug_Assert (! constant);
2318 840 : m2statement_BuildAssignmentStatement (location, lasttree, expr);
2319 : }
2320 : }
2321 : }
2322 : else
2323 : {
2324 0 : M2MetaError_MetaErrorT1 (lastpos, (const char *) "the value {%1Ead} in the {%kBY} clause of the {%kFOR} loop must be constant", 75, incr);
2325 0 : M2MetaError_MetaErrorDecl (incr, true);
2326 0 : NoChange = false;
2327 0 : M2Quads_SubQuad (quad);
2328 : }
2329 2562 : }
2330 :
2331 :
2332 : /*
2333 : CodeStatement - A multi-way decision call depending on the current
2334 : quadruple.
2335 : */
2336 :
2337 4311506 : static void CodeStatement (unsigned int q)
2338 : {
2339 4311506 : M2Quads_QuadOperator op;
2340 4311506 : unsigned int op1;
2341 4311506 : unsigned int op2;
2342 4311506 : unsigned int op3;
2343 4311506 : location_t location;
2344 :
2345 4311506 : InitBuiltinSyms (M2LexBuf_BuiltinTokenNo);
2346 4311506 : M2Quads_GetQuad (q, &op, &op1, &op2, &op3);
2347 4311506 : CheckBreak (q);
2348 4311506 : if (op == M2Quads_StatementNoteOp)
2349 : {
2350 502117 : FoldStatementNote (op3); /* Will change CurrentQuadToken using op3. */
2351 : }
2352 : else
2353 : {
2354 3809389 : CurrentQuadToken = M2Quads_QuadToTokenNo (q);
2355 : }
2356 4311506 : location = M2LexBuf_TokenToLocation (CurrentQuadToken);
2357 4311506 : CheckReferenced (q, op);
2358 4311506 : if (M2Options_GetDebugTraceQuad ())
2359 : {
2360 0 : M2Printf_printf0 ((const char *) "building: ", 10);
2361 0 : M2Quads_DisplayQuad (q);
2362 : }
2363 4311506 : switch (op)
2364 : {
2365 162164 : case M2Quads_StartDefFileOp:
2366 162164 : CodeStartDefFile (op3);
2367 162164 : break;
2368 :
2369 83566 : case M2Quads_StartModFileOp:
2370 83566 : CodeStartModFile (op3);
2371 83566 : break;
2372 :
2373 83974 : case M2Quads_ModuleScopeOp:
2374 83974 : CodeModuleScope (op3);
2375 83974 : break;
2376 :
2377 245730 : case M2Quads_EndFileOp:
2378 245730 : CodeEndFile ();
2379 245730 : break;
2380 :
2381 83974 : case M2Quads_InitStartOp:
2382 83974 : CodeInitStart (op3, IsCompilingMainModule (op3));
2383 83974 : break;
2384 :
2385 83974 : case M2Quads_InitEndOp:
2386 83974 : CodeInitEnd (op3, IsCompilingMainModule (op3));
2387 83974 : break;
2388 :
2389 15328 : case M2Quads_FinallyStartOp:
2390 15328 : CodeFinallyStart (op3, IsCompilingMainModule (op3));
2391 15328 : break;
2392 :
2393 15328 : case M2Quads_FinallyEndOp:
2394 15328 : CodeFinallyEnd (op3, IsCompilingMainModule (op3));
2395 15328 : break;
2396 :
2397 79597 : case M2Quads_NewLocalVarOp:
2398 79597 : CodeNewLocalVar (op1, op3);
2399 79597 : break;
2400 :
2401 79591 : case M2Quads_KillLocalVarOp:
2402 79591 : CodeKillLocalVar (op3);
2403 79591 : break;
2404 :
2405 79603 : case M2Quads_ProcedureScopeOp:
2406 79603 : CodeProcedureScope (op3);
2407 79603 : break;
2408 :
2409 : case M2Quads_ReturnOp:
2410 : break;
2411 :
2412 27853 : case M2Quads_ReturnValueOp:
2413 27853 : CodeReturnValue (q); /* Not used as return is achieved by KillLocalVar. */
2414 27853 : break;
2415 :
2416 2950 : case M2Quads_TryOp:
2417 2950 : CodeTry ();
2418 2950 : break;
2419 :
2420 322 : case M2Quads_ThrowOp:
2421 322 : CodeThrow (op3);
2422 322 : break;
2423 :
2424 2950 : case M2Quads_CatchBeginOp:
2425 2950 : CodeCatchBegin ();
2426 2950 : break;
2427 :
2428 2950 : case M2Quads_CatchEndOp:
2429 2950 : CodeCatchEnd ();
2430 2950 : break;
2431 :
2432 156 : case M2Quads_RetryOp:
2433 156 : CodeRetry (op3);
2434 156 : break;
2435 :
2436 : case M2Quads_DummyOp:
2437 : break;
2438 :
2439 54 : case M2Quads_InitAddressOp:
2440 54 : CodeInitAddress (q, op1, op2, op3);
2441 54 : break;
2442 :
2443 196070 : case M2Quads_BecomesOp:
2444 196070 : CodeBecomes (q);
2445 196070 : break;
2446 :
2447 35144 : case M2Quads_ArithAddOp:
2448 35144 : case M2Quads_AddOp:
2449 35144 : CodeAddChecked (q, op2, op3);
2450 35144 : break;
2451 :
2452 10632 : case M2Quads_SubOp:
2453 10632 : CodeSubChecked (q, op2, op3);
2454 10632 : break;
2455 :
2456 11518 : case M2Quads_MultOp:
2457 11518 : CodeMultChecked (q, op2, op3);
2458 11518 : break;
2459 :
2460 1986 : case M2Quads_DivM2Op:
2461 1986 : CodeDivM2Checked (q, op2, op3);
2462 1986 : break;
2463 :
2464 2124 : case M2Quads_ModM2Op:
2465 2124 : CodeModM2Checked (q, op2, op3);
2466 2124 : break;
2467 :
2468 734 : case M2Quads_DivTruncOp:
2469 734 : CodeDivTrunc (q, op2, op3);
2470 734 : break;
2471 :
2472 0 : case M2Quads_ModTruncOp:
2473 0 : CodeModTrunc (q, op2, op3);
2474 0 : break;
2475 :
2476 0 : case M2Quads_DivCeilOp:
2477 0 : CodeDivCeil (q, op2, op3);
2478 0 : break;
2479 :
2480 0 : case M2Quads_ModCeilOp:
2481 0 : CodeModCeil (q, op2, op3);
2482 0 : break;
2483 :
2484 0 : case M2Quads_DivFloorOp:
2485 0 : CodeDivFloor (q, op2, op3);
2486 0 : break;
2487 :
2488 0 : case M2Quads_ModFloorOp:
2489 0 : CodeModFloor (q, op2, op3);
2490 0 : break;
2491 :
2492 46253 : case M2Quads_GotoOp:
2493 46253 : CodeGoto (op3);
2494 46253 : break;
2495 :
2496 1226 : case M2Quads_InclOp:
2497 1226 : CodeIncl (q);
2498 1226 : break;
2499 :
2500 764 : case M2Quads_ExclOp:
2501 764 : CodeExcl (q);
2502 764 : break;
2503 :
2504 996 : case M2Quads_NegateOp:
2505 996 : CodeNegateChecked (q);
2506 996 : break;
2507 :
2508 840 : case M2Quads_LastForIteratorOp:
2509 840 : CodeLastForIterator (q);
2510 840 : break;
2511 :
2512 676 : case M2Quads_LogicalShiftOp:
2513 676 : CodeSetShift (q);
2514 676 : break;
2515 :
2516 406 : case M2Quads_LogicalRotateOp:
2517 406 : CodeSetRotate (q);
2518 406 : break;
2519 :
2520 754 : case M2Quads_LogicalOrOp:
2521 754 : CodeSetOr (q);
2522 754 : break;
2523 :
2524 284 : case M2Quads_LogicalAndOp:
2525 284 : CodeSetAnd (q);
2526 284 : break;
2527 :
2528 124 : case M2Quads_LogicalXorOp:
2529 124 : CodeSetSymmetricDifference (q);
2530 124 : break;
2531 :
2532 66 : case M2Quads_LogicalDiffOp:
2533 66 : CodeSetLogicalDifference (q);
2534 66 : break;
2535 :
2536 3988 : case M2Quads_IfLessOp:
2537 3988 : CodeIfLess (q);
2538 3988 : break;
2539 :
2540 21878 : case M2Quads_IfEquOp:
2541 21878 : CodeIfEqu (q);
2542 21878 : break;
2543 :
2544 33301 : case M2Quads_IfNotEquOp:
2545 33301 : CodeIfNotEqu (q);
2546 33301 : break;
2547 :
2548 7172 : case M2Quads_IfGreEquOp:
2549 7172 : CodeIfGreEqu (q);
2550 7172 : break;
2551 :
2552 5984 : case M2Quads_IfLessEquOp:
2553 5984 : CodeIfLessEqu (q);
2554 5984 : break;
2555 :
2556 4832 : case M2Quads_IfGreOp:
2557 4832 : CodeIfGre (q);
2558 4832 : break;
2559 :
2560 536 : case M2Quads_IfInOp:
2561 536 : CodeIfIn (q);
2562 536 : break;
2563 :
2564 1946 : case M2Quads_IfNotInOp:
2565 1946 : CodeIfNotIn (q);
2566 1946 : break;
2567 :
2568 16981 : case M2Quads_IndrXOp:
2569 16981 : CodeIndrX (q);
2570 16981 : break;
2571 :
2572 43588 : case M2Quads_XIndrOp:
2573 43588 : CodeXIndr (q);
2574 43588 : break;
2575 :
2576 213259 : case M2Quads_CallOp:
2577 213259 : CodeCall (CurrentQuadToken, op3);
2578 213259 : break;
2579 :
2580 600344 : case M2Quads_ParamOp:
2581 600344 : CodeParam (q);
2582 600344 : break;
2583 :
2584 67945 : case M2Quads_FunctValueOp:
2585 67945 : CodeFunctValue (location, op1);
2586 67945 : break;
2587 :
2588 191385 : case M2Quads_AddrOp:
2589 191385 : CodeAddr (CurrentQuadToken, q, op1, op3);
2590 191385 : break;
2591 :
2592 0 : case M2Quads_SizeOp:
2593 0 : CodeSize (op1, op3);
2594 0 : break;
2595 :
2596 34561 : case M2Quads_UnboundedOp:
2597 34561 : CodeUnbounded (op1, op3);
2598 34561 : break;
2599 :
2600 143644 : case M2Quads_RecordFieldOp:
2601 143644 : CodeRecordField (op1, op2, op3);
2602 143644 : break;
2603 :
2604 39905 : case M2Quads_HighOp:
2605 39905 : CodeHigh (op1, op2, op3);
2606 39905 : break;
2607 :
2608 47900 : case M2Quads_ArrayOp:
2609 47900 : CodeArray (op1, op2, op3);
2610 47900 : break;
2611 :
2612 0 : case M2Quads_ElementSizeOp:
2613 0 : M2Error_InternalError ((const char *) "ElementSizeOp is expected to have been folded via constant evaluation", 69);
2614 51884 : break;
2615 :
2616 51884 : case M2Quads_ConvertOp:
2617 51884 : CodeConvert (q, op1, op2, op3);
2618 51884 : break;
2619 :
2620 1320 : case M2Quads_CoerceOp:
2621 1320 : CodeCoerce (q, op1, op2, op3);
2622 1320 : break;
2623 :
2624 126 : case M2Quads_CastOp:
2625 126 : CodeCast (q, op1, op2, op3);
2626 126 : break;
2627 :
2628 330 : case M2Quads_StandardFunctionOp:
2629 330 : CodeStandardFunction (q, op1, op2, op3);
2630 330 : break;
2631 :
2632 420 : case M2Quads_SavePriorityOp:
2633 420 : CodeSavePriority (op1, op2, op3);
2634 420 : break;
2635 :
2636 412 : case M2Quads_RestorePriorityOp:
2637 412 : CodeRestorePriority (op1, op2, op3);
2638 412 : break;
2639 :
2640 27 : case M2Quads_InlineOp:
2641 27 : CodeInline (q);
2642 27 : break;
2643 :
2644 502117 : case M2Quads_StatementNoteOp:
2645 502117 : CodeStatementNote (op3);
2646 502117 : break;
2647 :
2648 : case M2Quads_CodeOnOp:
2649 : break;
2650 :
2651 : case M2Quads_CodeOffOp:
2652 : break;
2653 :
2654 : case M2Quads_ProfileOnOp:
2655 : break;
2656 :
2657 : case M2Quads_ProfileOffOp:
2658 : break;
2659 :
2660 : case M2Quads_OptimizeOnOp:
2661 : break;
2662 :
2663 : case M2Quads_OptimizeOffOp:
2664 : break;
2665 :
2666 827964 : case M2Quads_RangeCheckOp:
2667 827964 : CodeRange (op3); /* The following make no sense with gcc. */
2668 827964 : break;
2669 :
2670 981 : case M2Quads_ErrorOp:
2671 981 : CodeError (op3);
2672 981 : break;
2673 :
2674 2950 : case M2Quads_SaveExceptionOp:
2675 2950 : CodeSaveException (op1, op3);
2676 2950 : break;
2677 :
2678 2890 : case M2Quads_RestoreExceptionOp:
2679 2890 : CodeRestoreException (op1, op3);
2680 2890 : break;
2681 :
2682 :
2683 0 : default:
2684 0 : M2Error_WriteFormat1 ((const char *) "quadruple %d not yet implemented", 32, (const unsigned char *) &q, (sizeof (q)-1));
2685 0 : M2Error_InternalError ((const char *) "quadruple not implemented yet", 29);
2686 4311494 : break;
2687 : }
2688 4311494 : LastOperator = op;
2689 4311494 : }
2690 :
2691 :
2692 : /*
2693 : FindSize - given a Modula-2 symbol sym return a gcc tree
2694 : constant representing the storage size in bytes.
2695 : */
2696 :
2697 30970 : static tree FindSize (unsigned int tokenno, unsigned int sym)
2698 : {
2699 30970 : location_t location;
2700 :
2701 30970 : location = M2LexBuf_TokenToLocation (tokenno);
2702 30970 : if (SymbolTable_IsConstString (sym))
2703 : {
2704 6432 : M2Debug_Assert (SymbolTable_IsConstStringKnown (sym));
2705 6432 : M2ALU_PushCard (SymbolTable_GetStringLength (tokenno, sym));
2706 6432 : return M2ALU_PopIntegerTree ();
2707 : }
2708 24538 : else if (SymbolTable_IsSizeSolved (sym))
2709 : {
2710 : /* avoid dangling else. */
2711 20420 : SymbolTable_PushSize (sym);
2712 20420 : return M2ALU_PopIntegerTree ();
2713 : }
2714 : else
2715 : {
2716 : /* avoid dangling else. */
2717 4118 : if (SymbolConversion_GccKnowsAbout (sym))
2718 : {
2719 4118 : if ((SymbolTable_IsVar (sym)) && (SymbolTable_IsVariableSSA (sym)))
2720 : {
2721 0 : sym = SymbolTable_GetType (sym);
2722 : }
2723 4118 : M2ALU_PushIntegerTree (m2expr_BuildSize (location, SymbolConversion_Mod2Gcc (sym), false));
2724 4118 : SymbolTable_PopSize (sym);
2725 4118 : SymbolTable_PushSize (sym);
2726 4118 : return M2ALU_PopIntegerTree ();
2727 : }
2728 0 : else if ((SymbolTable_IsVar (sym)) && (SymbolConversion_GccKnowsAbout (SymbolTable_GetType (sym))))
2729 : {
2730 : /* avoid dangling else. */
2731 0 : M2ALU_PushIntegerTree (m2expr_BuildSize (location, SymbolConversion_Mod2Gcc (SymbolTable_GetType (sym)), false));
2732 0 : return M2ALU_PopIntegerTree ();
2733 : }
2734 : else
2735 : {
2736 : /* avoid dangling else. */
2737 0 : M2Error_InternalError ((const char *) "expecting gcc to already know about this symbol", 47);
2738 : }
2739 : }
2740 : ReturnException ("/home/worker/buildworker/tiber-lcov/build/gcc/m2/gm2-compiler/M2GenGCC.def", 20, 1);
2741 : __builtin_unreachable ();
2742 : }
2743 :
2744 :
2745 : /*
2746 : FindType - returns the type of, Sym, if Sym is a TYPE then return Sym otherwise return GetType(Sym)
2747 : */
2748 :
2749 250324 : static unsigned int FindType (unsigned int Sym)
2750 : {
2751 250324 : if (SymbolTable_IsType (Sym))
2752 : {
2753 : return Sym;
2754 : }
2755 : else
2756 : {
2757 250324 : return SymbolTable_GetType (Sym);
2758 : }
2759 : /* static analysis guarentees a RETURN statement will be used before here. */
2760 : __builtin_unreachable ();
2761 : }
2762 :
2763 :
2764 : /*
2765 : BuildTreeFromInterface - generates a GCC tree from an interface definition.
2766 : */
2767 :
2768 54 : static tree BuildTreeFromInterface (unsigned int sym)
2769 : {
2770 54 : unsigned int tok;
2771 54 : unsigned int i;
2772 54 : NameKey_Name name;
2773 54 : unsigned int str;
2774 54 : unsigned int obj;
2775 54 : tree gccName;
2776 54 : tree asmTree;
2777 :
2778 54 : asmTree = (tree) (NULL);
2779 54 : if (sym != SymbolTable_NulSym)
2780 : {
2781 : i = 1;
2782 63 : do {
2783 63 : SymbolTable_GetRegInterface (sym, i, &tok, &name, &str, &obj);
2784 63 : if (str != SymbolTable_NulSym)
2785 : {
2786 : /* avoid gcc warning by using compound statement even if not strictly necessary. */
2787 33 : if (SymbolTable_IsConstString (str))
2788 : {
2789 : /* avoid dangling else. */
2790 33 : M2GCCDeclare_DeclareConstant (tok, obj);
2791 33 : if (name == NameKey_NulName)
2792 : {
2793 : gccName = NULL;
2794 : }
2795 : else
2796 : {
2797 6 : gccName = m2decl_BuildCStringConstant (const_cast <const char * > (static_cast <char * > (NameKey_KeyToCharStar (name))), static_cast<int> (NameKey_LengthKey (name)));
2798 : }
2799 33 : asmTree = m2type_ChainOnParamValue (asmTree, gccName, M2GCCDeclare_PromoteToCString (tok, str), m2tree_skip_const_decl (SymbolConversion_Mod2Gcc (obj)));
2800 33 : if (DebugTokPos)
2801 : {
2802 : M2Error_WarnStringAt (DynamicStrings_InitString ((const char *) "input expression", 16), tok);
2803 : }
2804 : }
2805 : else
2806 : {
2807 0 : M2MetaError_MetaErrorT1 (tok, (const char *) "a constraint to the GNU ASM statement must be a constant string and not a {%1Edv}", 81, str);
2808 : }
2809 : }
2810 63 : i += 1;
2811 63 : } while (! ((str == SymbolTable_NulSym) && (obj == SymbolTable_NulSym)));
2812 : }
2813 54 : return asmTree;
2814 : /* static analysis guarentees a RETURN statement will be used before here. */
2815 : __builtin_unreachable ();
2816 : }
2817 :
2818 :
2819 : /*
2820 : BuildTrashTreeFromInterface - generates a GCC string tree from an interface definition.
2821 : */
2822 :
2823 27 : static tree BuildTrashTreeFromInterface (unsigned int sym)
2824 : {
2825 27 : unsigned int tok;
2826 27 : unsigned int i;
2827 27 : unsigned int str;
2828 27 : unsigned int obj;
2829 27 : NameKey_Name name;
2830 27 : tree asmTree;
2831 :
2832 27 : asmTree = (tree) (NULL);
2833 27 : if (sym != SymbolTable_NulSym)
2834 : {
2835 : i = 1;
2836 6 : do {
2837 6 : SymbolTable_GetRegInterface (sym, i, &tok, &name, &str, &obj);
2838 6 : if (str != SymbolTable_NulSym)
2839 : {
2840 : /* avoid gcc warning by using compound statement even if not strictly necessary. */
2841 0 : if (SymbolTable_IsConstString (str))
2842 : {
2843 : /* avoid dangling else. */
2844 0 : asmTree = m2type_AddStringToTreeList (asmTree, M2GCCDeclare_PromoteToCString (tok, str));
2845 0 : if (DebugTokPos)
2846 : {
2847 : M2Error_WarnStringAt (DynamicStrings_InitString ((const char *) "trash expression", 16), tok);
2848 : }
2849 : }
2850 : else
2851 : {
2852 0 : M2MetaError_MetaErrorT1 (tok, (const char *) "a constraint to the GNU ASM statement must be a constant string and not a {%1Edv}", 81, str);
2853 : }
2854 : }
2855 6 : i += 1;
2856 6 : } while (! ((str == SymbolTable_NulSym) && (obj == SymbolTable_NulSym)));
2857 : }
2858 27 : return asmTree;
2859 : /* static analysis guarentees a RETURN statement will be used before here. */
2860 : __builtin_unreachable ();
2861 : }
2862 :
2863 :
2864 : /*
2865 : CodeInline - InlineOp is a quadruple which has the following format:
2866 :
2867 : InlineOp NulSym NulSym Sym
2868 : */
2869 :
2870 27 : static void CodeInline (unsigned int quad)
2871 : {
2872 27 : bool constExpr;
2873 27 : bool overflowChecking;
2874 27 : M2Quads_QuadOperator op;
2875 27 : unsigned int op1;
2876 27 : unsigned int op2;
2877 27 : unsigned int GnuAsm;
2878 27 : unsigned int op1pos;
2879 27 : unsigned int op2pos;
2880 27 : unsigned int op3pos;
2881 27 : unsigned int asmpos;
2882 27 : unsigned int string;
2883 27 : tree inputs;
2884 27 : tree outputs;
2885 27 : tree trash;
2886 27 : tree labels;
2887 27 : location_t location;
2888 :
2889 27 : M2Quads_GetQuadOtok (quad, &asmpos, &op, &op1, &op2, &GnuAsm, &overflowChecking, &constExpr, &op1pos, &op2pos, &op3pos);
2890 27 : location = M2LexBuf_TokenToLocation (asmpos);
2891 27 : inputs = BuildTreeFromInterface (SymbolTable_GetGnuAsmInput (GnuAsm));
2892 27 : outputs = BuildTreeFromInterface (SymbolTable_GetGnuAsmOutput (GnuAsm));
2893 27 : trash = BuildTrashTreeFromInterface (SymbolTable_GetGnuAsmTrash (GnuAsm));
2894 27 : labels = NULL; /* At present it makes no sence for Modula-2 to jump to a label,
2895 : given that labels are not allowed in Modula-2. */
2896 27 : string = SymbolTable_GetGnuAsm (GnuAsm); /* At present it makes no sence for Modula-2 to jump to a label,
2897 : given that labels are not allowed in Modula-2. */
2898 27 : m2statement_BuildAsm (location, M2GCCDeclare_PromoteToCString (SymbolTable_GetDeclaredMod (string), string), SymbolTable_IsGnuAsmVolatile (GnuAsm), SymbolTable_IsGnuAsmSimple (GnuAsm), inputs, outputs, trash, labels);
2899 27 : }
2900 :
2901 :
2902 : /*
2903 : FoldStatementNote - set CurrentQuadToken to tokennno.
2904 : */
2905 :
2906 10490501 : static void FoldStatementNote (unsigned int tokenno)
2907 : {
2908 10490501 : CurrentQuadToken = tokenno;
2909 502117 : }
2910 :
2911 :
2912 : /*
2913 : CodeStatementNote - set CurrentQuadToken to tokennno and
2914 : add a statement note.
2915 : */
2916 :
2917 502117 : static void CodeStatementNote (unsigned int tokenno)
2918 : {
2919 502117 : if (Debugging)
2920 : {
2921 : M2MetaError_MetaErrorT0 (tokenno, (const char *) "{%W} statement note", 19);
2922 : }
2923 502117 : CurrentQuadToken = tokenno;
2924 502117 : m2block_addStmtNote (M2LexBuf_TokenToLocation (tokenno));
2925 502117 : }
2926 :
2927 :
2928 : /*
2929 : FoldRange - attempts to fold the range test.
2930 : --fixme-- complete this.
2931 : */
2932 :
2933 14390657 : static void FoldRange (unsigned int tokenno, unsigned int quad, unsigned int rangeno)
2934 : {
2935 0 : M2Range_FoldRangeCheck (tokenno, quad, rangeno); /* p: WalkAction; */
2936 14390495 : }
2937 :
2938 :
2939 : /*
2940 : CodeSaveException - op1 := op3(TRUE)
2941 : */
2942 :
2943 2950 : static void CodeSaveException (unsigned int des, unsigned int exceptionProcedure)
2944 : {
2945 2950 : tree functValue;
2946 2950 : location_t location;
2947 :
2948 2950 : location = M2LexBuf_TokenToLocation (CurrentQuadToken);
2949 2950 : m2statement_BuildParam (location, SymbolConversion_Mod2Gcc (M2Base_True));
2950 2950 : m2statement_BuildFunctionCallTree (location, SymbolConversion_Mod2Gcc (exceptionProcedure), SymbolConversion_Mod2Gcc (SymbolTable_GetType (exceptionProcedure)));
2951 2950 : functValue = m2statement_BuildFunctValue (location, SymbolConversion_Mod2Gcc (des));
2952 2950 : m2type_AddStatement (location, functValue);
2953 2950 : }
2954 :
2955 :
2956 : /*
2957 : CodeRestoreException - op1 := op3(op1).
2958 : */
2959 :
2960 2890 : static void CodeRestoreException (unsigned int des, unsigned int exceptionProcedure)
2961 : {
2962 2890 : tree functValue;
2963 2890 : location_t location;
2964 :
2965 2890 : location = M2LexBuf_TokenToLocation (CurrentQuadToken);
2966 2890 : m2statement_BuildParam (location, SymbolConversion_Mod2Gcc (des));
2967 2890 : m2statement_BuildFunctionCallTree (location, SymbolConversion_Mod2Gcc (exceptionProcedure), SymbolConversion_Mod2Gcc (SymbolTable_GetType (exceptionProcedure)));
2968 2890 : functValue = m2statement_BuildFunctValue (location, SymbolConversion_Mod2Gcc (des));
2969 2890 : m2type_AddStatement (location, functValue);
2970 2890 : }
2971 :
2972 :
2973 : /*
2974 : PushScope -
2975 : */
2976 :
2977 409301 : static void PushScope (unsigned int sym)
2978 : {
2979 0 : M2StackWord_PushWord (ScopeStack, sym);
2980 0 : }
2981 :
2982 :
2983 : /*
2984 : PopScope -
2985 : */
2986 :
2987 79591 : static void PopScope (void)
2988 : {
2989 79591 : unsigned int sym;
2990 :
2991 79591 : sym = static_cast<unsigned int> (M2StackWord_PopWord (ScopeStack));
2992 79591 : M2Debug_Assert (sym != SymbolTable_NulSym);
2993 79591 : }
2994 :
2995 :
2996 : /*
2997 : GetActiveScope -
2998 : */
2999 :
3000 3296 : static unsigned int GetActiveScope (void)
3001 : {
3002 3296 : if (M2StackWord_IsEmptyWord (ScopeStack))
3003 : {
3004 0 : M2Error_InternalError ((const char *) "not expecting scope stack to be empty", 37);
3005 : }
3006 3296 : return static_cast<unsigned int> (M2StackWord_PeepWord (ScopeStack, 1));
3007 : /* static analysis guarentees a RETURN statement will be used before here. */
3008 : __builtin_unreachable ();
3009 : }
3010 :
3011 :
3012 : /*
3013 : GetCurrentScopeDescription - returns a description of the current scope.
3014 : */
3015 :
3016 828945 : static DynamicStrings_String GetCurrentScopeDescription (void)
3017 : {
3018 828945 : unsigned int sym;
3019 828945 : DynamicStrings_String n;
3020 :
3021 828945 : if (M2StackWord_IsEmptyWord (ScopeStack))
3022 : {
3023 0 : M2Error_InternalError ((const char *) "not expecting scope stack to be empty", 37);
3024 : }
3025 : else
3026 : {
3027 828945 : sym = static_cast<unsigned int> (M2StackWord_PeepWord (ScopeStack, 1));
3028 828945 : n = DynamicStrings_Mark (DynamicStrings_InitStringCharStar (NameKey_KeyToCharStar (SymbolTable_GetSymName (sym))));
3029 828945 : if (SymbolTable_IsDefImp (sym))
3030 : {
3031 4400 : return FormatStrings_Sprintf1 (DynamicStrings_Mark (DynamicStrings_InitString ((const char *) "implementation module %s", 24)), (const unsigned char *) &n, (sizeof (n)-1));
3032 : }
3033 824545 : else if (SymbolTable_IsModule (sym))
3034 : {
3035 : /* avoid dangling else. */
3036 53744 : if (SymbolTable_IsInnerModule (sym))
3037 : {
3038 84 : return FormatStrings_Sprintf1 (DynamicStrings_Mark (DynamicStrings_InitString ((const char *) "inner module %s", 15)), (const unsigned char *) &n, (sizeof (n)-1));
3039 : }
3040 : else
3041 : {
3042 53660 : return FormatStrings_Sprintf1 (DynamicStrings_Mark (DynamicStrings_InitString ((const char *) "program module %s", 17)), (const unsigned char *) &n, (sizeof (n)-1));
3043 : }
3044 : }
3045 770801 : else if (SymbolTable_IsProcedure (sym))
3046 : {
3047 : /* avoid dangling else. */
3048 770801 : if (SymbolTable_IsProcedureNested (sym))
3049 : {
3050 396 : return FormatStrings_Sprintf1 (DynamicStrings_Mark (DynamicStrings_InitString ((const char *) "nested procedure %s", 19)), (const unsigned char *) &n, (sizeof (n)-1));
3051 : }
3052 : else
3053 : {
3054 770405 : return FormatStrings_Sprintf1 (DynamicStrings_Mark (DynamicStrings_InitString ((const char *) "procedure %s", 12)), (const unsigned char *) &n, (sizeof (n)-1));
3055 : }
3056 : }
3057 : else
3058 : {
3059 : /* avoid dangling else. */
3060 0 : M2Error_InternalError ((const char *) "unexpected scope symbol", 23);
3061 : }
3062 : }
3063 : ReturnException ("/home/worker/buildworker/tiber-lcov/build/gcc/m2/gm2-compiler/M2GenGCC.def", 20, 1);
3064 : __builtin_unreachable ();
3065 : }
3066 :
3067 :
3068 : /*
3069 : CodeRange - encode the range test associated with op3.
3070 : */
3071 :
3072 827964 : static void CodeRange (unsigned int rangeId)
3073 : {
3074 827964 : M2Range_CodeRangeCheck (rangeId, GetCurrentScopeDescription ());
3075 827958 : }
3076 :
3077 :
3078 : /*
3079 : CodeError - encode the error test associated with op3.
3080 : */
3081 :
3082 981 : static void CodeError (unsigned int errorId)
3083 : {
3084 : /* We would like to test whether this position is in the same basicblock
3085 : as any known entry point. If so we could emit an error message.
3086 : */
3087 981 : m2type_AddStatement (M2LexBuf_TokenToLocation (CurrentQuadToken), M2Range_CodeErrorCheck (errorId, GetCurrentScopeDescription (), static_cast<DynamicStrings_String> (NULL)));
3088 981 : }
3089 :
3090 :
3091 : /*
3092 : CodeModuleScope - ModuleScopeOp is a quadruple which has the following
3093 : format:
3094 :
3095 : ModuleScopeOp _ _ moduleSym
3096 :
3097 : Its purpose is to reset the source file to another
3098 : file, hence all line numbers emitted with the
3099 : generated code will be relative to this source file.
3100 : */
3101 :
3102 83974 : static void CodeModuleScope (unsigned int moduleSym)
3103 : {
3104 83974 : PushScope (moduleSym);
3105 83974 : }
3106 :
3107 :
3108 : /*
3109 : CodeStartModFile - StartModFileOp is a quadruple which has the following
3110 : format:
3111 :
3112 : StartModFileOp _ _ moduleSym
3113 :
3114 : A new source file has been encountered therefore
3115 : set LastLine to 1.
3116 : Call pushGlobalScope.
3117 : */
3118 :
3119 83566 : static void CodeStartModFile (unsigned int moduleSym)
3120 : {
3121 83566 : m2block_pushGlobalScope ();
3122 83566 : LastLine = 1;
3123 83566 : PushScope (moduleSym);
3124 83566 : }
3125 :
3126 :
3127 : /*
3128 : CodeStartDefFile - StartDefFileOp is a quadruple with the following
3129 : format:
3130 :
3131 : StartDefFileOp _ _ moduleSym
3132 :
3133 : A new source file has been encountered therefore
3134 : set LastLine to 1.
3135 : Call pushGlobalScope.
3136 : */
3137 :
3138 162164 : static void CodeStartDefFile (unsigned int moduleSym)
3139 : {
3140 162164 : m2block_pushGlobalScope ();
3141 162164 : PushScope (moduleSym);
3142 162164 : LastLine = 1;
3143 162164 : }
3144 :
3145 :
3146 : /*
3147 : CodeEndFile - pops the GlobalScope.
3148 : */
3149 :
3150 245730 : static void CodeEndFile (void)
3151 : {
3152 245730 : m2block_popGlobalScope ();
3153 245730 : }
3154 :
3155 :
3156 : /*
3157 : CallInnerInit - produce a call to inner module initialization routine.
3158 : */
3159 :
3160 408 : static void CallInnerInit (unsigned int moduleSym)
3161 : {
3162 408 : location_t location;
3163 408 : unsigned int ctor;
3164 408 : unsigned int init;
3165 408 : unsigned int fini;
3166 408 : unsigned int dep;
3167 :
3168 408 : location = M2LexBuf_TokenToLocation (CurrentQuadToken);
3169 408 : SymbolTable_GetModuleCtors (moduleSym, &ctor, &init, &fini, &dep);
3170 408 : m2statement_BuildCallInner (location, SymbolConversion_Mod2Gcc (init));
3171 408 : }
3172 :
3173 :
3174 : /*
3175 : CallInnerFinally - produce a call to inner module finalization routine.
3176 : */
3177 :
3178 264 : static void CallInnerFinally (unsigned int moduleSym)
3179 : {
3180 264 : location_t location;
3181 264 : unsigned int ctor;
3182 264 : unsigned int init;
3183 264 : unsigned int fini;
3184 264 : unsigned int dep;
3185 :
3186 264 : location = M2LexBuf_TokenToLocation (CurrentQuadToken);
3187 264 : SymbolTable_GetModuleCtors (moduleSym, &ctor, &init, &fini, &dep);
3188 264 : m2statement_BuildCallInner (location, SymbolConversion_Mod2Gcc (fini));
3189 264 : }
3190 :
3191 :
3192 : /*
3193 : CodeInitStart - emits starting code before the main BEGIN END of the
3194 : current module.
3195 : */
3196 :
3197 83974 : static void CodeInitStart (unsigned int moduleSym, bool CompilingMainModule)
3198 : {
3199 83974 : location_t location;
3200 83974 : unsigned int ctor;
3201 83974 : unsigned int init;
3202 83974 : unsigned int fini;
3203 83974 : unsigned int dep;
3204 :
3205 83974 : if (CompilingMainModule || M2Options_WholeProgram)
3206 : {
3207 15328 : location = M2LexBuf_TokenToLocation (CurrentQuadToken);
3208 15328 : SymbolTable_GetModuleCtors (moduleSym, &ctor, &init, &fini, &dep);
3209 15328 : m2statement_BuildStartFunctionCode (location, SymbolConversion_Mod2Gcc (init), IsExportedGcc (init), false);
3210 15328 : SymbolTable_ForeachInnerModuleDo (moduleSym, (SymbolKey_PerformOperation) {(SymbolKey_PerformOperation_t) CallInnerInit});
3211 : }
3212 83974 : }
3213 :
3214 :
3215 : /*
3216 : CodeInitEnd - emits terminating code after the main BEGIN END of the
3217 : current module.
3218 : */
3219 :
3220 83974 : static void CodeInitEnd (unsigned int moduleSym, bool CompilingMainModule)
3221 : {
3222 83974 : location_t location;
3223 83974 : unsigned int ctor;
3224 83974 : unsigned int init;
3225 83974 : unsigned int fini;
3226 83974 : unsigned int dep;
3227 :
3228 83974 : if (CompilingMainModule || M2Options_WholeProgram)
3229 : {
3230 15328 : location = M2LexBuf_TokenToLocation (SymbolTable_GetDeclaredMod (moduleSym));
3231 15328 : SymbolTable_GetModuleCtors (moduleSym, &ctor, &init, &fini, &dep);
3232 15328 : m2block_finishFunctionDecl (location, SymbolConversion_Mod2Gcc (init));
3233 15328 : m2statement_BuildEndFunctionCode (location, SymbolConversion_Mod2Gcc (init), SymbolTable_IsModuleWithinProcedure (moduleSym));
3234 : }
3235 83974 : }
3236 :
3237 :
3238 : /*
3239 : CodeFinallyStart - emits starting code before the main BEGIN END of the
3240 : current module.
3241 : */
3242 :
3243 15328 : static void CodeFinallyStart (unsigned int moduleSym, bool CompilingMainModule)
3244 : {
3245 15328 : location_t location;
3246 15328 : unsigned int ctor;
3247 15328 : unsigned int init;
3248 15328 : unsigned int fini;
3249 15328 : unsigned int dep;
3250 :
3251 15328 : if (CompilingMainModule || M2Options_WholeProgram)
3252 : {
3253 15328 : location = M2LexBuf_TokenToLocation (CurrentQuadToken);
3254 15328 : SymbolTable_GetModuleCtors (moduleSym, &ctor, &init, &fini, &dep);
3255 15328 : m2statement_BuildStartFunctionCode (location, SymbolConversion_Mod2Gcc (fini), IsExportedGcc (fini), false);
3256 15328 : SymbolTable_ForeachInnerModuleDo (moduleSym, (SymbolKey_PerformOperation) {(SymbolKey_PerformOperation_t) CallInnerFinally});
3257 : }
3258 15328 : }
3259 :
3260 :
3261 : /*
3262 : CodeFinallyEnd - emits terminating code after the main BEGIN END of the
3263 : current module. It also creates the scaffold if the
3264 : cflag was not present.
3265 : */
3266 :
3267 15328 : static void CodeFinallyEnd (unsigned int moduleSym, bool CompilingMainModule)
3268 : {
3269 15328 : location_t location;
3270 15328 : unsigned int tokenpos;
3271 15328 : unsigned int ctor;
3272 15328 : unsigned int init;
3273 15328 : unsigned int fini;
3274 15328 : unsigned int dep;
3275 :
3276 15328 : if (CompilingMainModule || M2Options_WholeProgram)
3277 : {
3278 15328 : tokenpos = SymbolTable_GetDeclaredMod (moduleSym);
3279 15328 : location = M2LexBuf_TokenToLocation (tokenpos);
3280 15328 : SymbolTable_GetModuleCtors (moduleSym, &ctor, &init, &fini, &dep);
3281 15328 : m2block_finishFunctionDecl (location, SymbolConversion_Mod2Gcc (fini));
3282 15328 : m2statement_BuildEndFunctionCode (location, SymbolConversion_Mod2Gcc (fini), SymbolTable_IsModuleWithinProcedure (moduleSym));
3283 : }
3284 15328 : }
3285 :
3286 :
3287 : /*
3288 : GetAddressOfUnbounded - returns the address of the unbounded array contents.
3289 : */
3290 :
3291 5514 : static tree GetAddressOfUnbounded (location_t location, unsigned int param)
3292 : {
3293 5514 : unsigned int UnboundedType;
3294 :
3295 5514 : UnboundedType = SymbolTable_GetType (param);
3296 5514 : M2Debug_Assert (SymbolTable_IsUnbounded (UnboundedType));
3297 5514 : return m2convert_BuildConvert (M2LexBuf_TokenToLocation (SymbolTable_GetDeclaredMod (param)), m2type_GetPointerType (), m2expr_BuildComponentRef (location, SymbolConversion_Mod2Gcc (param), SymbolConversion_Mod2Gcc (SymbolTable_GetUnboundedAddressOffset (UnboundedType))), false);
3298 : /* static analysis guarentees a RETURN statement will be used before here. */
3299 : __builtin_unreachable ();
3300 : }
3301 :
3302 :
3303 : /*
3304 : GetSizeOfHighFromUnbounded - returns a Tree containing the value of
3305 : param.HIGH * sizeof(unboundedType).
3306 : The number of legal bytes this array
3307 : occupies.
3308 : */
3309 :
3310 5514 : static tree GetSizeOfHighFromUnbounded (unsigned int tokenno, unsigned int param)
3311 : {
3312 5514 : tree t;
3313 5514 : unsigned int UnboundedType;
3314 5514 : unsigned int ArrayType;
3315 5514 : unsigned int i;
3316 5514 : unsigned int n;
3317 5514 : location_t location;
3318 :
3319 5514 : location = M2LexBuf_TokenToLocation (tokenno);
3320 5514 : UnboundedType = SymbolTable_GetType (param);
3321 5514 : M2Debug_Assert (SymbolTable_IsUnbounded (UnboundedType));
3322 5514 : ArrayType = SymbolTable_GetType (UnboundedType);
3323 5514 : i = 1;
3324 5514 : n = SymbolTable_GetDimension (UnboundedType);
3325 5514 : t = m2expr_GetCardinalOne (location);
3326 16632 : while (i <= n)
3327 : {
3328 5604 : t = m2expr_BuildMult (location, m2expr_BuildAdd (location, M2GenGCC_GetHighFromUnbounded (location, i, param), m2expr_GetCardinalOne (location), false), t, false);
3329 : /* Remember we must add one as a[HIGH(a)] is the last accessible element of the array. */
3330 5604 : i += 1;
3331 : }
3332 5514 : return m2convert_BuildConvert (location, m2type_GetCardinalType (), m2expr_BuildMult (location, t, m2convert_BuildConvert (location, m2type_GetCardinalType (), FindSize (tokenno, ArrayType), false), false), false);
3333 : /* static analysis guarentees a RETURN statement will be used before here. */
3334 : __builtin_unreachable ();
3335 : }
3336 :
3337 :
3338 : /*
3339 : MaybeDebugBuiltinAlloca - if DebugBuiltins is set
3340 : then call Builtins.alloca_trace
3341 : else call Builtins.alloca.
3342 : */
3343 :
3344 5514 : static tree MaybeDebugBuiltinAlloca (location_t location, unsigned int tok, tree high)
3345 : {
3346 5514 : tree call;
3347 5514 : tree memptr;
3348 5514 : tree func;
3349 :
3350 5514 : if (M2Options_DebugBuiltins)
3351 : {
3352 0 : func = SymbolConversion_Mod2Gcc (SymbolTable_FromModuleGetSym (tok, NameKey_MakeKey ((const char *) "alloca_trace", 12), M2Batch_MakeDefinitionSource (tok, NameKey_MakeKey ((const char *) "Builtins", 8))));
3353 0 : call = m2builtins_BuiltInAlloca (location, high);
3354 0 : m2statement_SetLastFunction (call);
3355 0 : memptr = m2statement_BuildFunctValue (location, call);
3356 0 : call = m2statement_BuildCall2 (location, func, m2type_GetPointerType (), memptr, high);
3357 : }
3358 : else
3359 : {
3360 5514 : call = m2builtins_BuiltInAlloca (location, high);
3361 : }
3362 5514 : m2statement_SetLastFunction (call);
3363 5514 : return m2statement_BuildFunctValue (location, call);
3364 : /* static analysis guarentees a RETURN statement will be used before here. */
3365 : __builtin_unreachable ();
3366 : }
3367 :
3368 :
3369 : /*
3370 : MaybeDebugBuiltinMemcpy - if DebugBuiltins is set
3371 : then call memcpy
3372 : else call Builtins.memcpy.
3373 : */
3374 :
3375 6984 : static tree MaybeDebugBuiltinMemcpy (location_t location, tree src, tree dest, tree nbytes)
3376 : {
3377 6984 : tree call;
3378 6984 : tree func;
3379 :
3380 6984 : if (M2Options_DebugBuiltins)
3381 : {
3382 0 : func = SymbolConversion_Mod2Gcc (Memcpy);
3383 0 : call = m2statement_BuildCall3 (location, func, m2type_GetPointerType (), src, dest, nbytes);
3384 : }
3385 : else
3386 : {
3387 6984 : call = m2builtins_BuiltinMemCopy (location, src, dest, nbytes);
3388 : }
3389 6984 : m2statement_SetLastFunction (call);
3390 6984 : return m2statement_BuildFunctValue (location, call);
3391 : /* static analysis guarentees a RETURN statement will be used before here. */
3392 : __builtin_unreachable ();
3393 : }
3394 :
3395 :
3396 : /*
3397 : MakeCopyUse - make a copy of the unbounded array and alter all references
3398 : from the old unbounded array to the new unbounded array.
3399 : The parameter, param, contains a RECORD
3400 : ArrayAddress: ADDRESS ;
3401 : ArrayHigh : CARDINAL ;
3402 : END
3403 : we simply declare a new array of size, ArrayHigh
3404 : and set ArrayAddress to the address of the copy.
3405 :
3406 : Remember ArrayHigh == sizeof(Array)-sizeof(typeof(array))
3407 : so we add 1 for the size and add 1 for a possible <nul>
3408 : */
3409 :
3410 5514 : static void MakeCopyUse (unsigned int tokenno, unsigned int param)
3411 : {
3412 5514 : location_t location;
3413 5514 : unsigned int UnboundedType;
3414 5514 : tree Addr;
3415 5514 : tree High;
3416 5514 : tree NewArray;
3417 :
3418 5514 : location = M2LexBuf_TokenToLocation (tokenno);
3419 5514 : UnboundedType = SymbolTable_GetType (param);
3420 5514 : M2Debug_Assert (SymbolTable_IsUnbounded (UnboundedType));
3421 5514 : High = GetSizeOfHighFromUnbounded (tokenno, param);
3422 5514 : Addr = GetAddressOfUnbounded (location, param);
3423 5514 : NewArray = MaybeDebugBuiltinAlloca (location, tokenno, High);
3424 5514 : NewArray = MaybeDebugBuiltinMemcpy (location, NewArray, Addr, High);
3425 : /* Now assign param.Addr := ADR(NewArray). */
3426 5514 : m2statement_BuildAssignmentStatement (location, m2expr_BuildComponentRef (location, SymbolConversion_Mod2Gcc (param), SymbolConversion_Mod2Gcc (SymbolTable_GetUnboundedAddressOffset (UnboundedType))), NewArray);
3427 5514 : }
3428 :
3429 :
3430 : /*
3431 : GetParamAddress - returns the address of parameter, param.
3432 : */
3433 :
3434 0 : static tree GetParamAddress (location_t location, unsigned int proc, unsigned int param)
3435 : {
3436 0 : unsigned int sym;
3437 0 : unsigned int type;
3438 :
3439 0 : if (SymbolTable_IsParameter (param))
3440 : {
3441 0 : type = SymbolTable_GetType (param);
3442 0 : sym = SymbolTable_GetLocalSym (proc, SymbolTable_GetSymName (param));
3443 0 : if (SymbolTable_IsUnbounded (type))
3444 : {
3445 0 : return GetAddressOfUnbounded (location, sym);
3446 : }
3447 : else
3448 : {
3449 0 : M2Debug_Assert ((SymbolTable_GetMode (sym)) == SymbolTable_LeftValue);
3450 0 : return SymbolConversion_Mod2Gcc (sym);
3451 : }
3452 : }
3453 : else
3454 : {
3455 0 : M2Debug_Assert (SymbolTable_IsVar (param));
3456 0 : M2Debug_Assert ((SymbolTable_GetMode (param)) == SymbolTable_LeftValue);
3457 0 : return SymbolConversion_Mod2Gcc (param);
3458 : }
3459 : /* static analysis guarentees a RETURN statement will be used before here. */
3460 : __builtin_unreachable ();
3461 : }
3462 :
3463 :
3464 : /*
3465 : IsUnboundedWrittenTo - returns TRUE if the unbounded parameter
3466 : might be written to, or if -funbounded-by-reference
3467 : was _not_ specified.
3468 : */
3469 :
3470 5514 : static bool IsUnboundedWrittenTo (unsigned int proc, unsigned int param)
3471 : {
3472 5514 : DynamicStrings_String f;
3473 5514 : unsigned int l;
3474 5514 : unsigned int sym;
3475 5514 : NameKey_Name n1;
3476 5514 : NameKey_Name n2;
3477 :
3478 5514 : sym = SymbolTable_GetLocalSym (proc, SymbolTable_GetSymName (param));
3479 5514 : if (sym == SymbolTable_NulSym)
3480 : {
3481 0 : M2Error_InternalError ((const char *) "should find symbol in table", 27);
3482 : }
3483 : else
3484 : {
3485 5514 : if (M2Options_UnboundedByReference)
3486 : {
3487 0 : if ((! (SymbolTable_GetVarWritten (sym))) && M2Options_VerboseUnbounded)
3488 : {
3489 0 : n1 = SymbolTable_GetSymName (sym);
3490 0 : n2 = SymbolTable_GetSymName (proc);
3491 0 : f = M2LexBuf_FindFileNameFromToken (SymbolTable_GetDeclaredMod (sym), 0);
3492 0 : l = M2LexBuf_TokenToLineNo (SymbolTable_GetDeclaredMod (sym), 0);
3493 0 : M2Printf_printf4 ((const char *) "%s:%d:non VAR unbounded parameter %a in procedure %a does not need to be copied\\n", 81, (const unsigned char *) &f, (sizeof (f)-1), (const unsigned char *) &l, (sizeof (l)-1), (const unsigned char *) &n1, (sizeof (n1)-1), (const unsigned char *) &n2, (sizeof (n2)-1));
3494 : }
3495 0 : return SymbolTable_GetVarWritten (sym);
3496 : }
3497 : else
3498 : {
3499 : return true;
3500 : }
3501 : }
3502 : ReturnException ("/home/worker/buildworker/tiber-lcov/build/gcc/m2/gm2-compiler/M2GenGCC.def", 20, 1);
3503 : __builtin_unreachable ();
3504 : }
3505 :
3506 :
3507 : /*
3508 : GetParamSize - returns the size in bytes of, param.
3509 : */
3510 :
3511 0 : static tree GetParamSize (unsigned int tokenno, unsigned int param)
3512 : {
3513 0 : M2Debug_Assert ((SymbolTable_IsVar (param)) || (SymbolTable_IsParameter (param)));
3514 0 : if (SymbolTable_IsUnbounded (param))
3515 : {
3516 0 : return GetSizeOfHighFromUnbounded (tokenno, param);
3517 : }
3518 : else
3519 : {
3520 0 : return m2expr_BuildSize (M2LexBuf_TokenToLocation (tokenno), SymbolConversion_Mod2Gcc (SymbolTable_GetType (param)), false);
3521 : }
3522 : /* static analysis guarentees a RETURN statement will be used before here. */
3523 : __builtin_unreachable ();
3524 : }
3525 :
3526 :
3527 : /*
3528 : DoIsIntersection - jumps to, tLabel, if the ranges i1..i2 j1..j2 overlap
3529 : else jump to, fLabel.
3530 : */
3531 :
3532 0 : static void DoIsIntersection (unsigned int tokenno, tree ta, tree tb, tree tc, tree td, DynamicStrings_String tLabel, DynamicStrings_String fLabel)
3533 : {
3534 0 : location_t location;
3535 :
3536 0 : location = M2LexBuf_TokenToLocation (tokenno);
3537 : /*
3538 : if (ta>td) OR (tb<tc)
3539 : then
3540 : goto fLabel
3541 : else
3542 : goto tLabel
3543 : fi
3544 : */
3545 0 : m2statement_IfExprJump (location, m2expr_BuildGreaterThan (location, ta, td), reinterpret_cast <char * > (DynamicStrings_string (fLabel)));
3546 0 : m2statement_IfExprJump (location, m2expr_BuildLessThan (location, tb, tc), reinterpret_cast <char * > (DynamicStrings_string (fLabel)));
3547 0 : m2statement_BuildGoto (location, reinterpret_cast <char * > (DynamicStrings_string (tLabel)));
3548 0 : if (CascadedDebugging)
3549 : {
3550 : M2Printf_printf1 ((const char *) "label used %s\\n", 15, (const unsigned char *) &tLabel, (sizeof (tLabel)-1));
3551 : M2Printf_printf1 ((const char *) "label used %s\\n", 15, (const unsigned char *) &fLabel, (sizeof (fLabel)-1));
3552 : }
3553 0 : }
3554 :
3555 :
3556 : /*
3557 : BuildCascadedIfThenElsif - mustCheck contains a list of variables which
3558 : must be checked against the address of (proc, param, i).
3559 : If the address matches we make a copy of the unbounded
3560 : parameter (proc, param) and quit further checking.
3561 : */
3562 :
3563 0 : static void BuildCascadedIfThenElsif (unsigned int tokenno, Lists_List mustCheck, unsigned int proc, unsigned int param)
3564 : {
3565 0 : tree ta;
3566 0 : tree tb;
3567 0 : tree tc;
3568 0 : tree td;
3569 0 : unsigned int n;
3570 0 : unsigned int j;
3571 0 : DynamicStrings_String tLabel;
3572 0 : DynamicStrings_String fLabel;
3573 0 : DynamicStrings_String nLabel;
3574 0 : location_t location;
3575 :
3576 0 : location = M2LexBuf_TokenToLocation (tokenno);
3577 0 : n = Lists_NoOfItemsInList (mustCheck);
3578 : /* We want a sequence of if then elsif statements. */
3579 0 : if (n > 0)
3580 : {
3581 0 : UnboundedLabelNo += 1;
3582 0 : j = 1;
3583 0 : ta = GetAddressOfUnbounded (location, param);
3584 0 : tb = m2convert_BuildConvert (M2LexBuf_TokenToLocation (tokenno), m2type_GetPointerType (), m2expr_BuildAddAddress (location, ta, GetSizeOfHighFromUnbounded (tokenno, param)), false);
3585 0 : while (j <= n)
3586 : {
3587 0 : if (j > 1)
3588 : {
3589 0 : nLabel = CreateLabelProcedureN (proc, (const char *) "n", 1, UnboundedLabelNo, j);
3590 0 : if (CascadedDebugging)
3591 : {
3592 : M2Printf_printf1 ((const char *) "label declared %s\\n", 19, (const unsigned char *) &nLabel, (sizeof (nLabel)-1));
3593 : }
3594 0 : m2statement_DeclareLabel (location, reinterpret_cast <char * > (DynamicStrings_string (nLabel)));
3595 : }
3596 0 : tc = GetParamAddress (location, proc, Lists_GetItemFromList (mustCheck, j));
3597 0 : td = m2convert_BuildConvert (M2LexBuf_TokenToLocation (tokenno), m2type_GetPointerType (), m2expr_BuildAddAddress (location, tc, GetParamSize (tokenno, param)), false);
3598 0 : tLabel = CreateLabelProcedureN (proc, (const char *) "t", 1, UnboundedLabelNo, j+1);
3599 0 : fLabel = CreateLabelProcedureN (proc, (const char *) "f", 1, UnboundedLabelNo, j+1);
3600 0 : DoIsIntersection (tokenno, ta, tb, tc, td, tLabel, fLabel);
3601 0 : if (CascadedDebugging)
3602 : {
3603 : M2Printf_printf1 ((const char *) "label declared %s\\n", 19, (const unsigned char *) &tLabel, (sizeof (tLabel)-1));
3604 : }
3605 0 : m2statement_DeclareLabel (location, reinterpret_cast <char * > (DynamicStrings_string (tLabel)));
3606 0 : MakeCopyUse (tokenno, param);
3607 0 : if (j < n)
3608 : {
3609 0 : nLabel = CreateLabelProcedureN (proc, (const char *) "n", 1, UnboundedLabelNo, n+1);
3610 0 : m2statement_BuildGoto (location, reinterpret_cast <char * > (DynamicStrings_string (nLabel)));
3611 0 : if (CascadedDebugging)
3612 : {
3613 : M2Printf_printf1 ((const char *) "goto %s\\n", 9, (const unsigned char *) &nLabel, (sizeof (nLabel)-1));
3614 : }
3615 : }
3616 0 : if (CascadedDebugging)
3617 : {
3618 : M2Printf_printf1 ((const char *) "label declared %s\\n", 19, (const unsigned char *) &fLabel, (sizeof (fLabel)-1));
3619 : }
3620 0 : m2statement_DeclareLabel (location, reinterpret_cast <char * > (DynamicStrings_string (fLabel)));
3621 0 : j += 1;
3622 : }
3623 : }
3624 0 : }
3625 :
3626 :
3627 : /*
3628 : CheckUnboundedNonVarParameter - if non var unbounded parameter is written to
3629 : then
3630 : make a copy of the contents of this parameter
3631 : and use the copy
3632 : else if param
3633 : is type compatible with any parameter, symv
3634 : and at runtime its address matches symv
3635 : then
3636 : make a copy of the contents of this parameter
3637 : and use the copy
3638 : fi
3639 : */
3640 :
3641 5514 : static void CheckUnboundedNonVarParameter (unsigned int tokenno, Lists_List trashed, unsigned int proc, unsigned int param)
3642 : {
3643 5514 : Lists_List mustCheck;
3644 5514 : unsigned int paramTrashed;
3645 5514 : unsigned int n;
3646 5514 : unsigned int j;
3647 5514 : DynamicStrings_String f;
3648 5514 : unsigned int l;
3649 5514 : NameKey_Name n1;
3650 5514 : NameKey_Name n2;
3651 :
3652 5514 : if (IsUnboundedWrittenTo (proc, param))
3653 : {
3654 5514 : MakeCopyUse (tokenno, param);
3655 : }
3656 : else
3657 : {
3658 0 : Lists_InitList (&mustCheck);
3659 0 : n = Lists_NoOfItemsInList (trashed);
3660 0 : j = 1;
3661 0 : while (j <= n)
3662 : {
3663 0 : paramTrashed = static_cast<unsigned int> (Lists_GetItemFromList (trashed, j));
3664 0 : if (M2Base_IsAssignmentCompatible (SymbolTable_GetLowestType (param), SymbolTable_GetLowestType (paramTrashed)))
3665 : {
3666 : /* We must check whether this unbounded parameter has the same
3667 : address as the trashed parameter. */
3668 0 : if (M2Options_VerboseUnbounded)
3669 : {
3670 0 : n1 = SymbolTable_GetSymName (paramTrashed);
3671 0 : n2 = SymbolTable_GetSymName (proc);
3672 0 : f = M2LexBuf_FindFileNameFromToken (SymbolTable_GetDeclaredMod (paramTrashed), 0);
3673 0 : l = M2LexBuf_TokenToLineNo (SymbolTable_GetDeclaredMod (paramTrashed), 0);
3674 0 : M2Printf_printf4 ((const char *) "%s:%d:must check at runtime the address of parameter, %a, in procedure, %a, whose contents will be trashed\\n", 108, (const unsigned char *) &f, (sizeof (f)-1), (const unsigned char *) &l, (sizeof (l)-1), (const unsigned char *) &n1, (sizeof (n1)-1), (const unsigned char *) &n2, (sizeof (n2)-1));
3675 0 : n1 = SymbolTable_GetSymName (param);
3676 0 : n2 = SymbolTable_GetSymName (paramTrashed);
3677 0 : M2Printf_printf4 ((const char *) "%s:%d:against address of parameter, %a, possibly resulting in a copy of parameter, %a\\n", 87, (const unsigned char *) &f, (sizeof (f)-1), (const unsigned char *) &l, (sizeof (l)-1), (const unsigned char *) &n1, (sizeof (n1)-1), (const unsigned char *) &n2, (sizeof (n2)-1));
3678 : }
3679 0 : Lists_PutItemIntoList (mustCheck, paramTrashed);
3680 : }
3681 0 : j += 1;
3682 : }
3683 : /* Now we build a sequence of if then { elsif then } end to check addresses. */
3684 0 : BuildCascadedIfThenElsif (tokenno, mustCheck, proc, param);
3685 0 : Lists_KillList (&mustCheck);
3686 : }
3687 5514 : }
3688 :
3689 :
3690 : /*
3691 : IsParameterWritten - returns TRUE if a parameter, sym, is written to.
3692 : */
3693 :
3694 91509 : static bool IsParameterWritten (unsigned int proc, unsigned int sym)
3695 : {
3696 91509 : if (SymbolTable_IsParameter (sym))
3697 : {
3698 91509 : sym = SymbolTable_GetLocalSym (proc, SymbolTable_GetSymName (sym));
3699 : }
3700 91509 : if (SymbolTable_IsVar (sym))
3701 : {
3702 : /* Unbounded arrays will appear as vars. */
3703 91509 : return SymbolTable_GetVarWritten (sym);
3704 : }
3705 0 : M2Error_InternalError ((const char *) "expecting IsVar to return TRUE", 30);
3706 : ReturnException ("/home/worker/buildworker/tiber-lcov/build/gcc/m2/gm2-compiler/M2GenGCC.def", 20, 1);
3707 : __builtin_unreachable ();
3708 : }
3709 :
3710 :
3711 : /*
3712 : SaveNonVarUnboundedParameters - for each var parameter, symv, do
3713 : not just unbounded var parameters, but _all_
3714 : parameters
3715 : if symv is written to
3716 : then
3717 : add symv to a compile list
3718 : fi
3719 : done
3720 :
3721 : for each parameter of procedure, symu, do
3722 : if non var unbounded parameter is written to
3723 : then
3724 : make a copy of the contents of this parameter
3725 : and use the copy
3726 : else if
3727 : symu is type compatible with any parameter, symv
3728 : and at runtime its address matches symv
3729 : then
3730 : make a copy of the contents of this parameter
3731 : and use the copy
3732 : fi
3733 : done
3734 : */
3735 :
3736 79597 : static void SaveNonVarUnboundedParameters (unsigned int tokenno, unsigned int proc)
3737 : {
3738 79597 : unsigned int i;
3739 79597 : unsigned int p;
3740 79597 : Lists_List trashed;
3741 79597 : DynamicStrings_String f;
3742 79597 : unsigned int sym;
3743 79597 : unsigned int l;
3744 79597 : NameKey_Name n1;
3745 79597 : NameKey_Name n2;
3746 :
3747 79597 : Lists_InitList (&trashed);
3748 79597 : i = 1;
3749 79597 : p = SymbolTable_NoOfParamAny (proc);
3750 250703 : while (i <= p)
3751 : {
3752 91509 : sym = SymbolTable_GetNthParamAny (proc, i);
3753 91509 : if (IsParameterWritten (proc, sym))
3754 : {
3755 6612 : if (M2Options_VerboseUnbounded)
3756 : {
3757 0 : n1 = SymbolTable_GetSymName (sym);
3758 0 : n2 = SymbolTable_GetSymName (proc);
3759 0 : f = M2LexBuf_FindFileNameFromToken (SymbolTable_GetDeclaredMod (sym), 0);
3760 0 : l = M2LexBuf_TokenToLineNo (SymbolTable_GetDeclaredMod (sym), 0);
3761 0 : M2Printf_printf4 ((const char *) "%s:%d:parameter, %a, in procedure, %a, is trashed\\n", 51, (const unsigned char *) &f, (sizeof (f)-1), (const unsigned char *) &l, (sizeof (l)-1), (const unsigned char *) &n1, (sizeof (n1)-1), (const unsigned char *) &n2, (sizeof (n2)-1));
3762 : }
3763 6612 : Lists_PutItemIntoList (trashed, sym);
3764 : }
3765 91509 : i += 1;
3766 : }
3767 : /* Now see whether we need to copy any unbounded array parameters. */
3768 79597 : i = 1;
3769 79597 : p = SymbolTable_NoOfParamAny (proc);
3770 250703 : while (i <= p)
3771 : {
3772 91509 : if ((SymbolTable_IsUnboundedParamAny (proc, i)) && (! (SymbolTable_IsVarParamAny (proc, i))))
3773 : {
3774 5514 : CheckUnboundedNonVarParameter (tokenno, trashed, proc, SymbolTable_GetNth (proc, i));
3775 : }
3776 91509 : i += 1;
3777 : }
3778 79597 : Lists_KillList (&trashed);
3779 79597 : }
3780 :
3781 :
3782 : /*
3783 : AutoInitVariable -
3784 : */
3785 :
3786 60 : static void AutoInitVariable (location_t location, unsigned int sym)
3787 : {
3788 60 : unsigned int type;
3789 :
3790 60 : if (((! (SymbolTable_IsParameter (sym))) && (SymbolTable_IsVar (sym))) && (! (SymbolTable_IsTemporary (sym))))
3791 : {
3792 : /* PrintSym (sym) ; */
3793 6 : type = SymbolTable_SkipType (SymbolTable_GetType (sym));
3794 : /* The type SYSTEM.ADDRESS is a pointer type. */
3795 6 : if (SymbolTable_IsPointer (type))
3796 : {
3797 6 : m2statement_BuildAssignmentStatement (location, SymbolConversion_Mod2Gcc (sym), m2convert_BuildConvert (location, SymbolConversion_Mod2Gcc (SymbolTable_GetType (sym)), m2expr_GetPointerZero (location), true));
3798 : }
3799 : }
3800 60 : }
3801 :
3802 :
3803 : /*
3804 : AutoInitialize - scope will be a procedure, module or defimp. All pointer
3805 : variables are assigned to NIL.
3806 : */
3807 :
3808 79597 : static void AutoInitialize (location_t location, unsigned int scope)
3809 : {
3810 79597 : unsigned int i;
3811 79597 : unsigned int n;
3812 :
3813 79597 : if (M2Options_AutoInit)
3814 : {
3815 30 : n = SymbolTable_NoOfVariables (scope);
3816 30 : i = 1;
3817 30 : if (SymbolTable_IsProcedure (scope))
3818 : {
3819 : /* The parameters are stored as local variables. */
3820 30 : i += SymbolTable_NoOfParamAny (scope);
3821 : }
3822 90 : while (i <= n)
3823 : {
3824 60 : AutoInitVariable (location, SymbolTable_GetNth (scope, i));
3825 60 : i += 1;
3826 : }
3827 : }
3828 79597 : }
3829 :
3830 :
3831 : /*
3832 : CodeNewLocalVar - Builds a new frame on the stack to contain the procedure
3833 : local variables.
3834 : */
3835 :
3836 79597 : static void CodeNewLocalVar (unsigned int tokenno, unsigned int CurrentProcedure)
3837 : {
3838 79597 : unsigned int begin;
3839 79597 : unsigned int end;
3840 :
3841 : /* Callee saves non var unbounded parameter contents. */
3842 79597 : SaveNonVarUnboundedParameters (tokenno, CurrentProcedure);
3843 79597 : m2statement_BuildPushFunctionContext ();
3844 79597 : SymbolTable_GetProcedureBeginEnd (CurrentProcedure, &begin, &end);
3845 79597 : CurrentQuadToken = begin;
3846 79597 : m2statement_SetBeginLocation (M2LexBuf_TokenToLocation (begin));
3847 79597 : AutoInitialize (M2LexBuf_TokenToLocation (begin), CurrentProcedure);
3848 79597 : SymbolTable_ForeachProcedureDo (CurrentProcedure, (SymbolKey_PerformOperation) {(SymbolKey_PerformOperation_t) M2Code_CodeBlock});
3849 79597 : SymbolTable_ForeachInnerModuleDo (CurrentProcedure, (SymbolKey_PerformOperation) {(SymbolKey_PerformOperation_t) M2Code_CodeBlock});
3850 79597 : m2statement_BuildPopFunctionContext ();
3851 79597 : SymbolTable_ForeachInnerModuleDo (CurrentProcedure, (SymbolKey_PerformOperation) {(SymbolKey_PerformOperation_t) CallInnerInit});
3852 79597 : }
3853 :
3854 :
3855 : /*
3856 : CodeKillLocalVar - removes local variables and returns to previous scope.
3857 : */
3858 :
3859 79591 : static void CodeKillLocalVar (unsigned int CurrentProcedure)
3860 : {
3861 79591 : unsigned int begin;
3862 79591 : unsigned int end;
3863 79591 : tree proc;
3864 :
3865 79591 : SymbolTable_GetProcedureBeginEnd (CurrentProcedure, &begin, &end);
3866 79591 : CurrentQuadToken = end;
3867 79591 : proc = NULL;
3868 79591 : if (SymbolTable_IsCtor (CurrentProcedure))
3869 : {
3870 14858 : proc = m2decl_DeclareModuleCtor (SymbolConversion_Mod2Gcc (CurrentProcedure));
3871 : }
3872 79591 : m2statement_BuildEndFunctionCode (M2LexBuf_TokenToLocation (end), SymbolConversion_Mod2Gcc (CurrentProcedure), M2GCCDeclare_IsProcedureGccNested (CurrentProcedure));
3873 79591 : if ((SymbolTable_IsCtor (CurrentProcedure)) && (proc != NULL))
3874 : {
3875 14858 : m2decl_BuildModuleCtor (proc);
3876 : }
3877 79591 : M2GCCDeclare_PoisonSymbols (CurrentProcedure);
3878 79591 : m2block_removeStmtNote ();
3879 79591 : PopScope ();
3880 79591 : }
3881 :
3882 :
3883 : /*
3884 : CodeProcedureScope - start a procedure scope for CurrentProcedure.
3885 : */
3886 :
3887 79603 : static void CodeProcedureScope (unsigned int CurrentProcedure)
3888 : {
3889 79603 : unsigned int begin;
3890 79603 : unsigned int end;
3891 :
3892 79603 : m2block_removeStmtNote ();
3893 79603 : SymbolTable_GetProcedureBeginEnd (CurrentProcedure, &begin, &end);
3894 79603 : m2statement_BuildStartFunctionCode (M2LexBuf_TokenToLocation (begin), SymbolConversion_Mod2Gcc (CurrentProcedure), IsExportedGcc (CurrentProcedure), SymbolTable_IsProcedureInline (CurrentProcedure));
3895 79603 : M2GCCDeclare_StartDeclareScope (CurrentProcedure);
3896 79597 : PushScope (CurrentProcedure);
3897 79597 : }
3898 :
3899 :
3900 : /*
3901 : CodeReturnValue - places the operand into the return value space
3902 : allocated by the function call.
3903 : */
3904 :
3905 27853 : static void CodeReturnValue (unsigned int quad)
3906 : {
3907 27853 : M2Quads_QuadOperator op;
3908 27853 : bool constExpr;
3909 27853 : bool overflowChecking;
3910 27853 : unsigned int expr;
3911 27853 : unsigned int none;
3912 27853 : unsigned int procedure;
3913 27853 : unsigned int combinedpos;
3914 27853 : unsigned int returnpos;
3915 27853 : unsigned int exprpos;
3916 27853 : unsigned int nonepos;
3917 27853 : unsigned int procpos;
3918 27853 : tree value;
3919 27853 : tree length;
3920 27853 : location_t location;
3921 :
3922 27853 : M2Quads_GetQuadOtok (quad, &returnpos, &op, &expr, &none, &procedure, &overflowChecking, &constExpr, &exprpos, &nonepos, &procpos);
3923 27853 : combinedpos = M2LexBuf_MakeVirtualTok (returnpos, returnpos, exprpos);
3924 27853 : location = M2LexBuf_TokenToLocation (combinedpos);
3925 27853 : M2GCCDeclare_TryDeclareConstant (exprpos, expr); /* Checks to see whether it is a constant and declares it. */
3926 27853 : M2GCCDeclare_TryDeclareConstructor (exprpos, expr); /* Checks to see whether it is a constant and declares it. */
3927 27853 : if ((SymbolTable_IsConstString (expr)) && ((SymbolTable_SkipTypeAndSubrange (SymbolTable_GetType (procedure))) != M2Base_Char))
3928 : {
3929 24 : if (! (M2GenGCC_PrepareCopyString (returnpos, &length, &value, expr, SymbolTable_GetType (procedure))))
3930 : {
3931 0 : M2MetaError_MetaErrorT3 (M2LexBuf_MakeVirtualTok (returnpos, returnpos, exprpos), (const char *) "string constant {%1Ea} is too large to be returned from procedure {%2a} via the {%3d} {%3a}", 91, expr, procedure, SymbolTable_GetType (procedure));
3932 : }
3933 24 : value = m2type_BuildArrayStringConstructor (location, SymbolConversion_Mod2Gcc (SymbolTable_GetType (procedure)), value, length);
3934 : }
3935 : else
3936 : {
3937 27829 : value = SymbolConversion_Mod2Gcc (expr);
3938 : }
3939 27853 : m2statement_BuildReturnValueCode (location, SymbolConversion_Mod2Gcc (procedure), value);
3940 27853 : }
3941 :
3942 :
3943 : /*
3944 : CodeCall - determines whether the procedure call is a direct call
3945 : or an indirect procedure call.
3946 : */
3947 :
3948 213259 : static void CodeCall (unsigned int tokenno, unsigned int procedure)
3949 : {
3950 213259 : tree callTree;
3951 213259 : location_t location;
3952 :
3953 213259 : if (SymbolTable_IsProcedure (procedure))
3954 : {
3955 212535 : M2GCCDeclare_DeclareParameters (procedure);
3956 212535 : callTree = CodeDirectCall (tokenno, procedure);
3957 : }
3958 724 : else if (SymbolTable_IsProcType (SymbolTable_SkipType (SymbolTable_GetType (procedure))))
3959 : {
3960 : /* avoid dangling else. */
3961 724 : M2GCCDeclare_DeclareParameters (SymbolTable_SkipType (SymbolTable_GetType (procedure)));
3962 724 : callTree = CodeIndirectCall (tokenno, procedure);
3963 724 : procedure = SymbolTable_SkipType (SymbolTable_GetType (procedure));
3964 : }
3965 : else
3966 : {
3967 : /* avoid dangling else. */
3968 0 : M2Error_InternalError ((const char *) "expecting Procedure or ProcType", 31);
3969 : }
3970 213259 : if ((SymbolTable_GetType (procedure)) == SymbolTable_NulSym)
3971 : {
3972 145314 : location = M2LexBuf_TokenToLocation (tokenno);
3973 145314 : m2type_AddStatement (location, callTree);
3974 : }
3975 : /* Leave tree alone - as it will be picked up when processing FunctValue. */
3976 213259 : }
3977 :
3978 :
3979 : /*
3980 : UseBuiltin - returns a Tree containing the builtin function
3981 : and parameters. It should only be called if
3982 : CanUseBuiltin or IsProcedureBuiltinAvailable returns TRUE.
3983 : */
3984 :
3985 1152 : static tree UseBuiltin (unsigned int tokenno, unsigned int Sym)
3986 : {
3987 1152 : if (m2builtins_BuiltinExists (reinterpret_cast <char * > (NameKey_KeyToCharStar (SymbolTable_GetProcedureBuiltin (Sym)))))
3988 : {
3989 1152 : return m2builtins_BuildBuiltinTree (M2LexBuf_TokenToLocation (tokenno), reinterpret_cast <char * > (NameKey_KeyToCharStar (SymbolTable_GetProcedureBuiltin (Sym))));
3990 : }
3991 : else
3992 : {
3993 0 : return m2builtins_BuildBuiltinTree (M2LexBuf_TokenToLocation (tokenno), reinterpret_cast <char * > (NameKey_KeyToCharStar (SymbolTable_GetSymName (Sym))));
3994 : }
3995 : /* static analysis guarentees a RETURN statement will be used before here. */
3996 : __builtin_unreachable ();
3997 : }
3998 :
3999 :
4000 : /*
4001 : CodeDirectCall - calls a function/procedure.
4002 : */
4003 :
4004 212535 : static tree CodeDirectCall (unsigned int tokenno, unsigned int procedure)
4005 : {
4006 212535 : location_t location;
4007 212535 : tree call;
4008 :
4009 212535 : location = M2LexBuf_TokenToLocation (tokenno);
4010 212535 : if (SymbolTable_IsProcedureBuiltinAvailable (procedure))
4011 : {
4012 : /* avoid dangling else. */
4013 1146 : call = UseBuiltin (tokenno, procedure);
4014 1146 : if (call != NULL)
4015 : {
4016 1146 : call = m2statement_BuildBuiltinCallTree (call);
4017 : }
4018 : }
4019 : else
4020 : {
4021 : call = NULL;
4022 : }
4023 1146 : if (call == NULL)
4024 : {
4025 : /* avoid gcc warning by using compound statement even if not strictly necessary. */
4026 211389 : if ((SymbolTable_GetType (procedure)) == SymbolTable_NulSym)
4027 : {
4028 144654 : call = m2statement_BuildProcedureCallTree (location, SymbolConversion_Mod2Gcc (procedure), NULL);
4029 : }
4030 : else
4031 : {
4032 66735 : call = m2statement_BuildProcedureCallTree (location, SymbolConversion_Mod2Gcc (procedure), SymbolConversion_Mod2Gcc (SymbolTable_GetType (procedure)));
4033 : }
4034 : }
4035 212535 : if ((SymbolTable_GetType (procedure)) == SymbolTable_NulSym)
4036 : {
4037 144678 : m2statement_SetLastFunction (NULL);
4038 : }
4039 : else
4040 : {
4041 67857 : m2statement_SetLastFunction (call);
4042 : }
4043 212535 : return call;
4044 : /* static analysis guarentees a RETURN statement will be used before here. */
4045 : __builtin_unreachable ();
4046 : }
4047 :
4048 :
4049 : /*
4050 : CodeIndirectCall - calls a function/procedure indirectly.
4051 : */
4052 :
4053 724 : static tree CodeIndirectCall (unsigned int tokenno, unsigned int ProcVar)
4054 : {
4055 724 : tree ReturnType;
4056 724 : unsigned int proc;
4057 724 : location_t location;
4058 :
4059 724 : location = M2LexBuf_TokenToLocation (tokenno);
4060 724 : proc = SymbolTable_SkipType (SymbolTable_GetType (ProcVar));
4061 724 : if ((SymbolTable_GetType (proc)) == SymbolTable_NulSym)
4062 : {
4063 : ReturnType = (tree) (NULL);
4064 : }
4065 : else
4066 : {
4067 88 : ReturnType = (tree) (SymbolConversion_Mod2Gcc (SymbolTable_GetType (proc)));
4068 : }
4069 : /* Now we dereference the lvalue if necessary. */
4070 724 : if ((SymbolTable_GetMode (ProcVar)) == SymbolTable_LeftValue)
4071 : {
4072 68 : return m2statement_BuildIndirectProcedureCallTree (location, m2expr_BuildIndirect (location, SymbolConversion_Mod2Gcc (ProcVar), SymbolConversion_Mod2Gcc (proc)), ReturnType);
4073 : }
4074 : else
4075 : {
4076 656 : return m2statement_BuildIndirectProcedureCallTree (location, SymbolConversion_Mod2Gcc (ProcVar), ReturnType);
4077 : }
4078 : /* static analysis guarentees a RETURN statement will be used before here. */
4079 : __builtin_unreachable ();
4080 : }
4081 :
4082 :
4083 : /*
4084 : ConvertTo - convert gcc tree, t, (which currently represents Modula-2 op3) into
4085 : a symbol of, type.
4086 : */
4087 :
4088 31678 : static tree ConvertTo (tree t, unsigned int type, unsigned int op3)
4089 : {
4090 31678 : if ((SymbolTable_SkipType (type)) != (SymbolTable_SkipType (SymbolTable_GetType (op3))))
4091 : {
4092 21616 : if ((SymbolTable_IsConst (op3)) && (! (SymbolTable_IsConstString (op3))))
4093 : {
4094 1648 : SymbolTable_PushValue (op3);
4095 1648 : return m2convert_BuildConvert (M2LexBuf_TokenToLocation (SymbolTable_GetDeclaredMod (op3)), SymbolConversion_Mod2Gcc (type), t, false);
4096 : }
4097 : }
4098 : return t;
4099 : /* static analysis guarentees a RETURN statement will be used before here. */
4100 : __builtin_unreachable ();
4101 : }
4102 :
4103 :
4104 : /*
4105 : ConvertRHS - convert (t, rhs) into, type. (t, rhs) refer to the
4106 : same entity t is a GCC Tree and, rhs, is a Modula-2
4107 : symbol. It checks for char and strings
4108 : first and then the remaining types.
4109 : */
4110 :
4111 31678 : static tree ConvertRHS (tree t, unsigned int type, unsigned int rhs)
4112 : {
4113 31678 : t = M2GenGCC_StringToChar (SymbolConversion_Mod2Gcc (rhs), type, rhs);
4114 31678 : return ConvertTo (t, type, rhs);
4115 : /* static analysis guarentees a RETURN statement will be used before here. */
4116 : __builtin_unreachable ();
4117 : }
4118 :
4119 :
4120 : /*
4121 : IsCoerceableParameter - returns TRUE if symbol, sym, is a
4122 : coerceable parameter.
4123 : */
4124 :
4125 394148 : static bool IsCoerceableParameter (unsigned int sym)
4126 : {
4127 394148 : return ((((((SymbolTable_IsSet (sym)) || (((M2Base_IsOrdinalType (sym)) && (sym != M2Base_Boolean)) && (! (SymbolTable_IsEnumeration (sym))))) || (M2Base_IsComplexType (sym))) || (M2Base_IsRealType (sym))) || (M2System_IsComplexN (sym))) || (M2System_IsRealN (sym))) || (M2System_IsSetN (sym));
4128 : /* static analysis guarentees a RETURN statement will be used before here. */
4129 : __builtin_unreachable ();
4130 : }
4131 :
4132 :
4133 : /*
4134 : IsConstProcedure - returns TRUE if, p, is a const procedure.
4135 : */
4136 :
4137 592 : static bool IsConstProcedure (unsigned int p)
4138 : {
4139 592 : return ((SymbolTable_IsConst (p)) && ((SymbolTable_GetType (p)) != SymbolTable_NulSym)) && (SymbolTable_IsProcType (SymbolTable_GetType (p)));
4140 : /* static analysis guarentees a RETURN statement will be used before here. */
4141 : __builtin_unreachable ();
4142 : }
4143 :
4144 :
4145 : /*
4146 : IsConstant - returns TRUE if symbol, p, is either a const or procedure.
4147 : */
4148 :
4149 870198 : static bool IsConstant (unsigned int p)
4150 : {
4151 870198 : return (SymbolTable_IsConst (p)) || (SymbolTable_IsProcedure (p));
4152 : /* static analysis guarentees a RETURN statement will be used before here. */
4153 : __builtin_unreachable ();
4154 : }
4155 :
4156 :
4157 : /*
4158 : CheckConvertCoerceParameter - ensure that actual parameter is the same as the nth of callee.
4159 : */
4160 :
4161 532357 : static tree CheckConvertCoerceParameter (unsigned int tokenno, unsigned int nth, unsigned int callee, unsigned int actual)
4162 : {
4163 532357 : unsigned int OperandType;
4164 532357 : unsigned int ParamType;
4165 532357 : location_t location;
4166 :
4167 532357 : location = M2LexBuf_TokenToLocation (tokenno);
4168 532357 : if ((SymbolTable_GetNthParamAny (callee, nth)) == SymbolTable_NulSym)
4169 : {
4170 : /* We reach here if the argument is being passed to a C vararg function. */
4171 6640 : return SymbolConversion_Mod2Gcc (actual);
4172 : }
4173 : else
4174 : {
4175 525717 : OperandType = SymbolTable_SkipType (SymbolTable_GetType (actual));
4176 525717 : ParamType = SymbolTable_SkipType (SymbolTable_GetType (SymbolTable_GetNthParamAny (callee, nth)));
4177 : }
4178 525717 : if (SymbolTable_IsProcType (ParamType))
4179 : {
4180 46474 : if (((SymbolTable_IsProcedure (actual)) || (IsConstProcedure (actual))) || (OperandType == ParamType))
4181 : {
4182 46410 : return SymbolConversion_Mod2Gcc (actual);
4183 : }
4184 : else
4185 : {
4186 64 : return m2convert_BuildConvert (location, SymbolConversion_Mod2Gcc (ParamType), SymbolConversion_Mod2Gcc (actual), false);
4187 : }
4188 : }
4189 479243 : else if (((M2Base_IsRealType (OperandType)) && (M2Base_IsRealType (ParamType))) && (ParamType != OperandType))
4190 : {
4191 : /* avoid dangling else. */
4192 : /* SHORTREAL, LONGREAL and REAL conversion during parameter passing. */
4193 1962 : return m2convert_BuildConvert (location, SymbolConversion_Mod2Gcc (ParamType), SymbolConversion_Mod2Gcc (actual), false);
4194 : }
4195 477281 : else if (((OperandType != SymbolTable_NulSym) && (SymbolTable_IsSet (OperandType))) && (SymbolTable_IsConst (actual)))
4196 : {
4197 : /* avoid dangling else. */
4198 550 : return m2decl_DeclareKnownConstant (location, SymbolConversion_Mod2Gcc (ParamType), SymbolConversion_Mod2Gcc (actual));
4199 : }
4200 476731 : else if ((SymbolTable_IsConst (actual)) && ((M2Base_IsOrdinalType (ParamType)) || (M2System_IsSystemType (ParamType))))
4201 : {
4202 : /* avoid dangling else. */
4203 82559 : return m2convert_BuildConvert (location, SymbolConversion_Mod2Gcc (ParamType), M2GenGCC_StringToChar (SymbolConversion_Mod2Gcc (actual), ParamType, actual), false);
4204 : }
4205 394172 : else if ((SymbolTable_IsConstString (actual)) || (((OperandType != SymbolTable_NulSym) && (IsCoerceableParameter (OperandType))) && (OperandType != ParamType)))
4206 : {
4207 : /* avoid dangling else. */
4208 5300 : return m2convert_BuildConvert (location, SymbolConversion_Mod2Gcc (ParamType), SymbolConversion_Mod2Gcc (actual), false);
4209 : }
4210 : else
4211 : {
4212 : /* avoid dangling else. */
4213 388872 : return SymbolConversion_Mod2Gcc (actual);
4214 : }
4215 : /* static analysis guarentees a RETURN statement will be used before here. */
4216 : __builtin_unreachable ();
4217 : }
4218 :
4219 :
4220 : /*
4221 : CheckConstant - checks to see whether we should declare the constant.
4222 : */
4223 :
4224 6 : static tree CheckConstant (unsigned int tokenno, unsigned int des, unsigned int expr)
4225 : {
4226 6 : location_t location;
4227 :
4228 6 : location = M2LexBuf_TokenToLocation (tokenno);
4229 6 : if (SymbolTable_IsProcedure (expr))
4230 : {
4231 0 : return SymbolConversion_Mod2Gcc (expr);
4232 : }
4233 : else
4234 : {
4235 6 : return m2decl_DeclareKnownConstant (location, SymbolConversion_Mod2Gcc (SymbolTable_GetType (des)), SymbolConversion_Mod2Gcc (expr));
4236 : }
4237 : /* static analysis guarentees a RETURN statement will be used before here. */
4238 : __builtin_unreachable ();
4239 : }
4240 :
4241 :
4242 : /*
4243 : CodeMakeAdr - code the function MAKEADR.
4244 : */
4245 :
4246 0 : static void CodeMakeAdr (unsigned int q, unsigned int op1, unsigned int op2, unsigned int op3)
4247 : {
4248 0 : unsigned int r;
4249 0 : unsigned int n;
4250 0 : unsigned int type;
4251 0 : M2Quads_QuadOperator op;
4252 0 : tree bits;
4253 0 : tree max;
4254 0 : tree tmp;
4255 0 : tree res;
4256 0 : tree val;
4257 0 : location_t location;
4258 :
4259 0 : location = M2LexBuf_TokenToLocation (CurrentQuadToken);
4260 0 : n = q;
4261 0 : do {
4262 0 : if (op1 > 0)
4263 : {
4264 0 : M2GCCDeclare_DeclareConstant (CurrentQuadToken, op3);
4265 : }
4266 0 : n = M2Quads_GetNextQuad (n);
4267 0 : M2Quads_GetQuad (n, &op, &r, &op2, &op3);
4268 0 : } while (! (op == M2Quads_FunctValueOp));
4269 0 : n = q;
4270 0 : M2Quads_GetQuad (n, &op, &op1, &op2, &op3);
4271 0 : res = SymbolConversion_Mod2Gcc (r);
4272 0 : max = m2expr_GetSizeOfInBits (SymbolConversion_Mod2Gcc (M2System_Address));
4273 0 : bits = m2expr_GetIntegerZero (location);
4274 0 : val = m2expr_GetPointerZero (location);
4275 0 : do {
4276 0 : location = M2LexBuf_TokenToLocation (CurrentQuadToken);
4277 0 : if ((op == M2Quads_ParamOp) && (op1 > 0))
4278 : {
4279 : /* avoid gcc warning by using compound statement even if not strictly necessary. */
4280 0 : if ((SymbolTable_GetType (op3)) == SymbolTable_NulSym)
4281 : {
4282 0 : M2Error_WriteFormat0 ((const char *) "must supply typed constants to MAKEADR", 38);
4283 : }
4284 : else
4285 : {
4286 0 : type = SymbolTable_GetType (op3);
4287 0 : tmp = m2convert_BuildConvert (location, m2type_GetPointerType (), SymbolConversion_Mod2Gcc (op3), false);
4288 0 : if ((m2expr_CompareTrees (bits, m2expr_GetIntegerZero (location))) > 0)
4289 : {
4290 0 : tmp = m2expr_BuildLSL (location, tmp, bits, false);
4291 : }
4292 0 : bits = m2expr_BuildAdd (location, bits, m2expr_GetSizeOfInBits (SymbolConversion_Mod2Gcc (type)), false);
4293 0 : val = m2expr_BuildLogicalOrAddress (location, val, tmp);
4294 : }
4295 : }
4296 0 : M2Quads_SubQuad (n);
4297 0 : n = M2Quads_GetNextQuad (n);
4298 0 : M2Quads_GetQuad (n, &op, &op1, &op2, &op3);
4299 0 : } while (! (op == M2Quads_FunctValueOp));
4300 0 : if ((m2expr_CompareTrees (bits, max)) > 0)
4301 : {
4302 0 : M2MetaError_MetaErrorT0 (CurrentQuadToken, (const char *) "total number of bits specified as parameters to {%kMAKEADR} exceeds address width", 81);
4303 : }
4304 0 : M2Quads_SubQuad (n);
4305 0 : m2statement_BuildAssignmentStatement (location, res, val);
4306 0 : }
4307 :
4308 :
4309 : /*
4310 : CodeBuiltinFunction - attempts to inline a function. Currently it only
4311 : inlines the SYSTEM function MAKEADR.
4312 : */
4313 :
4314 67945 : static void CodeBuiltinFunction (unsigned int q, unsigned int nth, unsigned int func, unsigned int parameter)
4315 : {
4316 67945 : if (nth == 0)
4317 : {
4318 67945 : InitBuiltinSyms (M2LexBuf_BuiltinTokenNo);
4319 67945 : if (func == M2System_MakeAdr)
4320 : {
4321 0 : CodeMakeAdr (q, nth, func, parameter);
4322 : }
4323 : }
4324 67945 : }
4325 :
4326 :
4327 : /*
4328 : FoldMakeAdr - attempts to fold the function MAKEADR.
4329 : */
4330 :
4331 12 : static void FoldMakeAdr (unsigned int tokenno, M2GCCDeclare_WalkAction p, unsigned int q, unsigned int op1, unsigned int op2, unsigned int op3)
4332 : {
4333 12 : bool resolved;
4334 12 : unsigned int r;
4335 12 : unsigned int n;
4336 12 : M2Quads_QuadOperator op;
4337 12 : unsigned int type;
4338 12 : tree bits;
4339 12 : tree max;
4340 12 : tree tmp;
4341 12 : tree val;
4342 12 : location_t location;
4343 :
4344 12 : location = M2LexBuf_TokenToLocation (tokenno);
4345 12 : resolved = true;
4346 12 : n = q;
4347 12 : r = op1;
4348 24 : do {
4349 24 : if (r > 0)
4350 : {
4351 12 : M2GCCDeclare_TryDeclareConstant (tokenno, op3);
4352 12 : if (! (SymbolConversion_GccKnowsAbout (op3)))
4353 : {
4354 24 : resolved = false;
4355 : }
4356 : }
4357 24 : n = M2Quads_GetNextQuad (n);
4358 24 : M2Quads_GetQuad (n, &op, &r, &op2, &op3);
4359 24 : } while (! (op == M2Quads_FunctValueOp));
4360 12 : if (resolved && (SymbolTable_IsConst (r)))
4361 : {
4362 12 : n = q;
4363 12 : M2Quads_GetQuad (n, &op, &op1, &op2, &op3);
4364 12 : max = m2expr_GetSizeOfInBits (SymbolConversion_Mod2Gcc (M2System_Address));
4365 12 : bits = m2expr_GetIntegerZero (location);
4366 12 : val = m2expr_GetPointerZero (location);
4367 24 : do {
4368 24 : location = M2LexBuf_TokenToLocation (tokenno);
4369 24 : if ((op == M2Quads_ParamOp) && (op1 > 0))
4370 : {
4371 : /* avoid gcc warning by using compound statement even if not strictly necessary. */
4372 12 : if ((SymbolTable_GetType (op3)) == SymbolTable_NulSym)
4373 : {
4374 0 : M2MetaError_MetaErrorT0 (tokenno, (const char *) "constants passed to {%kMAKEADR} must be typed", 45);
4375 : }
4376 : else
4377 : {
4378 12 : type = SymbolTable_GetType (op3);
4379 12 : tmp = m2convert_BuildConvert (location, m2type_GetPointerType (), SymbolConversion_Mod2Gcc (op3), false);
4380 12 : if ((m2expr_CompareTrees (bits, m2expr_GetIntegerZero (location))) > 0)
4381 : {
4382 0 : tmp = m2expr_BuildLSL (location, tmp, bits, false);
4383 : }
4384 12 : bits = m2expr_BuildAdd (location, bits, m2expr_GetSizeOfInBits (SymbolConversion_Mod2Gcc (type)), false);
4385 12 : val = m2expr_BuildLogicalOrAddress (location, val, tmp);
4386 : }
4387 : }
4388 24 : M2Quads_SubQuad (n);
4389 24 : n = M2Quads_GetNextQuad (n);
4390 24 : M2Quads_GetQuad (n, &op, &op1, &op2, &op3);
4391 24 : } while (! (op == M2Quads_FunctValueOp));
4392 12 : if ((m2expr_CompareTrees (bits, max)) > 0)
4393 : {
4394 0 : M2MetaError_MetaErrorT0 (tokenno, (const char *) "total number of bits specified as parameters to {%kMAKEADR} exceeds address width", 81);
4395 : }
4396 12 : SymbolTable_PutConst (r, M2System_Address);
4397 12 : SymbolConversion_AddModGcc (r, m2decl_DeclareKnownConstant (location, SymbolConversion_Mod2Gcc (M2System_Address), val));
4398 12 : (*p.proc) (r);
4399 12 : NoChange = false;
4400 12 : M2Quads_SubQuad (n);
4401 : }
4402 12 : }
4403 :
4404 :
4405 : /*
4406 : doParam - builds the parameter, op3, which is to be passed to
4407 : procedure, op2. The number of the parameter is op1.
4408 : */
4409 :
4410 532357 : static void doParam (unsigned int paramtok, unsigned int quad, unsigned int op1, unsigned int op2, unsigned int op3)
4411 : {
4412 532357 : location_t location;
4413 :
4414 532357 : location = M2LexBuf_TokenToLocation (paramtok);
4415 532357 : M2GCCDeclare_DeclareConstant (paramtok, op3);
4416 532357 : M2GCCDeclare_DeclareConstructor (paramtok, quad, op3);
4417 532357 : m2statement_BuildParam (location, CheckConvertCoerceParameter (paramtok, op1, op2, op3));
4418 532357 : }
4419 :
4420 :
4421 : /*
4422 : FoldBuiltin - attempts to fold the gcc builtin function.
4423 : */
4424 :
4425 18004 : static void FoldBuiltin (unsigned int tokenno, M2GCCDeclare_WalkAction p, unsigned int q)
4426 : {
4427 18004 : bool resolved;
4428 18004 : unsigned int procedure;
4429 18004 : unsigned int r;
4430 18004 : unsigned int n;
4431 18004 : unsigned int op1;
4432 18004 : unsigned int op2;
4433 18004 : unsigned int op3;
4434 18004 : M2Quads_QuadOperator op;
4435 18004 : tree val;
4436 18004 : tree call;
4437 18004 : location_t location;
4438 :
4439 18004 : M2Quads_GetQuad (q, &op, &op1, &op2, &op3);
4440 18004 : resolved = true;
4441 18004 : procedure = SymbolTable_NulSym;
4442 18004 : n = q;
4443 18004 : r = op1;
4444 57036 : do {
4445 57036 : if (r > 0)
4446 : {
4447 21028 : M2GCCDeclare_TryDeclareConstant (tokenno, op3);
4448 21028 : if (! (SymbolConversion_GccKnowsAbout (op3)))
4449 : {
4450 57036 : resolved = false;
4451 : }
4452 : }
4453 57036 : if ((op == M2Quads_CallOp) && (! (SymbolTable_IsProcedure (op3))))
4454 : {
4455 : /* Cannot fold an indirect procedure function call. */
4456 : resolved = false;
4457 : }
4458 57036 : n = M2Quads_GetNextQuad (n);
4459 57036 : M2Quads_GetQuad (n, &op, &r, &op2, &op3);
4460 57036 : } while (! (op == M2Quads_FunctValueOp));
4461 18004 : if (resolved && (SymbolTable_IsConst (r)))
4462 : {
4463 6 : n = q;
4464 6 : M2Quads_GetQuad (n, &op, &op1, &op2, &op3);
4465 18 : do {
4466 18 : if ((op == M2Quads_ParamOp) && (op1 > 0))
4467 : {
4468 6 : doParam (tokenno, n, op1, op2, op3);
4469 : }
4470 12 : else if (op == M2Quads_CallOp)
4471 : {
4472 : /* avoid dangling else. */
4473 6 : procedure = op3;
4474 : }
4475 18 : M2Quads_SubQuad (n);
4476 18 : n = M2Quads_GetNextQuad (n);
4477 18 : M2Quads_GetQuad (n, &op, &op1, &op2, &op3);
4478 18 : } while (! (op == M2Quads_FunctValueOp));
4479 6 : if (SymbolTable_IsProcedureBuiltinAvailable (procedure))
4480 : {
4481 6 : location = M2LexBuf_TokenToLocation (tokenno);
4482 6 : call = UseBuiltin (tokenno, procedure);
4483 6 : val = m2statement_BuildFunctValue (location, call);
4484 6 : val = m2expr_FoldAndStrip (val);
4485 6 : SymbolTable_PutConst (r, SymbolTable_GetType (procedure));
4486 6 : SymbolConversion_AddModGcc (r, m2decl_DeclareKnownConstant (location, SymbolConversion_Mod2Gcc (SymbolTable_GetType (procedure)), val));
4487 6 : (*p.proc) (r);
4488 6 : m2statement_SetLastFunction (NULL);
4489 : }
4490 : else
4491 : {
4492 0 : M2MetaError_MetaErrorT1 (tokenno, (const char *) "gcc builtin procedure {%1Ead} cannot be used in a constant expression", 69, procedure);
4493 : }
4494 6 : NoChange = false;
4495 6 : M2Quads_SubQuad (n);
4496 : }
4497 18004 : }
4498 :
4499 :
4500 : /*
4501 : FoldBuiltinFunction - attempts to inline a function. Currently it only
4502 : inlines the SYSTEM function MAKEADR.
4503 : */
4504 :
4505 7602937 : static void FoldBuiltinFunction (unsigned int tokenno, M2GCCDeclare_WalkAction p, unsigned int q, unsigned int op1, unsigned int op2, unsigned int op3)
4506 : {
4507 7602937 : if (op1 == 0)
4508 : {
4509 : /* avoid gcc warning by using compound statement even if not strictly necessary. */
4510 : /* Must be a function as op1 is the return parameter. */
4511 1023649 : if (op3 == M2System_MakeAdr)
4512 : {
4513 12 : FoldMakeAdr (tokenno, p, q, op1, op2, op3);
4514 : }
4515 1023637 : else if ((SymbolTable_IsProcedure (op3)) && (SymbolTable_IsProcedureBuiltinAvailable (op3)))
4516 : {
4517 : /* avoid dangling else. */
4518 18004 : FoldBuiltin (tokenno, p, q);
4519 : }
4520 : }
4521 7602937 : }
4522 :
4523 :
4524 : /*
4525 : CodeParam - builds a parameter list.
4526 : Note that we can ignore ModeOfAddr as any lvalue will
4527 : have been created in a preceeding quadruple.
4528 : */
4529 :
4530 600344 : static void CodeParam (unsigned int quad)
4531 : {
4532 600344 : unsigned int nopos;
4533 600344 : unsigned int procedure;
4534 600344 : unsigned int parameter;
4535 600344 : unsigned int parampos;
4536 600344 : unsigned int nth;
4537 600344 : bool compatible;
4538 600344 : bool constExpr;
4539 600344 : bool overflow;
4540 600344 : M2Quads_QuadOperator op;
4541 :
4542 600344 : M2Quads_GetQuadOtok (quad, ¶mpos, &op, &nth, &procedure, ¶meter, &overflow, &constExpr, &nopos, &nopos, &nopos);
4543 600344 : compatible = true;
4544 600344 : if (nth == 0)
4545 : {
4546 67945 : CodeBuiltinFunction (quad, nth, procedure, parameter);
4547 : }
4548 : else
4549 : {
4550 532399 : if (M2Options_StrictTypeChecking)
4551 : {
4552 532399 : if (nth <= (SymbolTable_NoOfParamAny (procedure)))
4553 : {
4554 525759 : compatible = M2Check_ParameterTypeCompatible (parampos, (const char *) "parameter incompatibility when attempting to pass actual parameter {%2ad} to a {%kVAR} formal parameter {%3Ead} during call to procedure {%1ad}", 143, procedure, SymbolTable_GetNthParamAny (procedure, nth), parameter, nth, SymbolTable_IsVarParamAny (procedure, nth));
4555 : }
4556 : }
4557 532399 : if (((nth <= (SymbolTable_NoOfParamAny (procedure))) && (SymbolTable_IsVarParamAny (procedure, nth))) && (SymbolTable_IsConst (parameter)))
4558 : {
4559 0 : M2MetaError_MetaErrorT1 (parampos, (const char *) "cannot pass a constant {%1Ead} as a VAR parameter", 49, parameter);
4560 : }
4561 532399 : else if (SymbolTable_IsAModula2Type (parameter))
4562 : {
4563 : /* avoid dangling else. */
4564 0 : M2MetaError_MetaErrorT2 (parampos, (const char *) "cannot pass a type {%1Ead} as a parameter to procedure {%2ad}", 61, parameter, procedure);
4565 : }
4566 532399 : else if (compatible)
4567 : {
4568 : /* avoid dangling else. */
4569 532351 : doParam (parampos, quad, nth, procedure, parameter);
4570 : }
4571 : }
4572 600344 : }
4573 :
4574 :
4575 : /*
4576 : Replace - replace the entry for sym in the double entry bookkeeping with sym/tree.
4577 : */
4578 :
4579 0 : static void Replace (unsigned int sym, tree gcc)
4580 : {
4581 0 : if (SymbolConversion_GccKnowsAbout (sym))
4582 : {
4583 0 : SymbolConversion_RemoveMod2Gcc (sym);
4584 : }
4585 0 : SymbolConversion_AddModGcc (sym, gcc);
4586 0 : }
4587 :
4588 :
4589 : /*
4590 : CodeFunctValue - retrieves the function return value and assigns it
4591 : into a variable.
4592 : */
4593 :
4594 67945 : static void CodeFunctValue (location_t location, unsigned int op1)
4595 : {
4596 67945 : tree call;
4597 67945 : tree value;
4598 :
4599 : /*
4600 : operator : FunctValueOp
4601 : op1 : The Returned Variable
4602 : op3 : The Function Returning this Variable
4603 : */
4604 67945 : if (M2SSA_EnableSSA && (SymbolTable_IsVariableSSA (op1)))
4605 : {
4606 : call = m2statement_GetLastFunction ();
4607 : m2statement_SetLastFunction (NULL);
4608 : Replace (op1, call);
4609 : }
4610 : else
4611 : {
4612 67945 : value = m2statement_BuildFunctValue (location, SymbolConversion_Mod2Gcc (op1));
4613 : /* AddStatement (location, CheckCleanup (location, op3, value, call)) */
4614 67945 : m2type_AddStatement (location, value);
4615 : }
4616 67945 : }
4617 :
4618 :
4619 : /*
4620 : FoldStringLength -
4621 : */
4622 :
4623 72 : static void FoldStringLength (unsigned int quad, M2GCCDeclare_WalkAction p)
4624 : {
4625 72 : M2Quads_QuadOperator op;
4626 72 : unsigned int des;
4627 72 : unsigned int none;
4628 72 : unsigned int expr;
4629 72 : unsigned int stroppos;
4630 72 : unsigned int despos;
4631 72 : unsigned int nonepos;
4632 72 : unsigned int exprpos;
4633 72 : bool constExpr;
4634 72 : bool overflowChecking;
4635 72 : location_t location;
4636 :
4637 72 : M2Quads_GetQuadOtok (quad, &stroppos, &op, &des, &none, &expr, &overflowChecking, &constExpr, &despos, &nonepos, &exprpos);
4638 72 : if ((IsConstStr (expr)) && (IsConstStrKnown (expr)))
4639 : {
4640 66 : location = M2LexBuf_TokenToLocation (stroppos);
4641 66 : M2ALU_PushCard (SymbolTable_GetStringLength (exprpos, expr));
4642 66 : SymbolConversion_AddModGcc (des, m2convert_BuildConvert (location, SymbolConversion_Mod2Gcc (SymbolTable_GetType (des)), M2ALU_PopIntegerTree (), false));
4643 132 : RemoveQuad (p, des, quad);
4644 : }
4645 72 : }
4646 :
4647 :
4648 : /*
4649 : FoldStringConvertM2nul - attempt to assign the des with the string contents from expr.
4650 : It also marks the des as a m2 string which must be nul terminated.
4651 : The front end uses double book keeping and it is easier to have
4652 : different m2 string symbols each of which map onto a slightly different
4653 : gcc string tree.
4654 : */
4655 :
4656 34913 : static void FoldStringConvertM2nul (unsigned int quad, M2GCCDeclare_WalkAction p)
4657 : {
4658 34913 : M2Quads_QuadOperator op;
4659 34913 : unsigned int des;
4660 34913 : unsigned int none;
4661 34913 : unsigned int expr;
4662 34913 : unsigned int stroppos;
4663 34913 : unsigned int despos;
4664 34913 : unsigned int nonepos;
4665 34913 : unsigned int exprpos;
4666 34913 : DynamicStrings_String s;
4667 34913 : bool constExpr;
4668 34913 : bool overflowChecking;
4669 :
4670 34913 : M2Quads_GetQuadOtok (quad, &stroppos, &op, &des, &none, &expr, &overflowChecking, &constExpr, &despos, &nonepos, &exprpos);
4671 34913 : if ((IsConstStr (expr)) && (IsConstStrKnown (expr)))
4672 : {
4673 34913 : s = GetStr (exprpos, expr);
4674 34913 : SymbolTable_PutConstStringKnown (stroppos, des, NameKey_makekey (DynamicStrings_string (s)), false, true);
4675 34913 : M2GCCDeclare_TryDeclareConstant (despos, des);
4676 34913 : (*p.proc) (des);
4677 34913 : NoChange = false;
4678 34913 : M2Quads_SubQuad (quad);
4679 34913 : s = DynamicStrings_KillString (s);
4680 : }
4681 34913 : }
4682 :
4683 :
4684 : /*
4685 : FoldStringConvertCnul -attempt to assign the des with the string contents from expr.
4686 : It also marks the des as a C string which must be nul terminated.
4687 : */
4688 :
4689 9733 : static void FoldStringConvertCnul (unsigned int quad, M2GCCDeclare_WalkAction p)
4690 : {
4691 9733 : M2Quads_QuadOperator op;
4692 9733 : unsigned int des;
4693 9733 : unsigned int none;
4694 9733 : unsigned int expr;
4695 9733 : unsigned int stroppos;
4696 9733 : unsigned int despos;
4697 9733 : unsigned int nonepos;
4698 9733 : unsigned int exprpos;
4699 9733 : DynamicStrings_String s;
4700 9733 : bool constExpr;
4701 9733 : bool overflowChecking;
4702 :
4703 9733 : M2Quads_GetQuadOtok (quad, &stroppos, &op, &des, &none, &expr, &overflowChecking, &constExpr, &despos, &nonepos, &exprpos);
4704 9733 : if ((IsConstStr (expr)) && (IsConstStrKnown (expr)))
4705 : {
4706 9709 : s = GetStr (exprpos, expr);
4707 9709 : SymbolTable_PutConstStringKnown (stroppos, des, NameKey_makekey (DynamicStrings_string (s)), true, true);
4708 9709 : M2GCCDeclare_TryDeclareConstant (despos, des);
4709 9709 : (*p.proc) (des);
4710 9709 : NoChange = false;
4711 9709 : M2Quads_SubQuad (quad);
4712 9709 : s = DynamicStrings_KillString (s);
4713 : }
4714 9733 : }
4715 :
4716 191385 : static void CodeAddr (unsigned int tokenno, unsigned int quad, unsigned int op1, unsigned int op3)
4717 : {
4718 191385 : tree value;
4719 191385 : unsigned int type;
4720 191385 : location_t location;
4721 :
4722 : /*
4723 : Addr Operator - generates the address of a variable (op1 = &op3).
4724 : */
4725 191385 : if ((SymbolTable_IsConst (op3)) && (! (SymbolTable_IsConstString (op3))))
4726 : {
4727 6 : M2MetaError_MetaErrorT1 (tokenno, (const char *) "error in expression, trying to find the address of a constant {%1Ead}", 69, op3);
4728 : }
4729 : else
4730 : {
4731 191379 : if ((SymbolTable_IsConstString (op3)) && (! (SymbolTable_IsConstStringKnown (op3))))
4732 : {
4733 0 : M2Printf_printf1 ((const char *) "failure in quad: %d\\n", 21, (const unsigned char *) &quad, (sizeof (quad)-1));
4734 : }
4735 191379 : location = M2LexBuf_TokenToLocation (tokenno);
4736 191379 : type = SymbolTable_SkipType (SymbolTable_GetType (op3));
4737 191379 : M2GCCDeclare_DeclareConstant (tokenno, op3); /* We might be asked to find the address of a constant string. */
4738 191379 : M2GCCDeclare_DeclareConstructor (tokenno, quad, op3); /* We might be asked to find the address of a constant string. */
4739 191379 : if (((SymbolTable_IsConst (op3)) && (type == M2Base_Char)) || (SymbolTable_IsConstString (op3)))
4740 : {
4741 175117 : value = m2decl_BuildStringConstant (const_cast <const char * > (static_cast <char * > (NameKey_KeyToCharStar (SymbolTable_GetString (op3)))), static_cast<int> (SymbolTable_GetStringLength (tokenno, op3)));
4742 : }
4743 : else
4744 : {
4745 16262 : value = SymbolConversion_Mod2Gcc (op3);
4746 : }
4747 191379 : m2statement_BuildAssignmentStatement (location, SymbolConversion_Mod2Gcc (op1), m2expr_BuildAddr (location, value, false));
4748 : }
4749 191385 : }
4750 :
4751 5106768 : static void FoldBecomes (M2GCCDeclare_WalkAction p, M2BasicBlock_BasicBlock bb, unsigned int quad)
4752 : {
4753 : /*
4754 : ------------------------------------------------------------------------------
4755 : := Operator
4756 : ------------------------------------------------------------------------------
4757 : Sym1<I> := Sym3<I> := produces a constant
4758 : */
4759 5106768 : if (DeclaredOperandsBecomes (p, quad))
4760 : {
4761 305126 : CheckBreak (quad);
4762 305126 : if ((! (M2Quads_IsConditionalBooleanQuad (quad))) || (M2BasicBlock_IsBasicBlockFirst (bb)))
4763 : {
4764 300062 : if (TypeCheckBecomes (p, quad))
4765 : {
4766 300062 : PerformFoldBecomes (p, quad);
4767 : }
4768 : }
4769 : }
4770 5106768 : }
4771 :
4772 :
4773 : /*
4774 : TryDeclareConst -
4775 : */
4776 :
4777 5106768 : static void TryDeclareConst (unsigned int tokenno, unsigned int sym)
4778 : {
4779 : /* Check whether expr is a constant literal and if so declare it. */
4780 5106768 : M2GCCDeclare_TryDeclareConstant (tokenno, sym);
4781 : /* Check whether expr is a const constructor and if so declare it. */
4782 5106768 : M2GCCDeclare_TryDeclareConstructor (tokenno, sym);
4783 5106768 : }
4784 :
4785 :
4786 : /*
4787 : RemoveQuad - remove quad and ensure p (des) is called.
4788 : */
4789 :
4790 299724 : static void RemoveQuad (M2GCCDeclare_WalkAction p, unsigned int des, unsigned int quad)
4791 : {
4792 66 : (*p.proc) (des);
4793 299724 : NoChange = false;
4794 299724 : M2Quads_SubQuad (quad);
4795 0 : }
4796 :
4797 :
4798 : /*
4799 : DeclaredOperandsBecomes -
4800 : */
4801 :
4802 5106768 : static bool DeclaredOperandsBecomes (M2GCCDeclare_WalkAction p, unsigned int quad)
4803 : {
4804 5106768 : unsigned int des;
4805 5106768 : unsigned int op2;
4806 5106768 : unsigned int expr;
4807 5106768 : bool constExpr;
4808 5106768 : bool overflowChecking;
4809 5106768 : unsigned int despos;
4810 5106768 : unsigned int op2pos;
4811 5106768 : unsigned int exprpos;
4812 5106768 : unsigned int becomespos;
4813 5106768 : M2Quads_QuadOperator op;
4814 :
4815 5106768 : M2Quads_GetQuadOtok (quad, &becomespos, &op, &des, &op2, &expr, &overflowChecking, &constExpr, &despos, &op2pos, &exprpos);
4816 5106768 : M2Debug_Assert (op2pos == M2LexBuf_UnknownTokenNo);
4817 5106768 : TryDeclareConst (exprpos, expr);
4818 5106768 : if ((SymbolTable_IsConst (des)) && (IsConstant (expr)))
4819 : {
4820 : /* Constant folding taking place, but have we resolved op3 yet? */
4821 313202 : if (SymbolConversion_GccKnowsAbout (expr))
4822 : {
4823 : /* avoid gcc warning by using compound statement even if not strictly necessary. */
4824 : /* RemoveSSAPlaceholder (quad, des) ; */
4825 305126 : if (SymbolConversion_GccKnowsAbout (des))
4826 : {
4827 0 : M2MetaError_MetaErrorT1 (despos, (const char *) "constant {%1Ead} should not be reassigned", 41, des);
4828 0 : RemoveQuad (p, des, quad);
4829 0 : return false;
4830 : }
4831 : else
4832 : {
4833 : return true;
4834 : }
4835 : }
4836 : }
4837 : return false;
4838 : /* static analysis guarentees a RETURN statement will be used before here. */
4839 : __builtin_unreachable ();
4840 : }
4841 :
4842 :
4843 : /*
4844 : TypeCheckBecomes - returns TRUE if the type check succeeds.
4845 : */
4846 :
4847 300062 : static bool TypeCheckBecomes (M2GCCDeclare_WalkAction p, unsigned int quad)
4848 : {
4849 300062 : unsigned int des;
4850 300062 : unsigned int op2;
4851 300062 : unsigned int expr;
4852 300062 : bool constExpr;
4853 300062 : bool overflowChecking;
4854 300062 : unsigned int despos;
4855 300062 : unsigned int op2pos;
4856 300062 : unsigned int exprpos;
4857 300062 : unsigned int becomespos;
4858 300062 : M2Quads_QuadOperator op;
4859 :
4860 300062 : M2Quads_GetQuadOtok (quad, &becomespos, &op, &des, &op2, &expr, &overflowChecking, &constExpr, &despos, &op2pos, &exprpos);
4861 300062 : M2Debug_Assert (op2pos == M2LexBuf_UnknownTokenNo);
4862 300062 : if (M2Options_StrictTypeChecking && (! (M2Check_AssignmentTypeCompatible (despos, (const char *) "", 0, des, expr, true))))
4863 : {
4864 0 : M2MetaError_MetaErrorT2 (M2LexBuf_MakeVirtualTok (becomespos, despos, exprpos), (const char *) "assignment check caught mismatch between {%1Ead} and {%2ad}", 59, des, expr);
4865 0 : RemoveQuad (p, des, quad);
4866 0 : return false;
4867 : }
4868 : return true;
4869 : /* static analysis guarentees a RETURN statement will be used before here. */
4870 : __builtin_unreachable ();
4871 : }
4872 :
4873 :
4874 : /*
4875 : PerformFoldBecomes - attempts to fold quad. It propagates constant strings
4876 : and attempts to declare des providing it is a constant
4877 : and expr is resolved.
4878 : */
4879 :
4880 300062 : static void PerformFoldBecomes (M2GCCDeclare_WalkAction p, unsigned int quad)
4881 : {
4882 300062 : unsigned int des;
4883 300062 : unsigned int op2;
4884 300062 : unsigned int expr;
4885 300062 : bool constExpr;
4886 300062 : bool overflowChecking;
4887 300062 : unsigned int despos;
4888 300062 : unsigned int op2pos;
4889 300062 : unsigned int exprpos;
4890 300062 : unsigned int becomespos;
4891 300062 : unsigned int virtpos;
4892 300062 : M2Quads_QuadOperator op;
4893 :
4894 300062 : M2Quads_GetQuadOtok (quad, &becomespos, &op, &des, &op2, &expr, &overflowChecking, &constExpr, &despos, &op2pos, &exprpos);
4895 300062 : M2Debug_Assert (op2pos == M2LexBuf_UnknownTokenNo);
4896 300062 : if ((SymbolTable_IsConst (des)) && (SymbolTable_IsConstString (expr)))
4897 : {
4898 : /* avoid dangling else. */
4899 1408 : if ((SymbolTable_IsConstStringKnown (expr)) && (! (SymbolTable_IsConstStringKnown (des))))
4900 : {
4901 1408 : SymbolTable_CopyConstString (exprpos, des, expr);
4902 : }
4903 : }
4904 298654 : else if ((SymbolTable_GetType (des)) == SymbolTable_NulSym)
4905 : {
4906 : /* avoid dangling else. */
4907 0 : M2Debug_Assert ((SymbolTable_GetType (expr)) != SymbolTable_NulSym);
4908 0 : SymbolTable_PutConst (des, SymbolTable_GetType (expr));
4909 : }
4910 300062 : if ((SymbolTable_GetType (expr)) == SymbolTable_NulSym)
4911 : {
4912 1422 : M2ALU_CheckOrResetOverflow (exprpos, SymbolConversion_Mod2Gcc (expr), M2Quads_MustCheckOverflow (quad));
4913 1422 : SymbolConversion_AddModGcc (des, SymbolConversion_Mod2Gcc (expr));
4914 : }
4915 : else
4916 : {
4917 298640 : if (! (SymbolConversion_GccKnowsAbout (SymbolTable_GetType (des))))
4918 : {
4919 404 : return;
4920 : }
4921 298236 : if (SymbolTable_IsProcedure (expr))
4922 : {
4923 12 : SymbolConversion_AddModGcc (des, m2convert_BuildConvert (M2LexBuf_TokenToLocation (exprpos), SymbolConversion_Mod2Gcc (SymbolTable_GetType (des)), m2expr_BuildAddr (M2LexBuf_TokenToLocation (exprpos), SymbolConversion_Mod2Gcc (expr), false), true));
4924 : }
4925 298224 : else if (SymbolTable_IsValueSolved (expr))
4926 : {
4927 : /* avoid dangling else. */
4928 298224 : SymbolTable_PushValue (expr);
4929 298224 : if (M2ALU_IsValueTypeReal ())
4930 : {
4931 504 : M2ALU_CheckOrResetOverflow (exprpos, M2ALU_PopRealTree (), M2Quads_MustCheckOverflow (quad));
4932 504 : SymbolTable_PushValue (expr);
4933 504 : SymbolConversion_AddModGcc (des, M2ALU_PopRealTree ());
4934 : }
4935 297720 : else if (M2ALU_IsValueTypeSet ())
4936 : {
4937 : /* avoid dangling else. */
4938 3880 : SymbolTable_PopValue (des);
4939 3880 : SymbolTable_PutConstSet (des);
4940 : }
4941 293840 : else if (((M2ALU_IsValueTypeConstructor ()) || (M2ALU_IsValueTypeArray ())) || (M2ALU_IsValueTypeRecord ()))
4942 : {
4943 : /* avoid dangling else. */
4944 428 : SymbolTable_PopValue (des);
4945 428 : SymbolTable_PutConstructor (des);
4946 : }
4947 293412 : else if (M2ALU_IsValueTypeComplex ())
4948 : {
4949 : /* avoid dangling else. */
4950 330 : M2ALU_CheckOrResetOverflow (exprpos, M2ALU_PopComplexTree (), M2Quads_MustCheckOverflow (quad));
4951 330 : SymbolTable_PushValue (expr);
4952 330 : SymbolTable_PopValue (des);
4953 : }
4954 : else
4955 : {
4956 : /* avoid dangling else. */
4957 293082 : M2ALU_CheckOrResetOverflow (exprpos, M2ALU_PopIntegerTree (), M2Quads_MustCheckOverflow (quad));
4958 293082 : if ((SymbolTable_GetType (des)) == SymbolTable_NulSym)
4959 : {
4960 0 : SymbolTable_PushValue (expr);
4961 0 : SymbolConversion_AddModGcc (des, M2ALU_PopIntegerTree ());
4962 : }
4963 : else
4964 : {
4965 293082 : virtpos = M2LexBuf_MakeVirtualTok (becomespos, despos, exprpos);
4966 293082 : SymbolTable_PushValue (expr);
4967 293082 : SymbolConversion_AddModGcc (des, m2convert_BuildConvert (M2LexBuf_TokenToLocation (virtpos), SymbolConversion_Mod2Gcc (SymbolTable_GetType (des)), M2ALU_PopIntegerTree (), false));
4968 : }
4969 : }
4970 : }
4971 : else
4972 : {
4973 : /* avoid dangling else. */
4974 0 : virtpos = M2LexBuf_MakeVirtualTok (becomespos, despos, exprpos);
4975 0 : M2ALU_CheckOrResetOverflow (exprpos, SymbolConversion_Mod2Gcc (des), M2Quads_MustCheckOverflow (quad));
4976 0 : SymbolConversion_AddModGcc (des, m2convert_BuildConvert (M2LexBuf_TokenToLocation (virtpos), SymbolConversion_Mod2Gcc (SymbolTable_GetType (des)), m2decl_DeclareKnownConstant (M2LexBuf_TokenToLocation (virtpos), SymbolConversion_Mod2Gcc (SymbolTable_GetType (expr)), SymbolConversion_Mod2Gcc (expr)), false));
4977 : }
4978 : }
4979 299658 : RemoveQuad (p, des, quad);
4980 299658 : M2Debug_Assert ((m2block_RememberConstant (SymbolConversion_Mod2Gcc (des))) == (SymbolConversion_Mod2Gcc (des)));
4981 : }
4982 :
4983 :
4984 : /*
4985 : CodeTry - starts building a GCC 'try' node.
4986 : */
4987 :
4988 2950 : static void CodeTry (void)
4989 : {
4990 2950 : location_t location;
4991 :
4992 2950 : location = M2LexBuf_TokenToLocation (CurrentQuadToken);
4993 2950 : handlerBlock = NULL;
4994 2950 : tryBlock = m2except_BuildTryBegin (location);
4995 2950 : }
4996 :
4997 :
4998 : /*
4999 : CodeThrow - builds a GCC 'throw' node.
5000 : */
5001 :
5002 322 : static void CodeThrow (unsigned int value)
5003 : {
5004 322 : location_t location;
5005 :
5006 322 : location = M2LexBuf_TokenToLocation (CurrentQuadToken);
5007 322 : if (value == SymbolTable_NulSym)
5008 : {
5009 210 : m2type_AddStatement (location, m2except_BuildThrow (location, (tree) (NULL)));
5010 : }
5011 : else
5012 : {
5013 112 : M2GCCDeclare_DeclareConstant (CurrentQuadToken, value); /* Checks to see whether it is a constant and declares it. */
5014 112 : m2type_AddStatement (location, m2except_BuildThrow (location, m2convert_BuildConvert (location, m2type_GetIntegerType (), SymbolConversion_Mod2Gcc (value), false))); /* Checks to see whether it is a constant and declares it. */
5015 : }
5016 322 : }
5017 :
5018 156 : static void CodeRetry (unsigned int destQuad)
5019 : {
5020 156 : location_t location;
5021 :
5022 156 : location = M2LexBuf_TokenToLocation (CurrentQuadToken);
5023 156 : m2statement_BuildGoto (location, reinterpret_cast <char * > (DynamicStrings_string (CreateLabelName (destQuad))));
5024 156 : }
5025 :
5026 2950 : static void CodeCatchBegin (void)
5027 : {
5028 2950 : location_t location;
5029 :
5030 2950 : location = M2LexBuf_TokenToLocation (CurrentQuadToken);
5031 2950 : m2except_BuildTryEnd (tryBlock);
5032 2950 : handlerBlock = m2except_BuildCatchBegin (location);
5033 2950 : }
5034 :
5035 2950 : static void CodeCatchEnd (void)
5036 : {
5037 2950 : location_t location;
5038 :
5039 2950 : location = M2LexBuf_TokenToLocation (CurrentQuadToken);
5040 2950 : tryBlock = m2except_BuildCatchEnd (location, handlerBlock, tryBlock);
5041 2950 : m2type_AddStatement (location, tryBlock);
5042 2950 : }
5043 :
5044 :
5045 : /*
5046 : DescribeTypeError -
5047 : */
5048 :
5049 6 : static void DescribeTypeError (unsigned int token, unsigned int op1, unsigned int op2)
5050 : {
5051 6 : M2MetaError_MetaErrorT2 (token, (const char *) "incompatible set types in assignment, assignment between {%1ERad} and {%2ad}", 76, op1, op2);
5052 6 : M2MetaError_MetaError2 ((const char *) "set types are {%1CDtsad} and {%2Dtsad}", 38, op1, op2);
5053 6 : }
5054 :
5055 :
5056 : /*
5057 : DefaultConvertGM2 - provides a simple mapping between
5058 : front end data types and GCC equivalents.
5059 : This is only used to aid assignment of
5060 : typed constants.
5061 : */
5062 :
5063 22075 : static tree DefaultConvertGM2 (unsigned int sym)
5064 : {
5065 22075 : sym = SymbolTable_SkipType (sym);
5066 22075 : if (sym == M2Bitset_Bitset)
5067 : {
5068 0 : return m2type_GetWordType ();
5069 : }
5070 : else
5071 : {
5072 22075 : return SymbolConversion_Mod2Gcc (sym);
5073 : }
5074 : /* static analysis guarentees a RETURN statement will be used before here. */
5075 : __builtin_unreachable ();
5076 : }
5077 :
5078 :
5079 : /*
5080 : FoldConstBecomes - returns a Tree containing op3.
5081 : The tree will have been folded and
5082 : type converted if necessary.
5083 : */
5084 :
5085 195132 : static tree FoldConstBecomes (unsigned int tokenno, unsigned int op1, unsigned int op3)
5086 : {
5087 195132 : tree t;
5088 195132 : tree type;
5089 195132 : location_t location;
5090 :
5091 195132 : if ((SymbolTable_IsConstSet (op3)) || (((SymbolTable_SkipType (SymbolTable_GetType (op3))) != SymbolTable_NulSym) && (SymbolTable_IsSet (SymbolTable_SkipType (SymbolTable_GetType (op3))))))
5092 : {
5093 3622 : if ((SymbolTable_SkipType (SymbolTable_GetTypeMode (op1))) != (SymbolTable_SkipType (SymbolTable_GetTypeMode (op3))))
5094 : {
5095 6 : DescribeTypeError (tokenno, op1, op3);
5096 : /* Assigning an errant op3 might ICE, therefore it is safer to return op1. */
5097 6 : return SymbolConversion_Mod2Gcc (op1);
5098 : }
5099 : }
5100 195126 : location = M2LexBuf_TokenToLocation (tokenno);
5101 195126 : M2GCCDeclare_TryDeclareConstant (tokenno, op3);
5102 195126 : t = SymbolConversion_Mod2Gcc (op3);
5103 195126 : M2Debug_Assert (t != NULL);
5104 195126 : if (IsConstant (op3))
5105 : {
5106 : /* avoid gcc warning by using compound statement even if not strictly necessary. */
5107 55087 : if (SymbolTable_IsProcedure (op3))
5108 : {
5109 : return t;
5110 : }
5111 54415 : else if (((! (SymbolTable_IsConstString (op3))) && (! (SymbolTable_IsConstSet (op3)))) && ((SymbolTable_SkipType (SymbolTable_GetType (op3))) != (SymbolTable_SkipType (SymbolTable_GetType (op1)))))
5112 : {
5113 : /* avoid dangling else. */
5114 22075 : type = DefaultConvertGM2 (SymbolTable_GetType (op1)); /* do we need this now? --fixme-- */
5115 22075 : t = m2convert_ConvertConstantAndCheck (location, type, t); /* do we need this now? --fixme-- */
5116 : }
5117 32340 : else if ((SymbolTable_GetType (op1)) != SymbolTable_NulSym)
5118 : {
5119 : /* avoid dangling else. */
5120 32340 : t = M2GenGCC_StringToChar (SymbolConversion_Mod2Gcc (op3), SymbolTable_GetType (op1), op3);
5121 : }
5122 : }
5123 : return t;
5124 : /* static analysis guarentees a RETURN statement will be used before here. */
5125 : __builtin_unreachable ();
5126 : }
5127 :
5128 :
5129 : /*
5130 : checkArrayElements - return TRUE if des or expr are not arrays.
5131 : If they are arrays and have different number of
5132 : elements return FALSE, otherwise TRUE.
5133 : */
5134 :
5135 195132 : static bool checkArrayElements (unsigned int des, unsigned int expr, unsigned int virtpos, unsigned int despos, unsigned int exprpos)
5136 : {
5137 195132 : tree e1;
5138 195132 : tree e3;
5139 195132 : unsigned int t1;
5140 195132 : unsigned int t3;
5141 :
5142 195132 : t1 = SymbolTable_GetType (des);
5143 195132 : t3 = SymbolTable_GetType (expr);
5144 195132 : if ((((t1 != SymbolTable_NulSym) && (t3 != SymbolTable_NulSym)) && (SymbolTable_IsArray (SymbolTable_SkipType (SymbolTable_GetType (expr))))) && (SymbolTable_IsArray (SymbolTable_SkipType (SymbolTable_GetType (des)))))
5145 : {
5146 : /* both arrays continue checking */
5147 476 : e1 = m2type_GetArrayNoOfElements (M2LexBuf_TokenToLocation (despos), SymbolConversion_Mod2Gcc (SymbolTable_SkipType (SymbolTable_GetType (des))));
5148 476 : e3 = m2type_GetArrayNoOfElements (M2LexBuf_TokenToLocation (exprpos), SymbolConversion_Mod2Gcc (SymbolTable_SkipType (SymbolTable_GetType (expr))));
5149 476 : if ((m2expr_CompareTrees (e1, e3)) != 0)
5150 : {
5151 0 : M2MetaError_MetaErrorT2 (virtpos, (const char *) "not allowed to assign array {%2Ead} to {%1ad} as they have a different number of elements", 89, des, expr);
5152 0 : return false;
5153 : }
5154 : }
5155 : return true;
5156 : /* static analysis guarentees a RETURN statement will be used before here. */
5157 : __builtin_unreachable ();
5158 : }
5159 :
5160 :
5161 : /*
5162 : CodeInitAddress -
5163 : */
5164 :
5165 54 : static void CodeInitAddress (unsigned int quad, unsigned int op1, unsigned int op2, unsigned int op3)
5166 : {
5167 54 : location_t location;
5168 :
5169 54 : M2GCCDeclare_DeclareConstant (CurrentQuadToken, op3); /* checks to see whether it is a constant and declares it */
5170 54 : M2GCCDeclare_DeclareConstructor (CurrentQuadToken, quad, op3); /* checks to see whether it is a constant and declares it */
5171 54 : location = M2LexBuf_TokenToLocation (CurrentQuadToken);
5172 54 : M2Debug_Assert (op2 == SymbolTable_NulSym);
5173 54 : M2Debug_Assert ((SymbolTable_GetMode (op1)) == SymbolTable_LeftValue);
5174 54 : m2statement_BuildAssignmentStatement (location, SymbolConversion_Mod2Gcc (op1), m2convert_BuildConvert (location, m2type_GetPointerType (), SymbolConversion_Mod2Gcc (op3), false));
5175 54 : }
5176 :
5177 :
5178 : /*
5179 : checkRecordTypes - returns TRUE if des is not a record or if the record
5180 : is the same type as expr.
5181 : */
5182 :
5183 195132 : static bool checkRecordTypes (unsigned int des, unsigned int expr, unsigned int virtpos)
5184 : {
5185 195132 : unsigned int t1;
5186 195132 : unsigned int t2;
5187 :
5188 195132 : if (((SymbolTable_GetType (des)) == SymbolTable_NulSym) || ((SymbolTable_GetMode (des)) == SymbolTable_LeftValue))
5189 : {
5190 24926 : return true;
5191 : }
5192 : else
5193 : {
5194 170206 : t1 = SymbolTable_SkipType (SymbolTable_GetType (des));
5195 170206 : if (SymbolTable_IsRecord (t1))
5196 : {
5197 : /* avoid gcc warning by using compound statement even if not strictly necessary. */
5198 326 : if ((SymbolTable_GetType (expr)) == SymbolTable_NulSym)
5199 : {
5200 0 : M2MetaError_MetaErrorT2 (virtpos, (const char *) "cannot assign an operand of type {%1Ets} to a record type {%2tsa}", 65, expr, des);
5201 0 : return false;
5202 : }
5203 : else
5204 : {
5205 326 : t2 = SymbolTable_SkipType (SymbolTable_GetType (expr));
5206 326 : if (t1 == t2)
5207 : {
5208 : return true;
5209 : }
5210 : else
5211 : {
5212 0 : M2MetaError_MetaErrorT2 (virtpos, (const char *) "cannot assign an operand of type {%1ts} to a record type {%2tsa}", 64, expr, des);
5213 0 : return false;
5214 : }
5215 : }
5216 : }
5217 : }
5218 : return true;
5219 : /* static analysis guarentees a RETURN statement will be used before here. */
5220 : __builtin_unreachable ();
5221 : }
5222 :
5223 :
5224 : /*
5225 : checkIncorrectMeta - checks to see if des and expr are assignment compatible is allows
5226 : generic system types to be assigned.
5227 : */
5228 :
5229 195132 : static bool checkIncorrectMeta (unsigned int des, unsigned int expr, unsigned int virtpos)
5230 : {
5231 195132 : unsigned int t1;
5232 195132 : unsigned int t2;
5233 :
5234 195132 : t1 = SymbolTable_SkipType (SymbolTable_GetType (des));
5235 195132 : t2 = SymbolTable_SkipType (SymbolTable_GetType (expr));
5236 195132 : if ((((t1 == SymbolTable_NulSym) || ((SymbolTable_GetMode (des)) == SymbolTable_LeftValue)) || (t2 == SymbolTable_NulSym)) || ((SymbolTable_GetMode (expr)) == SymbolTable_LeftValue))
5237 : {
5238 25622 : return true;
5239 : }
5240 169510 : else if (((t1 != t2) && (! (M2System_IsGenericSystemType (t1)))) && (! (M2System_IsGenericSystemType (t2))))
5241 : {
5242 : /* avoid dangling else. */
5243 32360 : if (((SymbolTable_IsArray (t1)) || (SymbolTable_IsSet (t1))) || (SymbolTable_IsRecord (t1)))
5244 : {
5245 12 : if (! (M2Base_IsAssignmentCompatible (t1, t2)))
5246 : {
5247 0 : ErrorMessageDecl (virtpos, (const char *) "illegal assignment error between {%1Etad} and {%2tad}", 53, des, expr, true);
5248 0 : return false;
5249 : }
5250 : }
5251 : }
5252 : return true;
5253 : /* static analysis guarentees a RETURN statement will be used before here. */
5254 : __builtin_unreachable ();
5255 : }
5256 :
5257 :
5258 : /*
5259 : checkBecomes - returns TRUE if the checks pass.
5260 : */
5261 :
5262 195132 : static bool checkBecomes (unsigned int des, unsigned int expr, unsigned int virtpos, unsigned int despos, unsigned int exprpos)
5263 : {
5264 195132 : if (((! (checkArrayElements (des, expr, virtpos, despos, exprpos))) || (! (checkRecordTypes (des, expr, virtpos)))) || (! (checkIncorrectMeta (des, expr, virtpos))))
5265 : {
5266 0 : return false;
5267 : }
5268 : return true;
5269 : /* static analysis guarentees a RETURN statement will be used before here. */
5270 : __builtin_unreachable ();
5271 : }
5272 :
5273 :
5274 : /*
5275 : checkDeclare - checks to see if sym is declared and if it is not then declare it.
5276 : */
5277 :
5278 11270 : static void checkDeclare (unsigned int sym)
5279 : {
5280 11270 : if ((sym != SymbolTable_NulSym) && (! (SymbolConversion_GccKnowsAbout (sym))))
5281 : {
5282 : /* avoid gcc warning by using compound statement even if not strictly necessary. */
5283 0 : if ((SymbolTable_IsTemporary (sym)) && (SymbolTable_IsVariableSSA (sym)))
5284 : {
5285 0 : M2GCCDeclare_DeclareLocalVariable (sym);
5286 : }
5287 0 : else if (SymbolTable_IsProcedure (sym))
5288 : {
5289 : /* avoid dangling else. */
5290 0 : M2GCCDeclare_DeclareProcedure (sym);
5291 : }
5292 : }
5293 11270 : }
5294 :
5295 :
5296 : /*
5297 : PerformCodeBecomes -
5298 : */
5299 :
5300 195132 : static void PerformCodeBecomes (location_t location, unsigned int virtpos, unsigned int des, unsigned int expr)
5301 : {
5302 195132 : tree destree;
5303 195132 : tree exprtree;
5304 :
5305 195132 : destree = SymbolConversion_Mod2Gcc (des);
5306 195132 : exprtree = FoldConstBecomes (virtpos, des, expr);
5307 195132 : if ((SymbolTable_IsVar (des)) && (SymbolTable_IsVariableSSA (des)))
5308 : {
5309 0 : Replace (des, exprtree);
5310 : }
5311 195132 : else if (m2type_IsGccStrictTypeEquivalent (destree, exprtree))
5312 : {
5313 : /* avoid dangling else. */
5314 195060 : m2statement_BuildAssignmentStatement (location, destree, exprtree);
5315 : }
5316 : else
5317 : {
5318 : /* avoid dangling else. */
5319 72 : m2statement_CopyByField (location, destree, exprtree);
5320 : }
5321 195132 : }
5322 :
5323 :
5324 : /*
5325 : IsSystemTypeBecomes - return TRUE if expr should be copied using
5326 : memcpy into des. If des or expr are generic
5327 : system types and expr is not constant then
5328 : this is true.
5329 : */
5330 :
5331 195518 : static bool IsSystemTypeBecomes (unsigned int des, unsigned int expr)
5332 : {
5333 195518 : return (((M2System_IsGenericSystemType (SymbolTable_SkipType (SymbolTable_GetType (des)))) != (M2System_IsGenericSystemType (SymbolTable_SkipType (SymbolTable_GetType (expr))))) || (((SymbolTable_IsUnbounded (SymbolTable_SkipType (SymbolTable_GetType (des)))) && (SymbolTable_IsUnbounded (SymbolTable_SkipType (SymbolTable_GetType (expr))))) && ((M2System_IsGenericSystemType (SymbolTable_SkipType (SymbolTable_GetType (SymbolTable_GetType (des))))) != (M2System_IsGenericSystemType (SymbolTable_SkipType (SymbolTable_GetType (SymbolTable_GetType (expr)))))))) && (! (IsConstant (expr)));
5334 : /* static analysis guarentees a RETURN statement will be used before here. */
5335 : __builtin_unreachable ();
5336 : }
5337 :
5338 196070 : static void CodeBecomes (unsigned int quad)
5339 : {
5340 196070 : bool constExpr;
5341 196070 : bool overflowChecking;
5342 196070 : M2Quads_QuadOperator op;
5343 196070 : unsigned int des;
5344 196070 : unsigned int op2;
5345 196070 : unsigned int expr;
5346 196070 : unsigned int virtpos;
5347 196070 : unsigned int becomespos;
5348 196070 : unsigned int despos;
5349 196070 : unsigned int op2pos;
5350 196070 : unsigned int exprpos;
5351 196070 : tree length;
5352 196070 : tree exprt;
5353 196070 : location_t location;
5354 :
5355 : /*
5356 : ------------------------------------------------------------------------------
5357 : := Operator
5358 : ------------------------------------------------------------------------------
5359 : Sym1<I> := Sym3<I> := produces a constant
5360 : Sym1<O> := Sym3<O> := has the effect Mem[Sym1<I>] := Mem[Sym3<I>]
5361 : */
5362 196070 : M2Quads_GetQuadOtok (quad, &becomespos, &op, &des, &op2, &expr, &overflowChecking, &constExpr, &despos, &op2pos, &exprpos);
5363 196070 : M2Debug_Assert (op2pos == M2LexBuf_UnknownTokenNo);
5364 196070 : M2GCCDeclare_DeclareConstant (exprpos, expr); /* Check to see whether expr is a constant and declare it. */
5365 196070 : M2GCCDeclare_DeclareConstructor (exprpos, quad, expr); /* Check to see whether expr is a constant and declare it. */
5366 196070 : virtpos = M2LexBuf_MakeVirtualTok (becomespos, despos, exprpos);
5367 196070 : location = M2LexBuf_TokenToLocation (virtpos);
5368 196070 : if (M2Options_StrictTypeChecking && (! (M2Check_AssignmentTypeCompatible (virtpos, (const char *) "", 0, des, expr, true))))
5369 : {
5370 0 : ErrorMessageDecl (virtpos, (const char *) "assignment check caught mismatch between {%1Ead} and {%2ad}", 59, des, expr, true);
5371 : }
5372 196070 : if ((SymbolTable_IsConstString (expr)) && (! (SymbolTable_IsConstStringKnown (expr))))
5373 : {
5374 0 : M2MetaError_MetaErrorT2 (virtpos, (const char *) "internal error: CodeBecomes {%1Aad} in quad {%2n}", 49, des, quad);
5375 : }
5376 196070 : if ((SymbolTable_IsConst (des)) && (! (SymbolConversion_GccKnowsAbout (des))))
5377 : {
5378 6 : M2GCCDeclare_ConstantKnownAndUsed (des, CheckConstant (virtpos, des, expr));
5379 : }
5380 196064 : else if ((SymbolTable_IsConstString (expr)) && ((SymbolTable_SkipTypeAndSubrange (SymbolTable_GetType (des))) != M2Base_Char))
5381 : {
5382 : /* avoid dangling else. */
5383 546 : checkDeclare (des);
5384 546 : if (! (M2GenGCC_PrepareCopyString (becomespos, &length, &exprt, expr, SymbolTable_SkipType (SymbolTable_GetType (des)))))
5385 : {
5386 12 : ErrorMessageDecl (virtpos, (const char *) "string constant {%1Ea} is too large to be assigned to the array {%2ad}", 70, expr, des, true);
5387 : }
5388 546 : m2statement_CopyMemcpy (location, SymbolConversion_Mod2Gcc (des), exprt, FindSize (virtpos, des));
5389 : }
5390 : else
5391 : {
5392 : /* avoid dangling else. */
5393 195518 : if (IsSystemTypeBecomes (des, expr))
5394 : {
5395 386 : checkDeclare (des);
5396 386 : m2statement_CopyMemcpy (location, SymbolConversion_Mod2Gcc (des), SymbolConversion_Mod2Gcc (expr), FindSize (virtpos, des));
5397 : }
5398 : else
5399 : {
5400 195132 : if (checkBecomes (des, expr, virtpos, despos, exprpos))
5401 : {
5402 195132 : PerformCodeBecomes (location, virtpos, des, expr);
5403 : }
5404 : else
5405 : {
5406 0 : M2Quads_SubQuad (quad); /* We don't want multiple errors for the quad. */
5407 : }
5408 : }
5409 : }
5410 196070 : }
5411 :
5412 :
5413 : /*
5414 : getrvalue -
5415 : */
5416 :
5417 10948 : static tree getrvalue (location_t location, unsigned int expr, unsigned int type, bool islvalue)
5418 : {
5419 10948 : return m2expr_GetRValue (location, SymbolConversion_Mod2Gcc (expr), SymbolConversion_Mod2Gcc (type), islvalue);
5420 : /* static analysis guarentees a RETURN statement will be used before here. */
5421 : __builtin_unreachable ();
5422 : }
5423 :
5424 :
5425 : /*
5426 : LValueToGenericPtrOrConvert - if sym is an lvalue then convert to pointer type
5427 : else convert to type, type. Return the converted tree.
5428 : */
5429 :
5430 19547 : static tree LValueToGenericPtrOrConvert (unsigned int sym, tree type)
5431 : {
5432 19547 : tree n;
5433 19547 : location_t location;
5434 :
5435 19547 : n = SymbolConversion_Mod2Gcc (sym);
5436 19547 : location = M2LexBuf_TokenToLocation (SymbolTable_GetDeclaredMod (sym));
5437 19547 : if (n == NULL)
5438 : {
5439 0 : M2Error_InternalError ((const char *) "expecting symbol to be resolved", 31);
5440 : }
5441 19547 : if ((SymbolTable_GetMode (sym)) == SymbolTable_LeftValue)
5442 : {
5443 0 : n = m2convert_BuildConvert (location, m2type_GetPointerType (), n, false);
5444 : }
5445 : else
5446 : {
5447 19547 : n = m2convert_BuildConvert (location, type, n, false);
5448 : }
5449 19547 : return n;
5450 : /* static analysis guarentees a RETURN statement will be used before here. */
5451 : __builtin_unreachable ();
5452 : }
5453 :
5454 :
5455 : /*
5456 : FoldBinary - check whether we can fold the binop operation.
5457 : */
5458 :
5459 731440 : static void FoldBinary (unsigned int tokenno, M2GCCDeclare_WalkAction p, m2expr_BuildBinProcedure binop, unsigned int quad, unsigned int op1, unsigned int op2, unsigned int op3)
5460 : {
5461 731440 : tree tl;
5462 731440 : tree tr;
5463 731440 : tree tv;
5464 731440 : tree resType;
5465 731440 : location_t location;
5466 :
5467 : /* firstly ensure that constant literals are declared */
5468 731440 : M2GCCDeclare_TryDeclareConstant (tokenno, op3);
5469 731440 : M2GCCDeclare_TryDeclareConstant (tokenno, op2);
5470 731440 : location = M2LexBuf_TokenToLocation (tokenno);
5471 731440 : if ((SymbolTable_IsConst (op2)) && (SymbolTable_IsConst (op3)))
5472 : {
5473 41610 : if ((SymbolConversion_GccKnowsAbout (op2)) && (SymbolConversion_GccKnowsAbout (op3)))
5474 : {
5475 : /* avoid gcc warning by using compound statement even if not strictly necessary. */
5476 : /* fine, we can take advantage of this and fold constants */
5477 34914 : if (SymbolTable_IsConst (op1))
5478 : {
5479 34914 : M2Debug_Assert ((M2Base_MixTypes (FindType (op3), FindType (op2), tokenno)) != SymbolTable_NulSym);
5480 34914 : SymbolTable_PutConst (op1, M2Base_MixTypes (FindType (op3), FindType (op2), tokenno));
5481 34914 : tl = M2GenGCC_LValueToGenericPtr (location, op2);
5482 34914 : tr = M2GenGCC_LValueToGenericPtr (location, op3);
5483 34914 : if ((SymbolTable_GetType (op1)) == SymbolTable_NulSym)
5484 : {
5485 0 : resType = m2type_GetM2ZType ();
5486 : }
5487 : else
5488 : {
5489 34914 : resType = SymbolConversion_Mod2Gcc (SymbolTable_GetType (op1));
5490 : }
5491 34914 : tl = m2convert_BuildConvert (location, resType, tl, false);
5492 34914 : tr = m2convert_BuildConvert (location, resType, tr, false);
5493 34914 : tv = (*binop.proc) (location, tl, tr, true);
5494 34914 : M2ALU_CheckOrResetOverflow (tokenno, tv, M2Quads_MustCheckOverflow (quad));
5495 34902 : SymbolConversion_AddModGcc (op1, m2decl_DeclareKnownConstant (location, resType, tv));
5496 34902 : (*p.proc) (op1);
5497 34902 : NoChange = false;
5498 34902 : M2Quads_SubQuad (quad);
5499 : }
5500 : /* we can still fold the expression, but not the assignment,
5501 : however, we will not do this here but in CodeBinary
5502 : */
5503 : }
5504 : }
5505 731428 : }
5506 :
5507 :
5508 : /*
5509 : ConvertBinaryOperands -
5510 : */
5511 :
5512 138165 : static void ConvertBinaryOperands (location_t location, tree *tl, tree *tr, unsigned int type, unsigned int op2, unsigned int op3)
5513 : {
5514 138165 : (*tl) = NULL;
5515 138165 : (*tr) = NULL;
5516 138165 : if ((SymbolTable_GetMode (op2)) == SymbolTable_LeftValue)
5517 : {
5518 90 : (*tl) = M2GenGCC_LValueToGenericPtr (location, op2);
5519 90 : type = M2System_Address;
5520 : }
5521 138165 : if ((SymbolTable_GetMode (op3)) == SymbolTable_LeftValue)
5522 : {
5523 0 : (*tr) = M2GenGCC_LValueToGenericPtr (location, op3);
5524 0 : type = M2System_Address;
5525 : }
5526 138165 : if (((*tl) == NULL) && ((*tr) == NULL))
5527 : {
5528 138075 : (*tl) = m2convert_BuildConvert (location, SymbolConversion_Mod2Gcc (type), SymbolConversion_Mod2Gcc (op2), false);
5529 138075 : (*tr) = m2convert_BuildConvert (location, SymbolConversion_Mod2Gcc (type), SymbolConversion_Mod2Gcc (op3), false);
5530 : }
5531 90 : else if ((*tl) == NULL)
5532 : {
5533 : /* avoid dangling else. */
5534 0 : (*tl) = m2convert_BuildConvert (location, SymbolConversion_Mod2Gcc (type), SymbolConversion_Mod2Gcc (op2), false);
5535 : }
5536 90 : else if ((*tr) == NULL)
5537 : {
5538 : /* avoid dangling else. */
5539 90 : (*tr) = m2convert_BuildConvert (location, SymbolConversion_Mod2Gcc (type), SymbolConversion_Mod2Gcc (op3), false);
5540 : }
5541 138165 : }
5542 :
5543 :
5544 : /*
5545 : CodeBinaryCheck - encode a binary arithmetic operation.
5546 : */
5547 :
5548 50150 : static void CodeBinaryCheck (m2expr_BuildBinCheckProcedure binop, unsigned int quad)
5549 : {
5550 50150 : M2Quads_QuadOperator op;
5551 50150 : unsigned int op1;
5552 50150 : unsigned int op2;
5553 50150 : unsigned int op3;
5554 50150 : unsigned int op1pos;
5555 50150 : unsigned int op2pos;
5556 50150 : unsigned int op3pos;
5557 50150 : unsigned int lowestType;
5558 50150 : unsigned int type;
5559 50150 : tree min;
5560 50150 : tree max;
5561 50150 : tree lowest;
5562 50150 : tree tv;
5563 50150 : tree tl;
5564 50150 : tree tr;
5565 50150 : location_t location;
5566 :
5567 : /* firstly ensure that constant literals are declared. */
5568 50150 : M2Quads_GetQuadtok (quad, &op, &op1, &op2, &op3, &op1pos, &op2pos, &op3pos);
5569 50150 : M2GCCDeclare_DeclareConstant (op3pos, op3);
5570 50150 : M2GCCDeclare_DeclareConstant (op2pos, op2);
5571 50150 : location = M2LexBuf_TokenToLocation (op1pos);
5572 50150 : type = MixTypesBinary (op2, op3, op1pos, M2Quads_MustCheckOverflow (quad));
5573 50150 : ConvertBinaryOperands (location, &tl, &tr, type, op2, op3);
5574 50150 : lowestType = SymbolTable_GetLType (op1);
5575 50150 : lowest = SymbolConversion_Mod2Gcc (lowestType);
5576 50150 : if (M2Range_GetMinMax (CurrentQuadToken, lowestType, &min, &max))
5577 : {
5578 46456 : tv = (*binop.proc) (location, tl, tr, lowest, min, max);
5579 : }
5580 : else
5581 : {
5582 3694 : tv = (*binop.proc) (location, tl, tr, NULL, NULL, NULL);
5583 : }
5584 50150 : M2ALU_CheckOrResetOverflow (op1pos, tv, M2Quads_MustCheckOverflow (quad));
5585 50150 : if (SymbolTable_IsConst (op1))
5586 : {
5587 : /* still have a constant which was not resolved, pass it to gcc. */
5588 0 : M2Debug_Assert ((M2Base_MixTypes (FindType (op3), FindType (op2), op3pos)) != SymbolTable_NulSym);
5589 0 : SymbolTable_PutConst (op1, M2Base_MixTypes (FindType (op3), FindType (op2), op3pos));
5590 0 : M2GCCDeclare_ConstantKnownAndUsed (op1, m2decl_DeclareKnownConstant (location, SymbolConversion_Mod2Gcc (SymbolTable_GetType (op3)), tv));
5591 : }
5592 : else
5593 : {
5594 50150 : if (M2SSA_EnableSSA && (SymbolTable_IsVariableSSA (op1)))
5595 : {
5596 : Replace (op1, tv);
5597 : }
5598 : else
5599 : {
5600 50150 : m2statement_BuildAssignmentStatement (location, SymbolConversion_Mod2Gcc (op1), tv);
5601 : }
5602 : }
5603 50150 : }
5604 :
5605 :
5606 : /*
5607 : MixTypesBinary - depending upon overflowCheck do not check pointer arithmetic.
5608 : */
5609 :
5610 62138 : static unsigned int MixTypesBinary (unsigned int left, unsigned int right, unsigned int tokpos, bool overflowCheck)
5611 : {
5612 62138 : if (! overflowCheck && ((SymbolTable_IsPointer (SymbolTable_GetTypeMode (left))) || (SymbolTable_IsPointer (SymbolTable_GetTypeMode (right)))))
5613 : {
5614 8706 : return M2System_Address;
5615 : }
5616 : else
5617 : {
5618 53432 : return M2Base_MixTypesDecl (left, right, FindType (left), FindType (right), tokpos);
5619 : }
5620 : /* static analysis guarentees a RETURN statement will be used before here. */
5621 : __builtin_unreachable ();
5622 : }
5623 :
5624 :
5625 : /*
5626 : CodeBinary - encode a binary arithmetic operation.
5627 : */
5628 :
5629 11988 : static void CodeBinary (m2expr_BuildBinProcedure binop, unsigned int quad)
5630 : {
5631 11988 : M2Quads_QuadOperator op;
5632 11988 : unsigned int op1;
5633 11988 : unsigned int op2;
5634 11988 : unsigned int op3;
5635 11988 : unsigned int op1pos;
5636 11988 : unsigned int op2pos;
5637 11988 : unsigned int op3pos;
5638 11988 : unsigned int type;
5639 11988 : tree tv;
5640 11988 : tree tl;
5641 11988 : tree tr;
5642 11988 : location_t location;
5643 :
5644 : /* firstly ensure that constant literals are declared */
5645 11988 : M2Quads_GetQuadtok (quad, &op, &op1, &op2, &op3, &op1pos, &op2pos, &op3pos);
5646 11988 : M2GCCDeclare_DeclareConstant (op3pos, op3);
5647 11988 : M2GCCDeclare_DeclareConstant (op2pos, op2);
5648 11988 : location = M2LexBuf_TokenToLocation (op1pos);
5649 11988 : type = MixTypesBinary (op2, op3, op1pos, M2Quads_MustCheckOverflow (quad));
5650 11988 : ConvertBinaryOperands (location, &tl, &tr, type, op2, op3);
5651 11988 : tv = (*binop.proc) (location, tl, tr, false);
5652 11988 : M2ALU_CheckOrResetOverflow (op1pos, tv, M2Quads_MustCheckOverflow (quad));
5653 11988 : if (SymbolTable_IsConst (op1))
5654 : {
5655 : /* still have a constant which was not resolved, pass it to gcc */
5656 0 : M2Debug_Assert ((M2Base_MixTypes (FindType (op3), FindType (op2), op1pos)) != SymbolTable_NulSym);
5657 0 : SymbolTable_PutConst (op1, M2Base_MixTypes (FindType (op3), FindType (op2), op1pos));
5658 0 : M2GCCDeclare_ConstantKnownAndUsed (op1, m2decl_DeclareKnownConstant (location, SymbolConversion_Mod2Gcc (SymbolTable_GetType (op3)), tv));
5659 : }
5660 : else
5661 : {
5662 11988 : if (M2SSA_EnableSSA && (SymbolTable_IsVariableSSA (op1)))
5663 : {
5664 : Replace (op1, tv);
5665 : }
5666 : else
5667 : {
5668 11988 : m2statement_BuildAssignmentStatement (location, SymbolConversion_Mod2Gcc (op1), tv);
5669 : }
5670 : }
5671 11988 : }
5672 :
5673 :
5674 : /*
5675 : NoWalkProcedure -
5676 : */
5677 :
5678 0 : static void NoWalkProcedure (unsigned int param __attribute__((unused)))
5679 : {
5680 0 : }
5681 :
5682 :
5683 : /*
5684 : CheckBinaryExpressionTypes - returns TRUE if all expression checks pass.
5685 : If the expression check fails quad is removed,
5686 : the walk procedure (des) is called and NoChange is
5687 : set to FALSE.
5688 : */
5689 :
5690 4444 : static bool CheckBinaryExpressionTypes (unsigned int quad, M2GCCDeclare_WalkAction p)
5691 : {
5692 4444 : unsigned int des;
5693 4444 : unsigned int left;
5694 4444 : unsigned int right;
5695 4444 : bool typeChecking;
5696 4444 : bool constExpr;
5697 4444 : bool overflowChecking;
5698 4444 : unsigned int despos;
5699 4444 : unsigned int leftpos;
5700 4444 : unsigned int rightpos;
5701 4444 : unsigned int operatorpos;
5702 4444 : unsigned int subexprpos;
5703 4444 : M2Quads_QuadOperator op;
5704 :
5705 4444 : M2Quads_GetQuadOTypetok (quad, &operatorpos, &op, &des, &left, &right, &overflowChecking, &typeChecking, &constExpr, &despos, &leftpos, &rightpos);
5706 4444 : if ((typeChecking && (op != M2Quads_LogicalRotateOp)) && (op != M2Quads_LogicalShiftOp))
5707 : {
5708 2290 : subexprpos = M2LexBuf_MakeVirtualTok (operatorpos, leftpos, rightpos);
5709 2290 : if (M2Options_StrictTypeChecking && (! (M2Check_ExpressionTypeCompatible (subexprpos, (const char *) "", 0, left, right, M2Options_StrictTypeChecking, false))))
5710 : {
5711 0 : M2MetaError_MetaErrorT2 (subexprpos, (const char *) "expression mismatch between {%1Etad} and {%2tad}", 48, left, right);
5712 0 : NoChange = false;
5713 0 : M2Quads_SubQuad (quad);
5714 0 : (*p.proc) (des);
5715 0 : return false;
5716 : }
5717 : }
5718 : return true;
5719 : /* static analysis guarentees a RETURN statement will be used before here. */
5720 : __builtin_unreachable ();
5721 : }
5722 :
5723 :
5724 : /*
5725 : CheckElementSetTypes - returns TRUE if all expression checks pass.
5726 : If the expression check fails quad is removed,
5727 : the walk procedure (des) is called and NoChange is
5728 : set to FALSE.
5729 : */
5730 :
5731 2476 : static bool CheckElementSetTypes (unsigned int quad)
5732 : {
5733 2476 : unsigned int righttype;
5734 2476 : unsigned int ignore;
5735 2476 : unsigned int left;
5736 2476 : unsigned int right;
5737 2476 : bool constExpr;
5738 2476 : bool overflowChecking;
5739 2476 : unsigned int ignorepos;
5740 2476 : unsigned int leftpos;
5741 2476 : unsigned int rightpos;
5742 2476 : unsigned int operatorpos;
5743 2476 : unsigned int subexprpos;
5744 2476 : M2Quads_QuadOperator op;
5745 :
5746 2476 : M2Quads_GetQuadOtok (quad, &operatorpos, &op, &left, &right, &ignore, &overflowChecking, &constExpr, &leftpos, &rightpos, &ignorepos);
5747 2476 : subexprpos = M2LexBuf_MakeVirtualTok (operatorpos, leftpos, rightpos);
5748 2476 : righttype = SymbolTable_GetType (right);
5749 2476 : if (M2Options_StrictTypeChecking && (! (M2Check_ExpressionTypeCompatible (subexprpos, (const char *) "", 0, left, right, M2Options_StrictTypeChecking, true))))
5750 : {
5751 0 : M2MetaError_MetaErrorT2 (subexprpos, (const char *) "the types used in expression {%1Etad} {%kIN} {%2tad} are incompatible", 69, left, right);
5752 0 : NoChange = false;
5753 0 : M2Quads_SubQuad (quad);
5754 0 : return false;
5755 : }
5756 2476 : if ((righttype == SymbolTable_NulSym) || (! (SymbolTable_IsSet (SymbolTable_SkipType (righttype)))))
5757 : {
5758 12 : M2MetaError_MetaErrorT1 (rightpos, (const char *) "the right hand side of an {%kIN} expression is expecting {%1Ead} to be a {%kSET} type and not a {%1Etadv}", 105, right);
5759 12 : NoChange = false;
5760 12 : M2Quads_SubQuad (quad);
5761 12 : return false;
5762 : }
5763 : return true;
5764 : /* static analysis guarentees a RETURN statement will be used before here. */
5765 : __builtin_unreachable ();
5766 : }
5767 :
5768 :
5769 : /*
5770 : CodeBinarySet - encode a binary set AND arithmetic operation.
5771 : Set operands may be longer than a word.
5772 : */
5773 :
5774 1228 : static void CodeBinarySet (M2GenGCC_ProcedureCardinal constp, M2GenGCC_BinaryFunction binfunc, NameKey_Name wideprocname, unsigned int quad)
5775 : {
5776 1228 : M2Quads_QuadOperator op;
5777 1228 : unsigned int operatorpos;
5778 1228 : unsigned int combinedpos;
5779 1228 : unsigned int despos;
5780 1228 : unsigned int leftpos;
5781 1228 : unsigned int rightpos;
5782 1228 : unsigned int des;
5783 1228 : unsigned int left;
5784 1228 : unsigned int right;
5785 1228 : bool overflowChecking;
5786 1228 : bool typeChecking;
5787 1228 : bool constExpr;
5788 1228 : location_t location;
5789 1228 : unsigned int settype;
5790 :
5791 1228 : M2Quads_GetQuadOTypetok (quad, &operatorpos, &op, &des, &left, &right, &overflowChecking, &typeChecking, &constExpr, &despos, &leftpos, &rightpos);
5792 : /* Firstly ensure that constant literals are declared. */
5793 1228 : M2GCCDeclare_DeclareConstant (rightpos, right);
5794 1228 : M2GCCDeclare_DeclareConstant (leftpos, left);
5795 1228 : M2GCCDeclare_DeclareConstructor (rightpos, quad, right);
5796 1228 : M2GCCDeclare_DeclareConstructor (leftpos, quad, left);
5797 1228 : if (SymbolTable_IsConst (des))
5798 : {
5799 6 : combinedpos = M2LexBuf_MakeVirtual2Tok (leftpos, rightpos);
5800 6 : if ((SymbolTable_IsValueSolved (left)) && (SymbolTable_IsValueSolved (right)))
5801 : {
5802 6 : M2Debug_Assert ((M2Base_MixTypes (FindType (left), FindType (right), combinedpos)) != SymbolTable_NulSym);
5803 6 : SymbolTable_PutConst (des, FindType (right));
5804 6 : SymbolTable_PushValue (left);
5805 6 : SymbolTable_PushValue (right);
5806 6 : (*constp.proc) (combinedpos);
5807 6 : SymbolTable_PopValue (des);
5808 6 : SymbolTable_PutConstSet (des);
5809 : }
5810 : else
5811 : {
5812 0 : M2MetaError_MetaErrorT0 (combinedpos, (const char *) "{%E}constant expression cannot be evaluated", 43);
5813 : }
5814 : }
5815 : else
5816 : {
5817 1222 : checkDeclare (des);
5818 1222 : settype = SymbolTable_GetLType (des);
5819 1222 : M2Debug_Assert (SymbolTable_IsSet (settype));
5820 1222 : combinedpos = M2LexBuf_MakeVirtualTok (despos, leftpos, rightpos);
5821 1222 : if (SymbolTable_GetSetInWord (settype))
5822 : {
5823 1048 : location = M2LexBuf_TokenToLocation (combinedpos);
5824 1048 : SetNarrowBinary (location, binfunc, settype, des, left, right);
5825 : }
5826 : else
5827 : {
5828 174 : SetWideBinary (combinedpos, wideprocname, settype, des, left, right);
5829 : }
5830 : }
5831 1228 : }
5832 :
5833 :
5834 : /*
5835 : MakeTemporarySetName - returns a Name using the template _Tset%d.
5836 : */
5837 :
5838 3296 : static NameKey_Name MakeTemporarySetName (void)
5839 : {
5840 3296 : NameKey_Name name;
5841 3296 : DynamicStrings_String s;
5842 :
5843 3296 : SetTemporaryNo += 1;
5844 3296 : s = FormatStrings_Sprintf1 (DynamicStrings_Mark (DynamicStrings_InitString ((const char *) "_Tset%d", 7)), (const unsigned char *) &SetTemporaryNo, (sizeof (SetTemporaryNo)-1));
5845 3296 : name = NameKey_makekey (DynamicStrings_string (s));
5846 3296 : s = DynamicStrings_KillString (s);
5847 3296 : return name;
5848 : /* static analysis guarentees a RETURN statement will be used before here. */
5849 : __builtin_unreachable ();
5850 : }
5851 :
5852 :
5853 : /*
5854 : SetWideBinary -
5855 : */
5856 :
5857 174 : static void SetWideBinary (unsigned int tokenno, NameKey_Name wideprocname, unsigned int settype, unsigned int des, unsigned int left, unsigned int right)
5858 : {
5859 174 : if (M2Options_OptimizeSets)
5860 : {
5861 : /* avoid gcc warning by using compound statement even if not strictly necessary. */
5862 68 : if (wideprocname == (NameKey_MakeKey ((const char *) "And", 3)))
5863 : {
5864 4 : SetWideBinaryBuiltin (tokenno, (M2GenGCC_BinaryFunction) {(M2GenGCC_BinaryFunction_t) m2expr_BuildLogicalAnd}, des, left, right);
5865 4 : return;
5866 : }
5867 64 : else if (wideprocname == (NameKey_MakeKey ((const char *) "Or", 2)))
5868 : {
5869 : /* avoid dangling else. */
5870 56 : SetWideBinaryBuiltin (tokenno, (M2GenGCC_BinaryFunction) {(M2GenGCC_BinaryFunction_t) m2expr_BuildLogicalOr}, des, left, right);
5871 56 : return;
5872 : }
5873 : }
5874 114 : SetWideBinaryLibrary (tokenno, wideprocname, settype, des, left, right);
5875 : }
5876 :
5877 :
5878 : /*
5879 : SetWideBinaryLibrary - call wideprocname (des, left, right) passing des, left, right
5880 : as an array of byte.
5881 : */
5882 :
5883 114 : static void SetWideBinaryLibrary (unsigned int tokenno, NameKey_Name wideprocname, unsigned int settype, unsigned int des, unsigned int left, unsigned int right)
5884 : {
5885 114 : location_t location;
5886 114 : unsigned int procedure;
5887 114 : unsigned int param1;
5888 114 : unsigned int param2;
5889 114 : unsigned int param3;
5890 114 : tree highbit;
5891 114 : tree array1;
5892 114 : tree array2;
5893 114 : tree array3;
5894 114 : tree call;
5895 :
5896 114 : procedure = FromM2WIDESETImport (tokenno, wideprocname);
5897 114 : checkDeclare (procedure);
5898 114 : location = M2LexBuf_TokenToLocation (tokenno);
5899 114 : param1 = SymbolTable_GetNthParamAnyClosest (procedure, 1, SymbolTable_GetMainModule ());
5900 114 : param2 = SymbolTable_GetNthParamAnyClosest (procedure, 2, SymbolTable_GetMainModule ());
5901 114 : param3 = SymbolTable_GetNthParamAnyClosest (procedure, 3, SymbolTable_GetMainModule ());
5902 114 : array1 = CreateSetArrayParam (location, tokenno, des, param1);
5903 114 : array2 = CreateSetArrayParam (location, tokenno, left, param2);
5904 114 : array3 = CreateSetArrayParam (location, tokenno, right, param3);
5905 114 : highbit = m2convert_ToCardinal (location, CalcHighSetBit (location, settype));
5906 114 : m2statement_BuildParam (location, highbit); /* Parameter 4. */
5907 114 : m2statement_BuildParam (location, array3); /* Parameter 3. */
5908 114 : m2statement_BuildParam (location, array2); /* Parameter 2. */
5909 114 : m2statement_BuildParam (location, array1); /* Parameter 1. */
5910 114 : call = m2statement_BuildProcedureCallTree (location, SymbolConversion_Mod2Gcc (procedure), NULL); /* Parameter 1. */
5911 114 : m2statement_SetLastFunction (NULL);
5912 114 : m2type_AddStatement (location, call);
5913 114 : }
5914 :
5915 :
5916 : /*
5917 : SetWideBinaryBuiltin - build an builtin wideset NOT operation.
5918 : */
5919 :
5920 60 : static void SetWideBinaryBuiltin (unsigned int tokenno, M2GenGCC_BinaryFunction binfunc, unsigned int des, unsigned int left, unsigned int right)
5921 : {
5922 60 : location_t location;
5923 60 : tree byte;
5924 60 : tree lhs;
5925 60 : tree rhs;
5926 60 : tree dest;
5927 60 : tree index;
5928 60 : tree high;
5929 :
5930 60 : location = M2LexBuf_TokenToLocation (tokenno);
5931 60 : high = ResolveHigh (tokenno, 1, des);
5932 60 : index = m2expr_GetIntegerZero (location);
5933 60 : byte = SymbolConversion_Mod2Gcc (M2System_Byte);
5934 1512 : do {
5935 1512 : rhs = m2expr_BuildArray (location, byte, getrvalue (location, right, SymbolTable_GetType (right), (SymbolTable_GetMode (right)) == SymbolTable_LeftValue), index, m2expr_GetIntegerZero (location));
5936 1512 : lhs = m2expr_BuildArray (location, byte, getrvalue (location, left, SymbolTable_GetType (left), (SymbolTable_GetMode (left)) == SymbolTable_LeftValue), index, m2expr_GetIntegerZero (location));
5937 1512 : rhs = (*binfunc.proc) (location, lhs, rhs);
5938 1512 : rhs = m2convert_BuildConvert (location, byte, rhs, false);
5939 1512 : dest = m2expr_BuildArray (location, byte, getrvalue (location, des, SymbolTable_GetType (des), (SymbolTable_GetMode (des)) == SymbolTable_LeftValue), index, m2expr_GetIntegerZero (location));
5940 1512 : m2statement_BuildAssignmentStatement (location, dest, rhs);
5941 1512 : M2ALU_PushIntegerTree (index);
5942 1512 : M2ALU_PushCard (1);
5943 1512 : M2ALU_Addn ();
5944 1512 : index = M2ALU_PopIntegerTree ();
5945 1512 : } while (! ((m2expr_CompareTrees (index, high)) > 0));
5946 60 : }
5947 :
5948 :
5949 : /*
5950 : SetNarrowBinary - create tree consisting of:
5951 : result := binfunc (left, right)
5952 : result, left and right can be lvalues.
5953 : */
5954 :
5955 1048 : static void SetNarrowBinary (location_t location, M2GenGCC_BinaryFunction binfunc, unsigned int settype, unsigned int result, unsigned int left, unsigned int right)
5956 : {
5957 1048 : bool isResultL;
5958 1048 : bool isLeftL;
5959 1048 : bool isRightL;
5960 :
5961 1048 : isResultL = (SymbolTable_GetMode (result)) == SymbolTable_LeftValue;
5962 1048 : isLeftL = (SymbolTable_GetMode (left)) == SymbolTable_LeftValue;
5963 1048 : isRightL = (SymbolTable_GetMode (right)) == SymbolTable_LeftValue;
5964 1048 : m2statement_BuildAssignmentStatement (location, getrvalue (location, result, settype, isResultL), (tree) ((*binfunc.proc) (location, getrvalue (location, left, settype, isLeftL), getrvalue (location, right, settype, isRightL))));
5965 1048 : }
5966 :
5967 :
5968 : /*
5969 : CreateSetArrayParam - return a gcc tree containing value contained in an unbounded
5970 : array parameter.
5971 : */
5972 :
5973 3296 : static tree CreateSetArrayParam (location_t location, unsigned int tokenno, unsigned int value, unsigned int param)
5974 : {
5975 3296 : tree dataAddress;
5976 3296 : tree designator;
5977 3296 : tree oarecord;
5978 3296 : unsigned int unbounded;
5979 3296 : unsigned int HighField;
5980 3296 : unsigned int scope;
5981 :
5982 3296 : unbounded = SymbolTable_GetType (param);
5983 3296 : M2Debug_Assert (SymbolTable_IsUnbounded (unbounded));
5984 3296 : scope = GetActiveScope ();
5985 : /* Declare oarecord which has a pointer and high field. This will be passed as
5986 : a parameter into the runtime set procedure and appear as an ARRAY OF BYTE. */
5987 3296 : oarecord = m2decl_DeclareKnownVariable (location, const_cast <const char * > (static_cast <char * > (NameKey_KeyToCharStar (MakeTemporarySetName ()))), SymbolConversion_Mod2Gcc (unbounded), false, false, true, SymbolTable_IsProcedure (scope), SymbolConversion_Mod2Gcc (scope), NULL);
5988 : /* Designator is oarecord.address. */
5989 3296 : designator = m2expr_BuildComponentRef (location, oarecord, SymbolConversion_Mod2Gcc (SymbolTable_GetUnboundedAddressOffset (unbounded)));
5990 3296 : if ((SymbolTable_GetMode (value)) == SymbolTable_LeftValue)
5991 : {
5992 : /* Already pointing to the data. */
5993 200 : dataAddress = SymbolConversion_Mod2Gcc (value);
5994 : }
5995 : else
5996 : {
5997 3096 : dataAddress = m2expr_BuildAddr (location, SymbolConversion_Mod2Gcc (value), false);
5998 : }
5999 3296 : m2statement_BuildAssignmentStatement (location, designator, dataAddress);
6000 3296 : HighField = SymbolTable_GetUnboundedHighOffset (unbounded, 1);
6001 3296 : designator = m2expr_BuildComponentRef (location, oarecord, SymbolConversion_Mod2Gcc (HighField));
6002 3296 : m2statement_BuildAssignmentStatement (location, designator, ResolveHigh (tokenno, 1, value));
6003 3296 : return oarecord;
6004 : /* static analysis guarentees a RETURN statement will be used before here. */
6005 : __builtin_unreachable ();
6006 : }
6007 :
6008 :
6009 : /*
6010 : CheckUnaryOperand - checks to see whether operand is using a generic type.
6011 : */
6012 :
6013 918 : static bool CheckUnaryOperand (unsigned int quad, unsigned int operand)
6014 : {
6015 918 : unsigned int type;
6016 918 : DynamicStrings_String s;
6017 918 : DynamicStrings_String op;
6018 :
6019 918 : type = SymbolTable_SkipType (SymbolTable_GetType (operand));
6020 918 : if ((((M2System_Word == type) || (M2System_IsWordN (type))) || (M2System_Byte == type)) || (M2System_Loc == type))
6021 : {
6022 6 : op = M2Quads_GetM2OperatorDesc (M2Quads_GetQuadOp (quad));
6023 6 : s = DynamicStrings_InitString ((const char *) "operand of type {%1Ets} is not allowed in an unary expression", 61);
6024 6 : if (op != NULL)
6025 : {
6026 6 : s = DynamicStrings_ConCatChar (s, ' ');
6027 6 : s = DynamicStrings_ConCat (s, DynamicStrings_Mark (op));
6028 : }
6029 6 : M2MetaError_MetaErrorStringT1 (CurrentQuadToken, s, operand);
6030 6 : return false;
6031 : }
6032 : return true;
6033 : /* static analysis guarentees a RETURN statement will be used before here. */
6034 : __builtin_unreachable ();
6035 : }
6036 :
6037 :
6038 : /*
6039 : UnaryOperand - returns TRUE if operand is acceptable for
6040 : unary operator: + -. If FALSE
6041 : is returned, an error message will be generated
6042 : and the quad is deleted.
6043 : */
6044 :
6045 918 : static bool UnaryOperand (unsigned int quad, unsigned int operand)
6046 : {
6047 918 : if (! (CheckUnaryOperand (quad, operand)))
6048 : {
6049 6 : M2Quads_SubQuad (quad); /* We do not want multiple copies of the same error. */
6050 6 : return false; /* We do not want multiple copies of the same error. */
6051 : }
6052 : return true;
6053 : /* static analysis guarentees a RETURN statement will be used before here. */
6054 : __builtin_unreachable ();
6055 : }
6056 :
6057 :
6058 : /*
6059 : CheckBinaryOperand - checks to see whether operand is using a generic type.
6060 : */
6061 :
6062 1587180 : static bool CheckBinaryOperand (unsigned int quad, bool isleft, unsigned int operand, bool result)
6063 : {
6064 1587180 : unsigned int type;
6065 1587180 : M2Quads_QuadOperator qop;
6066 1587180 : unsigned int op1;
6067 1587180 : unsigned int op2;
6068 1587180 : unsigned int op3;
6069 1587180 : unsigned int op1pos;
6070 1587180 : unsigned int op2pos;
6071 1587180 : unsigned int op3pos;
6072 1587180 : DynamicStrings_String s;
6073 1587180 : DynamicStrings_String op;
6074 :
6075 1587180 : type = SymbolTable_SkipType (SymbolTable_GetType (operand));
6076 1587180 : if ((((M2System_Word == type) || (M2System_IsWordN (type))) || (M2System_Byte == type)) || (M2System_Loc == type))
6077 : {
6078 18 : M2Quads_GetQuadtok (quad, &qop, &op1, &op2, &op3, &op1pos, &op2pos, &op3pos);
6079 18 : op = M2Quads_GetM2OperatorDesc (M2Quads_GetQuadOp (quad));
6080 18 : if (isleft)
6081 : {
6082 6 : s = DynamicStrings_InitString ((const char *) "left operand {%1Ea} of type {%1Ets} is not allowed in binary expression", 71);
6083 : }
6084 : else
6085 : {
6086 12 : s = DynamicStrings_InitString ((const char *) "right operand {%1Ea} of type {%1Ets} is not allowed in binary expression", 72);
6087 : }
6088 18 : if (op != NULL)
6089 : {
6090 18 : s = DynamicStrings_ConCatChar (s, ' ');
6091 18 : s = DynamicStrings_ConCat (s, DynamicStrings_Mark (op));
6092 : }
6093 18 : M2MetaError_MetaErrorStringT1 (op1pos, s, operand);
6094 18 : return false;
6095 : }
6096 : return result;
6097 : /* static analysis guarentees a RETURN statement will be used before here. */
6098 : __builtin_unreachable ();
6099 : }
6100 :
6101 :
6102 : /*
6103 : BinaryOperands - returns TRUE if, l, and, r, are acceptable for
6104 : binary operator: + - / * and friends. If FALSE
6105 : is returned, an error message will be generated
6106 : and the, quad, is deleted.
6107 : */
6108 :
6109 793590 : static bool BinaryOperands (unsigned int quad, unsigned int l, unsigned int r)
6110 : {
6111 793590 : bool result;
6112 :
6113 793590 : result = CheckBinaryOperand (quad, true, l, true);
6114 793590 : result = CheckBinaryOperand (quad, false, r, result);
6115 793590 : if (! result)
6116 : {
6117 12 : M2Quads_SubQuad (quad); /* We do not want multiple copies of the same error. */
6118 : }
6119 793590 : return result;
6120 : /* static analysis guarentees a RETURN statement will be used before here. */
6121 : __builtin_unreachable ();
6122 : }
6123 :
6124 :
6125 : /*
6126 : IsConstStr - returns TRUE if sym is a constant string or a char constant.
6127 : */
6128 :
6129 447340 : static bool IsConstStr (unsigned int sym)
6130 : {
6131 447340 : return (SymbolTable_IsConstString (sym)) || ((SymbolTable_IsConst (sym)) && ((SymbolTable_GetSType (sym)) == M2Base_Char));
6132 : /* static analysis guarentees a RETURN statement will be used before here. */
6133 : __builtin_unreachable ();
6134 : }
6135 :
6136 :
6137 : /*
6138 : IsConstStrKnown - returns TRUE if sym is a constant string or a char constant
6139 : which is known.
6140 : */
6141 :
6142 45774 : static bool IsConstStrKnown (unsigned int sym)
6143 : {
6144 45774 : return ((SymbolTable_IsConstString (sym)) && (SymbolTable_IsConstStringKnown (sym))) || ((SymbolTable_IsConst (sym)) && ((SymbolTable_GetSType (sym)) == M2Base_Char));
6145 : /* static analysis guarentees a RETURN statement will be used before here. */
6146 : __builtin_unreachable ();
6147 : }
6148 :
6149 :
6150 : /*
6151 : GetStr - return a string containing a constant string value associated with sym.
6152 : A nul char constant will return an empty string.
6153 : */
6154 :
6155 45606 : static DynamicStrings_String GetStr (unsigned int tokenno, unsigned int sym)
6156 : {
6157 45606 : char ch;
6158 :
6159 45606 : M2Debug_Assert (SymbolTable_IsConst (sym));
6160 45606 : if (SymbolTable_IsConstString (sym))
6161 : {
6162 45582 : return DynamicStrings_InitStringCharStar (NameKey_KeyToCharStar (SymbolTable_GetString (sym)));
6163 : }
6164 : else
6165 : {
6166 24 : M2Debug_Assert ((SymbolTable_GetSType (sym)) == M2Base_Char);
6167 24 : SymbolTable_PushValue (sym);
6168 24 : ch = M2ALU_PopChar (tokenno);
6169 24 : return DynamicStrings_InitStringChar (ch);
6170 : }
6171 : /* static analysis guarentees a RETURN statement will be used before here. */
6172 : __builtin_unreachable ();
6173 : }
6174 :
6175 :
6176 : /*
6177 : FoldAdd - check addition for constant folding. It checks for conststrings
6178 : overloading the +.
6179 : */
6180 :
6181 402082 : static void FoldAdd (unsigned int tokenno, M2GCCDeclare_WalkAction p, unsigned int quad, unsigned int op1, unsigned int op2, unsigned int op3)
6182 : {
6183 402082 : DynamicStrings_String s;
6184 :
6185 402082 : if ((IsConstStr (op2)) && (IsConstStr (op3)))
6186 : {
6187 : /* avoid dangling else. */
6188 540 : if ((IsConstStrKnown (op2)) && (IsConstStrKnown (op3)))
6189 : {
6190 : /* Handle special addition for constant strings. */
6191 492 : s = DynamicStrings_Dup (GetStr (tokenno, op2));
6192 492 : s = DynamicStrings_ConCat (s, GetStr (tokenno, op3));
6193 492 : SymbolTable_PutConstStringKnown (tokenno, op1, NameKey_makekey (DynamicStrings_string (s)), false, true);
6194 492 : M2GCCDeclare_TryDeclareConstant (tokenno, op1);
6195 492 : (*p.proc) (op1);
6196 492 : NoChange = false;
6197 492 : M2Quads_SubQuad (quad);
6198 492 : s = DynamicStrings_KillString (s);
6199 : }
6200 : }
6201 : else
6202 : {
6203 401542 : FoldArithAdd (tokenno, p, quad, op1, op2, op3);
6204 : }
6205 402070 : }
6206 :
6207 :
6208 : /*
6209 : FoldArithAdd - check arithmetic addition for constant folding.
6210 : */
6211 :
6212 401542 : static void FoldArithAdd (unsigned int tokenno, M2GCCDeclare_WalkAction p, unsigned int quad, unsigned int op1, unsigned int op2, unsigned int op3)
6213 : {
6214 401542 : if (BinaryOperands (quad, op2, op3))
6215 : {
6216 401530 : FoldBinary (tokenno, p, (m2expr_BuildBinProcedure) {(m2expr_BuildBinProcedure_t) m2expr_BuildAdd}, quad, op1, op2, op3);
6217 : }
6218 401530 : }
6219 :
6220 :
6221 : /*
6222 : CodeAddChecked - code an addition instruction, determine whether checking
6223 : is required.
6224 : */
6225 :
6226 35144 : static void CodeAddChecked (unsigned int quad, unsigned int left, unsigned int right)
6227 : {
6228 35144 : if (M2Quads_MustCheckOverflow (quad))
6229 : {
6230 23890 : CodeAddCheck (quad, left, right);
6231 : }
6232 : else
6233 : {
6234 11254 : CodeAdd (quad, left, right);
6235 : }
6236 35144 : }
6237 :
6238 :
6239 : /*
6240 : CodeAddCheck - encode addition but check for overflow.
6241 : */
6242 :
6243 23890 : static void CodeAddCheck (unsigned int quad, unsigned int left, unsigned int right)
6244 : {
6245 23890 : if (BinaryOperands (quad, left, right))
6246 : {
6247 23890 : CodeBinaryCheck ((m2expr_BuildBinCheckProcedure) {(m2expr_BuildBinCheckProcedure_t) m2expr_BuildAddCheck}, quad);
6248 : }
6249 23890 : }
6250 :
6251 :
6252 : /*
6253 : CodeAdd - encode addition.
6254 : */
6255 :
6256 11254 : static void CodeAdd (unsigned int quad, unsigned int left, unsigned int right)
6257 : {
6258 11254 : if (BinaryOperands (quad, left, right))
6259 : {
6260 11254 : CodeBinary ((m2expr_BuildBinProcedure) {(m2expr_BuildBinProcedure_t) m2expr_BuildAdd}, quad);
6261 : }
6262 11254 : }
6263 :
6264 :
6265 : /*
6266 : FoldSub - check subtraction for constant folding.
6267 : */
6268 :
6269 166952 : static void FoldSub (unsigned int tokenno, M2GCCDeclare_WalkAction p, unsigned int quad, unsigned int op1, unsigned int op2, unsigned int op3)
6270 : {
6271 166952 : if (BinaryOperands (quad, op2, op3))
6272 : {
6273 166952 : FoldBinary (tokenno, p, (m2expr_BuildBinProcedure) {(m2expr_BuildBinProcedure_t) m2expr_BuildSub}, quad, op1, op2, op3);
6274 : }
6275 166952 : }
6276 :
6277 :
6278 : /*
6279 : CodeSubChecked - code a subtract instruction, determine whether checking
6280 : is required.
6281 : */
6282 :
6283 10632 : static void CodeSubChecked (unsigned int quad, unsigned int left, unsigned int right)
6284 : {
6285 10632 : if (M2Quads_MustCheckOverflow (quad))
6286 : {
6287 10632 : CodeSubCheck (quad, left, right);
6288 : }
6289 : else
6290 : {
6291 0 : CodeSub (quad, left, right);
6292 : }
6293 10632 : }
6294 :
6295 :
6296 : /*
6297 : CodeSubCheck - encode subtraction but check for overflow.
6298 : */
6299 :
6300 10632 : static void CodeSubCheck (unsigned int quad, unsigned int left, unsigned int right)
6301 : {
6302 10632 : if (BinaryOperands (quad, left, right))
6303 : {
6304 10632 : CodeBinaryCheck ((m2expr_BuildBinCheckProcedure) {(m2expr_BuildBinCheckProcedure_t) m2expr_BuildSubCheck}, quad);
6305 : }
6306 10632 : }
6307 :
6308 :
6309 : /*
6310 : CodeSub - encode subtraction.
6311 : */
6312 :
6313 0 : static void CodeSub (unsigned int quad, unsigned int left, unsigned int right)
6314 : {
6315 0 : if (BinaryOperands (quad, left, right))
6316 : {
6317 0 : CodeBinary ((m2expr_BuildBinProcedure) {(m2expr_BuildBinProcedure_t) m2expr_BuildSub}, quad);
6318 : }
6319 0 : }
6320 :
6321 :
6322 : /*
6323 : FoldMult - check multiplication for constant folding.
6324 : */
6325 :
6326 110456 : static void FoldMult (unsigned int tokenno, M2GCCDeclare_WalkAction p, unsigned int quad, unsigned int op1, unsigned int op2, unsigned int op3)
6327 : {
6328 110456 : if (BinaryOperands (quad, op2, op3))
6329 : {
6330 110456 : FoldBinary (tokenno, p, (m2expr_BuildBinProcedure) {(m2expr_BuildBinProcedure_t) m2expr_BuildMult}, quad, op1, op2, op3);
6331 : }
6332 110456 : }
6333 :
6334 :
6335 : /*
6336 : CodeMultChecked - code a multiplication instruction, determine whether checking
6337 : is required.
6338 : */
6339 :
6340 11518 : static void CodeMultChecked (unsigned int quad, unsigned int left, unsigned int right)
6341 : {
6342 11518 : if (M2Quads_MustCheckOverflow (quad))
6343 : {
6344 11518 : CodeMultCheck (quad, left, right);
6345 : }
6346 : else
6347 : {
6348 0 : CodeMult (quad, left, right);
6349 : }
6350 11518 : }
6351 :
6352 :
6353 : /*
6354 : CodeMultCheck - encode multiplication but check for overflow.
6355 : */
6356 :
6357 11518 : static void CodeMultCheck (unsigned int quad, unsigned int left, unsigned int right)
6358 : {
6359 11518 : if (BinaryOperands (quad, left, right))
6360 : {
6361 11518 : CodeBinaryCheck ((m2expr_BuildBinCheckProcedure) {(m2expr_BuildBinCheckProcedure_t) m2expr_BuildMultCheck}, quad);
6362 : }
6363 11518 : }
6364 :
6365 :
6366 : /*
6367 : CodeMult - encode multiplication.
6368 : */
6369 :
6370 0 : static void CodeMult (unsigned int quad, unsigned int left, unsigned int right)
6371 : {
6372 0 : if (BinaryOperands (quad, left, right))
6373 : {
6374 0 : CodeBinary ((m2expr_BuildBinProcedure) {(m2expr_BuildBinProcedure_t) m2expr_BuildMult}, quad);
6375 : }
6376 0 : }
6377 :
6378 :
6379 : /*
6380 : CodeDivM2Checked - code a divide instruction, determine whether checking
6381 : is required.
6382 : */
6383 :
6384 1986 : static void CodeDivM2Checked (unsigned int quad, unsigned int left, unsigned int right)
6385 : {
6386 1986 : if (M2Quads_MustCheckOverflow (quad))
6387 : {
6388 1986 : CodeDivM2Check (quad, left, right);
6389 : }
6390 : else
6391 : {
6392 0 : CodeDivM2 (quad, left, right);
6393 : }
6394 1986 : }
6395 :
6396 :
6397 : /*
6398 : CodeDivM2Check - encode addition but check for overflow.
6399 : */
6400 :
6401 1986 : static void CodeDivM2Check (unsigned int quad, unsigned int left, unsigned int right)
6402 : {
6403 1986 : if (BinaryOperands (quad, left, right))
6404 : {
6405 1986 : CodeBinaryCheck ((m2expr_BuildBinCheckProcedure) {(m2expr_BuildBinCheckProcedure_t) m2expr_BuildDivM2Check}, quad);
6406 : }
6407 1986 : }
6408 :
6409 :
6410 : /*
6411 : CodeModM2Checked - code a modulus instruction, determine whether checking
6412 : is required.
6413 : */
6414 :
6415 2124 : static void CodeModM2Checked (unsigned int quad, unsigned int left, unsigned int right)
6416 : {
6417 2124 : if (M2Quads_MustCheckOverflow (quad))
6418 : {
6419 2124 : CodeModM2Check (quad, left, right);
6420 : }
6421 : else
6422 : {
6423 0 : CodeModM2 (quad, left, right);
6424 : }
6425 2124 : }
6426 :
6427 :
6428 : /*
6429 : CodeModM2Check - encode addition but check for overflow.
6430 : */
6431 :
6432 2124 : static void CodeModM2Check (unsigned int quad, unsigned int left, unsigned int right)
6433 : {
6434 2124 : if (BinaryOperands (quad, left, right))
6435 : {
6436 2124 : CodeBinaryCheck ((m2expr_BuildBinCheckProcedure) {(m2expr_BuildBinCheckProcedure_t) m2expr_BuildModM2Check}, quad);
6437 : }
6438 2124 : }
6439 :
6440 :
6441 : /*
6442 : BinaryOperandRealFamily -
6443 : */
6444 :
6445 47906 : static bool BinaryOperandRealFamily (unsigned int op)
6446 : {
6447 47906 : unsigned int type;
6448 :
6449 47906 : type = SymbolTable_GetDType (op);
6450 47906 : return (((M2Base_IsComplexType (type)) || (M2System_IsComplexN (type))) || (M2Base_IsRealType (type))) || (M2System_IsRealN (type));
6451 : /* static analysis guarentees a RETURN statement will be used before here. */
6452 : __builtin_unreachable ();
6453 : }
6454 :
6455 :
6456 : /*
6457 : FoldDivM2 - check division for constant folding.
6458 : */
6459 :
6460 15176 : static void FoldDivM2 (unsigned int tokenno, M2GCCDeclare_WalkAction p, unsigned int quad, unsigned int op1, unsigned int op2, unsigned int op3)
6461 : {
6462 15176 : if (BinaryOperands (quad, op2, op3))
6463 : {
6464 : /* avoid gcc warning by using compound statement even if not strictly necessary. */
6465 15176 : if ((BinaryOperandRealFamily (op2)) || (BinaryOperandRealFamily (op3)))
6466 : {
6467 0 : FoldBinary (tokenno, p, (m2expr_BuildBinProcedure) {(m2expr_BuildBinProcedure_t) m2expr_BuildRDiv}, quad, op1, op2, op3);
6468 : }
6469 : else
6470 : {
6471 15176 : FoldBinary (tokenno, p, (m2expr_BuildBinProcedure) {(m2expr_BuildBinProcedure_t) m2expr_BuildDivM2}, quad, op1, op2, op3);
6472 : }
6473 : }
6474 15176 : }
6475 :
6476 :
6477 : /*
6478 : CodeDivM2 - encode division.
6479 : */
6480 :
6481 0 : static void CodeDivM2 (unsigned int quad, unsigned int left, unsigned int right)
6482 : {
6483 0 : if (BinaryOperands (quad, left, right))
6484 : {
6485 : /* avoid gcc warning by using compound statement even if not strictly necessary. */
6486 0 : if ((BinaryOperandRealFamily (left)) || (BinaryOperandRealFamily (right)))
6487 : {
6488 0 : CodeBinary ((m2expr_BuildBinProcedure) {(m2expr_BuildBinProcedure_t) m2expr_BuildRDiv}, quad);
6489 : }
6490 : else
6491 : {
6492 0 : CodeBinary ((m2expr_BuildBinProcedure) {(m2expr_BuildBinProcedure_t) m2expr_BuildDivM2}, quad);
6493 : }
6494 : }
6495 0 : }
6496 :
6497 :
6498 : /*
6499 : FoldModM2 - check modulus for constant folding.
6500 : */
6501 :
6502 26130 : static void FoldModM2 (unsigned int tokenno, M2GCCDeclare_WalkAction p, unsigned int quad, unsigned int op1, unsigned int op2, unsigned int op3)
6503 : {
6504 26130 : if (BinaryOperands (quad, op2, op3))
6505 : {
6506 26130 : FoldBinary (tokenno, p, (m2expr_BuildBinProcedure) {(m2expr_BuildBinProcedure_t) m2expr_BuildModM2}, quad, op1, op2, op3);
6507 : }
6508 26130 : }
6509 :
6510 :
6511 : /*
6512 : CodeModM2 - encode modulus.
6513 : */
6514 :
6515 0 : static void CodeModM2 (unsigned int quad, unsigned int left, unsigned int right)
6516 : {
6517 0 : if (BinaryOperands (quad, left, right))
6518 : {
6519 0 : CodeBinary ((m2expr_BuildBinProcedure) {(m2expr_BuildBinProcedure_t) m2expr_BuildModM2}, quad);
6520 : }
6521 0 : }
6522 :
6523 :
6524 : /*
6525 : FoldDivTrunc - check division for constant folding.
6526 : */
6527 :
6528 11100 : static void FoldDivTrunc (unsigned int tokenno, M2GCCDeclare_WalkAction p, unsigned int quad, unsigned int op1, unsigned int op2, unsigned int op3)
6529 : {
6530 11100 : if (BinaryOperands (quad, op2, op3))
6531 : {
6532 : /* avoid gcc warning by using compound statement even if not strictly necessary. */
6533 11100 : if ((BinaryOperandRealFamily (op2)) || (BinaryOperandRealFamily (op3)))
6534 : {
6535 5954 : FoldBinary (tokenno, p, (m2expr_BuildBinProcedure) {(m2expr_BuildBinProcedure_t) m2expr_BuildRDiv}, quad, op1, op2, op3);
6536 : }
6537 : else
6538 : {
6539 5146 : FoldBinary (tokenno, p, (m2expr_BuildBinProcedure) {(m2expr_BuildBinProcedure_t) m2expr_BuildDivTrunc}, quad, op1, op2, op3);
6540 : }
6541 : }
6542 11100 : }
6543 :
6544 :
6545 : /*
6546 : CodeDivTrunc - encode multiplication.
6547 : */
6548 :
6549 734 : static void CodeDivTrunc (unsigned int quad, unsigned int left, unsigned int right)
6550 : {
6551 734 : if (BinaryOperands (quad, left, right))
6552 : {
6553 : /* avoid gcc warning by using compound statement even if not strictly necessary. */
6554 734 : if ((BinaryOperandRealFamily (left)) || (BinaryOperandRealFamily (right)))
6555 : {
6556 160 : CodeBinary ((m2expr_BuildBinProcedure) {(m2expr_BuildBinProcedure_t) m2expr_BuildRDiv}, quad);
6557 : }
6558 : else
6559 : {
6560 574 : CodeBinary ((m2expr_BuildBinProcedure) {(m2expr_BuildBinProcedure_t) m2expr_BuildDivTrunc}, quad);
6561 : }
6562 : }
6563 734 : }
6564 :
6565 :
6566 : /*
6567 : FoldModTrunc - check modulus for constant folding.
6568 : */
6569 :
6570 96 : static void FoldModTrunc (unsigned int tokenno, M2GCCDeclare_WalkAction p, unsigned int quad, unsigned int op1, unsigned int op2, unsigned int op3)
6571 : {
6572 96 : if (BinaryOperands (quad, op2, op3))
6573 : {
6574 96 : FoldBinary (tokenno, p, (m2expr_BuildBinProcedure) {(m2expr_BuildBinProcedure_t) m2expr_BuildModTrunc}, quad, op1, op2, op3);
6575 : }
6576 96 : }
6577 :
6578 :
6579 : /*
6580 : CodeModTrunc - encode modulus.
6581 : */
6582 :
6583 0 : static void CodeModTrunc (unsigned int quad, unsigned int left, unsigned int right)
6584 : {
6585 0 : if (BinaryOperands (quad, left, right))
6586 : {
6587 0 : CodeBinary ((m2expr_BuildBinProcedure) {(m2expr_BuildBinProcedure_t) m2expr_BuildModTrunc}, quad);
6588 : }
6589 0 : }
6590 :
6591 :
6592 : /*
6593 : FoldDivCeil - check division for constant folding.
6594 : */
6595 :
6596 0 : static void FoldDivCeil (unsigned int tokenno, M2GCCDeclare_WalkAction p, unsigned int quad, unsigned int op1, unsigned int op2, unsigned int op3)
6597 : {
6598 0 : if (BinaryOperands (quad, op2, op3))
6599 : {
6600 : /* avoid gcc warning by using compound statement even if not strictly necessary. */
6601 0 : if ((BinaryOperandRealFamily (op2)) || (BinaryOperandRealFamily (op3)))
6602 : {
6603 0 : FoldBinary (tokenno, p, (m2expr_BuildBinProcedure) {(m2expr_BuildBinProcedure_t) m2expr_BuildRDiv}, quad, op1, op2, op3);
6604 : }
6605 : else
6606 : {
6607 0 : FoldBinary (tokenno, p, (m2expr_BuildBinProcedure) {(m2expr_BuildBinProcedure_t) m2expr_BuildDivCeil}, quad, op1, op2, op3);
6608 : }
6609 : }
6610 0 : }
6611 :
6612 :
6613 : /*
6614 : CodeDivCeil - encode multiplication.
6615 : */
6616 :
6617 0 : static void CodeDivCeil (unsigned int quad, unsigned int left, unsigned int right)
6618 : {
6619 0 : if (BinaryOperands (quad, left, right))
6620 : {
6621 : /* avoid gcc warning by using compound statement even if not strictly necessary. */
6622 0 : if ((BinaryOperandRealFamily (left)) || (BinaryOperandRealFamily (right)))
6623 : {
6624 0 : CodeBinary ((m2expr_BuildBinProcedure) {(m2expr_BuildBinProcedure_t) m2expr_BuildRDiv}, quad);
6625 : }
6626 : else
6627 : {
6628 0 : CodeBinary ((m2expr_BuildBinProcedure) {(m2expr_BuildBinProcedure_t) m2expr_BuildDivCeil}, quad);
6629 : }
6630 : }
6631 0 : }
6632 :
6633 :
6634 : /*
6635 : FoldModCeil - check modulus for constant folding.
6636 : */
6637 :
6638 0 : static void FoldModCeil (unsigned int tokenno, M2GCCDeclare_WalkAction p, unsigned int quad, unsigned int op1, unsigned int op2, unsigned int op3)
6639 : {
6640 0 : if (BinaryOperands (quad, op2, op3))
6641 : {
6642 0 : FoldBinary (tokenno, p, (m2expr_BuildBinProcedure) {(m2expr_BuildBinProcedure_t) m2expr_BuildModCeil}, quad, op1, op2, op3);
6643 : }
6644 0 : }
6645 :
6646 :
6647 : /*
6648 : CodeModCeil - encode multiplication.
6649 : */
6650 :
6651 0 : static void CodeModCeil (unsigned int quad, unsigned int left, unsigned int right)
6652 : {
6653 0 : if (BinaryOperands (quad, left, right))
6654 : {
6655 0 : CodeBinary ((m2expr_BuildBinProcedure) {(m2expr_BuildBinProcedure_t) m2expr_BuildModCeil}, quad);
6656 : }
6657 0 : }
6658 :
6659 :
6660 : /*
6661 : FoldDivFloor - check division for constant folding.
6662 : */
6663 :
6664 0 : static void FoldDivFloor (unsigned int tokenno, M2GCCDeclare_WalkAction p, unsigned int quad, unsigned int op1, unsigned int op2, unsigned int op3)
6665 : {
6666 0 : if (BinaryOperands (quad, op2, op3))
6667 : {
6668 : /* avoid gcc warning by using compound statement even if not strictly necessary. */
6669 0 : if ((BinaryOperandRealFamily (op2)) || (BinaryOperandRealFamily (op3)))
6670 : {
6671 0 : FoldBinary (tokenno, p, (m2expr_BuildBinProcedure) {(m2expr_BuildBinProcedure_t) m2expr_BuildRDiv}, quad, op1, op2, op3);
6672 : }
6673 : else
6674 : {
6675 0 : FoldBinary (tokenno, p, (m2expr_BuildBinProcedure) {(m2expr_BuildBinProcedure_t) m2expr_BuildDivFloor}, quad, op1, op2, op3);
6676 : }
6677 : }
6678 0 : }
6679 :
6680 :
6681 : /*
6682 : CodeDivFloor - encode multiplication.
6683 : */
6684 :
6685 0 : static void CodeDivFloor (unsigned int quad, unsigned int left, unsigned int right)
6686 : {
6687 0 : if (BinaryOperands (quad, left, right))
6688 : {
6689 : /* avoid gcc warning by using compound statement even if not strictly necessary. */
6690 0 : if ((BinaryOperandRealFamily (left)) || (BinaryOperandRealFamily (right)))
6691 : {
6692 0 : CodeBinary ((m2expr_BuildBinProcedure) {(m2expr_BuildBinProcedure_t) m2expr_BuildRDiv}, quad);
6693 : }
6694 : else
6695 : {
6696 0 : CodeBinary ((m2expr_BuildBinProcedure) {(m2expr_BuildBinProcedure_t) m2expr_BuildDivFloor}, quad);
6697 : }
6698 : }
6699 0 : }
6700 :
6701 :
6702 : /*
6703 : FoldModFloor - check modulus for constant folding.
6704 : */
6705 :
6706 0 : static void FoldModFloor (unsigned int tokenno, M2GCCDeclare_WalkAction p, unsigned int quad, unsigned int op1, unsigned int op2, unsigned int op3)
6707 : {
6708 0 : if (BinaryOperands (quad, op2, op3))
6709 : {
6710 0 : FoldBinary (tokenno, p, (m2expr_BuildBinProcedure) {(m2expr_BuildBinProcedure_t) m2expr_BuildModFloor}, quad, op1, op2, op3);
6711 : }
6712 0 : }
6713 :
6714 :
6715 : /*
6716 : CodeModFloor - encode modulus.
6717 : */
6718 :
6719 0 : static void CodeModFloor (unsigned int quad, unsigned int left, unsigned int right)
6720 : {
6721 0 : if (BinaryOperands (quad, left, right))
6722 : {
6723 0 : CodeBinary ((m2expr_BuildBinProcedure) {(m2expr_BuildBinProcedure_t) m2expr_BuildModFloor}, quad);
6724 : }
6725 0 : }
6726 :
6727 :
6728 : /*
6729 : FoldBuiltinConst -
6730 : */
6731 :
6732 28900 : static void FoldBuiltinConst (unsigned int tokenno, M2GCCDeclare_WalkAction p, unsigned int quad, unsigned int result, unsigned int constDesc)
6733 : {
6734 28900 : tree value;
6735 :
6736 28900 : value = m2builtins_GetBuiltinConst (reinterpret_cast <char * > (NameKey_KeyToCharStar ((NameKey_Name) (constDesc))));
6737 28900 : if (value == NULL)
6738 : {
6739 0 : M2MetaError_MetaErrorT1 (tokenno, (const char *) "unknown built in constant {%1Ead}", 33, constDesc);
6740 : }
6741 : else
6742 : {
6743 28900 : SymbolConversion_AddModGcc (result, value);
6744 28900 : (*p.proc) (result);
6745 28900 : NoChange = false;
6746 28900 : M2Quads_SubQuad (quad);
6747 : }
6748 28900 : }
6749 :
6750 :
6751 : /*
6752 : FoldBuiltinTypeInfo - attempts to fold a builtin attribute value on type op2.
6753 : */
6754 :
6755 360 : static void FoldBuiltinTypeInfo (unsigned int tokenno, M2GCCDeclare_WalkAction p, unsigned int quad, unsigned int op1, unsigned int op2, unsigned int op3)
6756 : {
6757 360 : tree t;
6758 360 : location_t location;
6759 :
6760 360 : if ((SymbolConversion_GccKnowsAbout (op2)) && (M2GCCDeclare_CompletelyResolved (op2)))
6761 : {
6762 360 : location = M2LexBuf_TokenToLocation (tokenno);
6763 360 : t = m2builtins_GetBuiltinTypeInfo (location, SymbolConversion_Mod2Gcc (op2), const_cast <const char * > (static_cast <char * > (NameKey_KeyToCharStar ((NameKey_Name) (op3)))));
6764 360 : if (t == NULL)
6765 : {
6766 0 : M2MetaError_MetaErrorT2 (tokenno, (const char *) "unknown built in constant {%1Ead} attribute for type {%2ad}", 59, op3, op2);
6767 : }
6768 : else
6769 : {
6770 360 : SymbolConversion_AddModGcc (op1, t);
6771 360 : (*p.proc) (op1);
6772 360 : NoChange = false;
6773 360 : M2Quads_SubQuad (quad);
6774 : }
6775 : }
6776 360 : }
6777 :
6778 :
6779 : /*
6780 : FoldTBitsize - attempt to fold the standard function SYSTEM.TBITSIZE
6781 : quadruple. If the quadruple is folded it is removed.
6782 : */
6783 :
6784 6508 : static void FoldTBitsize (unsigned int tokenno, M2GCCDeclare_WalkAction p, unsigned int quad, unsigned int res, unsigned int type)
6785 : {
6786 6508 : location_t location;
6787 :
6788 6508 : location = M2LexBuf_TokenToLocation (tokenno);
6789 6508 : if (((SymbolTable_IsType (type)) || (SymbolTable_IsVar (type))) || (SymbolTable_IsConst (type)))
6790 : {
6791 6368 : if ((SymbolTable_GetDType (type)) == SymbolTable_NulSym)
6792 : {
6793 0 : M2MetaError_MetaErrorT1 (tokenno, (const char *) "unknown type in TBITSIZE parameter {%1Ead}", 42, type);
6794 0 : NoChange = false;
6795 0 : M2Quads_SubQuad (quad);
6796 : }
6797 6368 : type = SymbolTable_GetDType (type);
6798 : }
6799 6508 : if (type != SymbolTable_NulSym)
6800 : {
6801 6508 : M2GCCDeclare_TryDeclareType (type);
6802 6508 : if (M2GCCDeclare_CompletelyResolved (type))
6803 : {
6804 6496 : SymbolConversion_AddModGcc (res, m2expr_BuildSystemTBitSize (location, SymbolConversion_Mod2Gcc (type)));
6805 6496 : (*p.proc) (res);
6806 6496 : NoChange = false;
6807 6496 : M2Quads_SubQuad (quad);
6808 : }
6809 : }
6810 6508 : }
6811 :
6812 :
6813 : /*
6814 : FoldStandardFunction - attempts to fold a standard function.
6815 : */
6816 :
6817 9564 : static void FoldStandardFunction (unsigned int tokenno, M2GCCDeclare_WalkAction p, unsigned int quad, unsigned int op1, unsigned int op2, unsigned int op3)
6818 : {
6819 9564 : DynamicStrings_String s;
6820 9564 : unsigned int type;
6821 9564 : unsigned int d;
6822 9564 : unsigned int result;
6823 9564 : location_t location;
6824 :
6825 9564 : location = M2LexBuf_TokenToLocation (tokenno);
6826 9564 : if ((SymbolTable_GetSymName (op2)) == (NameKey_MakeKey ((const char *) "Length", 6)))
6827 : {
6828 : /* avoid dangling else. */
6829 0 : M2GCCDeclare_TryDeclareConstant (tokenno, op3);
6830 0 : if ((SymbolTable_IsConst (op3)) && (SymbolConversion_GccKnowsAbout (op3)))
6831 : {
6832 : /* avoid gcc warning by using compound statement even if not strictly necessary. */
6833 : /* fine, we can take advantage of this and fold constants */
6834 0 : if (SymbolTable_IsConst (op1))
6835 : {
6836 0 : if (SymbolTable_IsConstString (op3))
6837 : {
6838 0 : SymbolConversion_AddModGcc (op1, FindSize (tokenno, op3));
6839 0 : (*p.proc) (op1);
6840 0 : NoChange = false;
6841 0 : M2Quads_SubQuad (quad);
6842 : }
6843 : else
6844 : {
6845 0 : M2MetaError_MetaErrorT1 (tokenno, (const char *) "parameter to LENGTH must be a string {%1Ead}", 44, op3);
6846 : }
6847 : }
6848 : else
6849 : {
6850 : /* rewrite the quad to use becomes. */
6851 0 : d = SymbolTable_GetStringLength (tokenno, op3);
6852 0 : s = FormatStrings_Sprintf1 (DynamicStrings_Mark (DynamicStrings_InitString ((const char *) "%d", 2)), (const unsigned char *) &d, (sizeof (d)-1));
6853 0 : result = SymbolTable_MakeConstLit (tokenno, NameKey_makekey (DynamicStrings_string (s)), M2Base_Cardinal);
6854 0 : s = DynamicStrings_KillString (s);
6855 0 : M2GCCDeclare_TryDeclareConstant (tokenno, result);
6856 0 : M2Quads_PutQuad (quad, M2Quads_BecomesOp, op1, SymbolTable_NulSym, result);
6857 : }
6858 : }
6859 : }
6860 9564 : else if ((SymbolTable_GetSymName (op2)) == (NameKey_MakeKey ((const char *) "CAP", 3)))
6861 : {
6862 : /* avoid dangling else. */
6863 766 : M2GCCDeclare_TryDeclareConstant (tokenno, op3);
6864 766 : if ((SymbolTable_IsConst (op3)) && (SymbolConversion_GccKnowsAbout (op3)))
6865 : {
6866 : /* fine, we can take advantage of this and fold constants */
6867 24 : if (SymbolTable_IsConst (op1))
6868 : {
6869 : /* avoid gcc warning by using compound statement even if not strictly necessary. */
6870 24 : if (((SymbolTable_IsConstString (op3)) && ((SymbolTable_GetStringLength (tokenno, op3)) == 1)) || ((SymbolTable_GetType (op3)) == M2Base_Char))
6871 : {
6872 24 : SymbolConversion_AddModGcc (op1, m2expr_BuildCap (location, SymbolConversion_Mod2Gcc (op3)));
6873 24 : (*p.proc) (op1);
6874 24 : NoChange = false;
6875 24 : M2Quads_SubQuad (quad);
6876 : }
6877 : else
6878 : {
6879 0 : M2MetaError_MetaErrorT1 (tokenno, (const char *) "parameter to CAP must be a single character {%1Ead}", 51, op3);
6880 : }
6881 : }
6882 : }
6883 : }
6884 8798 : else if ((SymbolTable_GetSymName (op2)) == (NameKey_MakeKey ((const char *) "ABS", 3)))
6885 : {
6886 : /* avoid dangling else. */
6887 796 : M2GCCDeclare_TryDeclareConstant (tokenno, op3);
6888 796 : if ((SymbolTable_IsConst (op3)) && (SymbolConversion_GccKnowsAbout (op3)))
6889 : {
6890 : /* fine, we can take advantage of this and fold constants */
6891 12 : if (SymbolTable_IsConst (op1))
6892 : {
6893 12 : SymbolConversion_AddModGcc (op1, m2expr_BuildAbs (location, SymbolConversion_Mod2Gcc (op3)));
6894 12 : (*p.proc) (op1);
6895 12 : NoChange = false;
6896 12 : M2Quads_SubQuad (quad);
6897 : }
6898 : }
6899 : }
6900 8002 : else if (op2 == M2Base_Im)
6901 : {
6902 : /* avoid dangling else. */
6903 90 : M2GCCDeclare_TryDeclareConstant (tokenno, op3);
6904 90 : if ((SymbolTable_IsConst (op3)) && (SymbolConversion_GccKnowsAbout (op3)))
6905 : {
6906 : /* fine, we can take advantage of this and fold constants */
6907 36 : if (SymbolTable_IsConst (op1))
6908 : {
6909 36 : SymbolConversion_AddModGcc (op1, m2expr_BuildIm (SymbolConversion_Mod2Gcc (op3)));
6910 36 : (*p.proc) (op1);
6911 36 : NoChange = false;
6912 36 : M2Quads_SubQuad (quad);
6913 : }
6914 : }
6915 : }
6916 7912 : else if (op2 == M2Base_Re)
6917 : {
6918 : /* avoid dangling else. */
6919 90 : M2GCCDeclare_TryDeclareConstant (tokenno, op3);
6920 90 : if ((SymbolTable_IsConst (op3)) && (SymbolConversion_GccKnowsAbout (op3)))
6921 : {
6922 : /* fine, we can take advantage of this and fold constants */
6923 36 : if (SymbolTable_IsConst (op1))
6924 : {
6925 36 : SymbolConversion_AddModGcc (op1, m2expr_BuildRe (SymbolConversion_Mod2Gcc (op3)));
6926 36 : (*p.proc) (op1);
6927 36 : NoChange = false;
6928 36 : M2Quads_SubQuad (quad);
6929 : }
6930 : }
6931 : }
6932 7822 : else if (op2 == M2Base_Cmplx)
6933 : {
6934 : /* avoid dangling else. */
6935 1314 : M2GCCDeclare_TryDeclareConstant (tokenno, SymbolTable_GetNth (op3, 1));
6936 1314 : M2GCCDeclare_TryDeclareConstant (tokenno, SymbolTable_GetNth (op3, 2));
6937 1314 : if ((((SymbolTable_IsConst (SymbolTable_GetNth (op3, 1))) && (SymbolConversion_GccKnowsAbout (SymbolTable_GetNth (op3, 1)))) && (SymbolTable_IsConst (SymbolTable_GetNth (op3, 2)))) && (SymbolConversion_GccKnowsAbout (SymbolTable_GetNth (op3, 2))))
6938 : {
6939 : /* fine, we can take advantage of this and fold constants */
6940 414 : if (SymbolTable_IsConst (op1))
6941 : {
6942 414 : type = M2Base_GetCmplxReturnType (SymbolTable_GetType (SymbolTable_GetNth (op3, 1)), SymbolTable_GetType (SymbolTable_GetNth (op3, 2)));
6943 414 : if (type == SymbolTable_NulSym)
6944 : {
6945 0 : M2MetaError_MetaErrorT2 (tokenno, (const char *) "real {%1Eatd} and imaginary {%2atd} types are incompatible", 58, SymbolTable_GetNth (op3, 1), SymbolTable_GetNth (op3, 2));
6946 : }
6947 : else
6948 : {
6949 414 : SymbolConversion_AddModGcc (op1, m2expr_BuildCmplx (location, SymbolConversion_Mod2Gcc (type), SymbolConversion_Mod2Gcc (SymbolTable_GetNth (op3, 1)), SymbolConversion_Mod2Gcc (SymbolTable_GetNth (op3, 2))));
6950 414 : (*p.proc) (op1);
6951 414 : NoChange = false;
6952 414 : M2Quads_SubQuad (quad);
6953 : }
6954 : }
6955 : }
6956 : }
6957 6508 : else if (op2 == M2System_TBitSize)
6958 : {
6959 : /* avoid dangling else. */
6960 6508 : FoldTBitsize (tokenno, p, quad, op1, op3);
6961 : }
6962 : else
6963 : {
6964 : /* avoid dangling else. */
6965 0 : M2Error_InternalError ((const char *) "only expecting LENGTH, CAP, ABS, IM, RE", 39);
6966 : }
6967 9564 : }
6968 :
6969 :
6970 : /*
6971 : CodeStandardFunction -
6972 : */
6973 :
6974 330 : static void CodeStandardFunction (unsigned int quad, unsigned int result, unsigned int function, unsigned int param)
6975 : {
6976 330 : unsigned int type;
6977 330 : location_t location;
6978 :
6979 330 : M2GCCDeclare_DeclareConstant (CurrentQuadToken, param);
6980 330 : M2GCCDeclare_DeclareConstructor (CurrentQuadToken, quad, param);
6981 330 : location = M2LexBuf_TokenToLocation (CurrentQuadToken);
6982 330 : if ((function != SymbolTable_NulSym) && ((SymbolTable_GetSymName (function)) == (NameKey_MakeKey ((const char *) "Length", 6))))
6983 : {
6984 : /* avoid dangling else. */
6985 0 : if (SymbolTable_IsConst (result))
6986 : {
6987 0 : M2Error_InternalError ((const char *) "LENGTH function should already have been folded", 47);
6988 : }
6989 : }
6990 330 : else if ((function != SymbolTable_NulSym) && ((SymbolTable_GetSymName (function)) == (NameKey_MakeKey ((const char *) "CAP", 3))))
6991 : {
6992 : /* avoid dangling else. */
6993 82 : if (SymbolTable_IsConst (result))
6994 : {
6995 0 : M2Error_InternalError ((const char *) "CAP function should already have been folded", 44);
6996 : }
6997 : else
6998 : {
6999 82 : m2statement_BuildAssignmentStatement (location, SymbolConversion_Mod2Gcc (result), m2expr_BuildCap (location, SymbolConversion_Mod2Gcc (param)));
7000 : }
7001 : }
7002 248 : else if ((function != SymbolTable_NulSym) && ((SymbolTable_GetSymName (function)) == (NameKey_MakeKey ((const char *) "ABS", 3))))
7003 : {
7004 : /* avoid dangling else. */
7005 140 : if (SymbolTable_IsConst (result))
7006 : {
7007 0 : M2Error_InternalError ((const char *) "ABS function should already have been folded", 44);
7008 : }
7009 : else
7010 : {
7011 140 : m2statement_BuildAssignmentStatement (location, SymbolConversion_Mod2Gcc (result), m2expr_BuildAbs (location, SymbolConversion_Mod2Gcc (param)));
7012 : }
7013 : }
7014 108 : else if (function == M2Base_Im)
7015 : {
7016 : /* avoid dangling else. */
7017 18 : if (SymbolTable_IsConst (result))
7018 : {
7019 0 : M2Error_InternalError ((const char *) "IM function should already have been folded", 43);
7020 : }
7021 : else
7022 : {
7023 18 : m2statement_BuildAssignmentStatement (location, SymbolConversion_Mod2Gcc (result), m2expr_BuildIm (SymbolConversion_Mod2Gcc (param)));
7024 : }
7025 : }
7026 90 : else if (function == M2Base_Re)
7027 : {
7028 : /* avoid dangling else. */
7029 18 : if (SymbolTable_IsConst (result))
7030 : {
7031 0 : M2Error_InternalError ((const char *) "RE function should already have been folded", 43);
7032 : }
7033 : else
7034 : {
7035 18 : m2statement_BuildAssignmentStatement (location, SymbolConversion_Mod2Gcc (result), m2expr_BuildRe (SymbolConversion_Mod2Gcc (param)));
7036 : }
7037 : }
7038 72 : else if (function == M2Base_Cmplx)
7039 : {
7040 : /* avoid dangling else. */
7041 72 : if (SymbolTable_IsConst (result))
7042 : {
7043 0 : M2Error_InternalError ((const char *) "CMPLX function should already have been folded", 46);
7044 : }
7045 : else
7046 : {
7047 72 : type = M2Base_GetCmplxReturnType (SymbolTable_GetType (SymbolTable_GetNth (param, 1)), SymbolTable_GetType (SymbolTable_GetNth (param, 2)));
7048 72 : if (type == SymbolTable_NulSym)
7049 : {
7050 0 : M2MetaError_MetaErrorT2 (CurrentQuadToken, (const char *) "real {%1Eatd} and imaginary {%2atd} types are incompatible", 58, SymbolTable_GetNth (param, 1), SymbolTable_GetNth (param, 2));
7051 : }
7052 : else
7053 : {
7054 72 : m2statement_BuildAssignmentStatement (location, SymbolConversion_Mod2Gcc (result), m2expr_BuildCmplx (location, SymbolConversion_Mod2Gcc (type), SymbolConversion_Mod2Gcc (SymbolTable_GetNth (param, 1)), SymbolConversion_Mod2Gcc (SymbolTable_GetNth (param, 2))));
7055 : }
7056 : }
7057 : }
7058 0 : else if (function == M2System_TBitSize)
7059 : {
7060 : /* avoid dangling else. */
7061 0 : if (SymbolTable_IsConst (result))
7062 : {
7063 0 : M2Error_InternalError ((const char *) "TBITSIZE function should already have been folded", 49);
7064 : }
7065 : else
7066 : {
7067 0 : m2statement_BuildAssignmentStatement (location, SymbolConversion_Mod2Gcc (result), m2expr_BuildTBitSize (location, SymbolConversion_Mod2Gcc (param)));
7068 : }
7069 : }
7070 : else
7071 : {
7072 : /* avoid dangling else. */
7073 0 : M2Error_InternalError ((const char *) "expecting LENGTH, CAP, ABS, IM", 30);
7074 : }
7075 330 : }
7076 :
7077 :
7078 : /*
7079 : CodeSavePriority - checks to see whether op2 is reachable and is directly accessible
7080 : externally. If so then it saves the current interrupt priority
7081 : in op1 and sets the current priority to that determined by
7082 : appropriate module.
7083 :
7084 : op1 := op3(GetModuleScope(op2))
7085 : */
7086 :
7087 420 : static void CodeSavePriority (unsigned int oldValue, unsigned int scopeSym, unsigned int procedureSym)
7088 : {
7089 420 : tree funcTree;
7090 420 : unsigned int mod;
7091 420 : NameKey_Name n;
7092 420 : location_t location;
7093 :
7094 420 : location = M2LexBuf_TokenToLocation (CurrentQuadToken);
7095 420 : if (((SymbolTable_IsModule (scopeSym)) || (SymbolTable_IsDefImp (scopeSym))) || ((SymbolTable_IsProcedure (scopeSym)) && (SymbolTable_GetNeedSavePriority (scopeSym))))
7096 : {
7097 206 : if (SymbolTable_IsProcedure (scopeSym))
7098 : {
7099 130 : mod = SymbolTable_GetModuleScope (scopeSym);
7100 : }
7101 : else
7102 : {
7103 76 : M2Debug_Assert ((SymbolTable_IsModule (scopeSym)) || (SymbolTable_IsDefImp (scopeSym)));
7104 76 : mod = scopeSym;
7105 : }
7106 206 : if ((SymbolTable_GetPriority (mod)) != SymbolTable_NulSym)
7107 : {
7108 206 : if (PriorityDebugging)
7109 : {
7110 : n = SymbolTable_GetSymName (scopeSym);
7111 : M2Printf_printf1 ((const char *) "procedure <%a> needs to save interrupts\\n", 41, (const unsigned char *) &n, (sizeof (n)-1));
7112 : }
7113 206 : M2GCCDeclare_DeclareConstant (CurrentQuadToken, SymbolTable_GetPriority (mod));
7114 206 : m2statement_BuildParam (location, SymbolConversion_Mod2Gcc (SymbolTable_GetPriority (mod)));
7115 206 : funcTree = m2statement_BuildProcedureCallTree (location, SymbolConversion_Mod2Gcc (procedureSym), SymbolConversion_Mod2Gcc (SymbolTable_GetType (procedureSym)));
7116 206 : funcTree = m2statement_BuildFunctValue (location, SymbolConversion_Mod2Gcc (oldValue));
7117 206 : m2type_AddStatement (location, funcTree);
7118 : }
7119 : }
7120 420 : }
7121 :
7122 :
7123 : /*
7124 : CodeRestorePriority - checks to see whether op2 is reachable and is directly accessible
7125 : externally. If so then it restores the previous interrupt priority
7126 : held in op1.
7127 :
7128 : op1 := op3(op1)
7129 : */
7130 :
7131 412 : static void CodeRestorePriority (unsigned int oldValue, unsigned int scopeSym, unsigned int procedureSym)
7132 : {
7133 412 : tree funcTree;
7134 412 : unsigned int mod;
7135 412 : NameKey_Name n;
7136 412 : location_t location;
7137 :
7138 412 : location = M2LexBuf_TokenToLocation (CurrentQuadToken);
7139 412 : if (((SymbolTable_IsModule (scopeSym)) || (SymbolTable_IsDefImp (scopeSym))) || ((SymbolTable_IsProcedure (scopeSym)) && (SymbolTable_GetNeedSavePriority (scopeSym))))
7140 : {
7141 198 : if (SymbolTable_IsProcedure (scopeSym))
7142 : {
7143 122 : mod = SymbolTable_GetModuleScope (scopeSym);
7144 : }
7145 : else
7146 : {
7147 76 : M2Debug_Assert ((SymbolTable_IsModule (scopeSym)) || (SymbolTable_IsDefImp (scopeSym)));
7148 76 : mod = scopeSym;
7149 : }
7150 198 : if ((SymbolTable_GetPriority (mod)) != SymbolTable_NulSym)
7151 : {
7152 198 : if (PriorityDebugging)
7153 : {
7154 : n = SymbolTable_GetSymName (scopeSym);
7155 : M2Printf_printf1 ((const char *) "procedure <%a> needs to restore interrupts\\n", 44, (const unsigned char *) &n, (sizeof (n)-1));
7156 : }
7157 198 : m2statement_BuildParam (location, SymbolConversion_Mod2Gcc (oldValue));
7158 198 : funcTree = m2statement_BuildProcedureCallTree (location, SymbolConversion_Mod2Gcc (procedureSym), SymbolConversion_Mod2Gcc (SymbolTable_GetType (procedureSym)));
7159 198 : funcTree = m2statement_BuildFunctValue (location, SymbolConversion_Mod2Gcc (oldValue));
7160 198 : m2type_AddStatement (location, funcTree);
7161 : }
7162 : }
7163 412 : }
7164 :
7165 :
7166 : /*
7167 : FoldBinarySet - attempts to fold set arithmetic it removes the quad if successful.
7168 : */
7169 :
7170 70812 : static void FoldBinarySet (unsigned int tokenno, M2GCCDeclare_WalkAction p, M2GenGCC_ProcedureCardinal op, unsigned int quad, unsigned int op1, unsigned int op2, unsigned int op3)
7171 : {
7172 70812 : location_t location;
7173 :
7174 : /* firstly try and ensure that constants are declared */
7175 70812 : M2GCCDeclare_TryDeclareConstant (tokenno, op2);
7176 70812 : M2GCCDeclare_TryDeclareConstant (tokenno, op3);
7177 70812 : location = M2LexBuf_TokenToLocation (tokenno);
7178 70812 : if ((SymbolConversion_GccKnowsAbout (op2)) && (SymbolConversion_GccKnowsAbout (op3)))
7179 : {
7180 4444 : if (CheckBinaryExpressionTypes (quad, p))
7181 : {
7182 4444 : if (((((SymbolTable_IsConst (op2)) && (SymbolTable_IsConstSet (op2))) && (SymbolTable_IsConst (op3))) && (SymbolTable_IsConstSet (op3))) && (SymbolTable_IsConst (op1)))
7183 : {
7184 224 : if ((SymbolTable_IsValueSolved (op2)) && (SymbolTable_IsValueSolved (op3)))
7185 : {
7186 224 : M2Debug_Assert ((M2Base_MixTypes (FindType (op3), FindType (op2), tokenno)) != SymbolTable_NulSym);
7187 224 : SymbolTable_PutConst (op1, M2Base_MixTypes (FindType (op3), FindType (op2), tokenno));
7188 224 : SymbolTable_PushValue (op2);
7189 224 : SymbolTable_PushValue (op3);
7190 224 : (*op.proc) (tokenno);
7191 224 : SymbolTable_PopValue (op1);
7192 224 : SymbolTable_PushValue (op1);
7193 224 : SymbolTable_PutConstSet (op1);
7194 224 : SymbolConversion_AddModGcc (op1, m2decl_DeclareKnownConstant (location, SymbolConversion_Mod2Gcc (SymbolTable_GetType (op3)), M2ALU_PopSetTree (tokenno)));
7195 224 : (*p.proc) (op1);
7196 224 : NoChange = false;
7197 224 : M2Quads_SubQuad (quad);
7198 : }
7199 : }
7200 : }
7201 : }
7202 70812 : }
7203 :
7204 :
7205 : /*
7206 : FoldSetOr - check whether we can fold a set arithmetic or.
7207 : */
7208 :
7209 14918 : static void FoldSetOr (unsigned int tokenno, M2GCCDeclare_WalkAction p, unsigned int quad, unsigned int op1, unsigned int op2, unsigned int op3)
7210 : {
7211 0 : FoldBinarySet (tokenno, p, (M2GenGCC_ProcedureCardinal) {(M2GenGCC_ProcedureCardinal_t) M2ALU_SetOr}, quad, op1, op2, op3);
7212 0 : }
7213 :
7214 :
7215 : /*
7216 : CodeSetOr - encode set arithmetic or.
7217 : */
7218 :
7219 754 : static void CodeSetOr (unsigned int quad)
7220 : {
7221 754 : CodeBinarySet ((M2GenGCC_ProcedureCardinal) {(M2GenGCC_ProcedureCardinal_t) M2ALU_SetOr}, (M2GenGCC_BinaryFunction) {(M2GenGCC_BinaryFunction_t) m2expr_BuildLogicalOr}, NameKey_MakeKey ((const char *) "Or", 2), quad);
7222 754 : }
7223 :
7224 :
7225 : /*
7226 : FoldSetAnd - check whether we can fold a logical and.
7227 : */
7228 :
7229 3684 : static void FoldSetAnd (unsigned int tokenno, M2GCCDeclare_WalkAction p, unsigned int quad, unsigned int op1, unsigned int op2, unsigned int op3)
7230 : {
7231 0 : FoldBinarySet (tokenno, p, (M2GenGCC_ProcedureCardinal) {(M2GenGCC_ProcedureCardinal_t) M2ALU_SetAnd}, quad, op1, op2, op3);
7232 0 : }
7233 :
7234 :
7235 : /*
7236 : CodeSetAnd - encode set arithmetic and.
7237 : */
7238 :
7239 284 : static void CodeSetAnd (unsigned int quad)
7240 : {
7241 284 : CodeBinarySet ((M2GenGCC_ProcedureCardinal) {(M2GenGCC_ProcedureCardinal_t) M2ALU_SetAnd}, (M2GenGCC_BinaryFunction) {(M2GenGCC_BinaryFunction_t) m2expr_BuildLogicalAnd}, NameKey_MakeKey ((const char *) "And", 3), quad);
7242 284 : }
7243 :
7244 :
7245 : /*
7246 : CalcHighSetBit - calculate the most significant bit used in a set starting from bit zero.
7247 : */
7248 :
7249 4354 : static tree CalcHighSetBit (location_t location, unsigned int settype)
7250 : {
7251 4354 : SymbolTable_PushValue (M2GCCDeclare_GetTypeMax (SymbolTable_SkipType (SymbolTable_GetType (settype))));
7252 4354 : M2ALU_PushIntegerTree (m2convert_BuildConvert (location, m2type_GetM2ZType (), M2ALU_PopIntegerTree (), false));
7253 4354 : SymbolTable_PushValue (M2GCCDeclare_GetTypeMin (SymbolTable_SkipType (SymbolTable_GetType (settype))));
7254 4354 : M2ALU_PushIntegerTree (m2convert_BuildConvert (location, m2type_GetM2ZType (), M2ALU_PopIntegerTree (), false));
7255 4354 : M2ALU_Sub ();
7256 4354 : return M2ALU_PopIntegerTree ();
7257 : /* static analysis guarentees a RETURN statement will be used before here. */
7258 : __builtin_unreachable ();
7259 : }
7260 :
7261 :
7262 : /*
7263 : CalcBitsInSet - returns the number of minimum number of bits used to represent a set.
7264 : */
7265 :
7266 3352 : static tree CalcBitsInSet (location_t location, unsigned int settype)
7267 : {
7268 3352 : M2ALU_PushIntegerTree (m2convert_BuildConvert (location, m2type_GetM2ZType (), CalcHighSetBit (location, settype), false));
7269 3352 : M2ALU_PushCard (1);
7270 3352 : M2ALU_PushIntegerTree (m2convert_BuildConvert (location, m2type_GetM2ZType (), M2ALU_PopIntegerTree (), false));
7271 3352 : M2ALU_Addn ();
7272 3352 : return M2ALU_PopIntegerTree ();
7273 : /* static analysis guarentees a RETURN statement will be used before here. */
7274 : __builtin_unreachable ();
7275 : }
7276 :
7277 :
7278 : /*
7279 : SetWideSetShiftRotate - generate a call:
7280 : M2WIDESET.name (dest, src, HIGHBIT (settype), count).
7281 : */
7282 :
7283 336 : static void SetWideSetShiftRotate (unsigned int tokenno, NameKey_Name name, unsigned int settype, unsigned int dest, unsigned int src, unsigned int count)
7284 : {
7285 336 : unsigned int procedure;
7286 336 : unsigned int param1;
7287 336 : unsigned int param2;
7288 336 : tree array1;
7289 336 : tree array2;
7290 336 : tree call;
7291 336 : tree highbit;
7292 336 : location_t location;
7293 :
7294 336 : procedure = FromM2WIDESETImport (tokenno, name);
7295 336 : location = M2LexBuf_TokenToLocation (tokenno);
7296 336 : param1 = SymbolTable_GetNthParamAnyClosest (procedure, 1, SymbolTable_GetMainModule ());
7297 336 : param2 = SymbolTable_GetNthParamAnyClosest (procedure, 2, SymbolTable_GetMainModule ());
7298 336 : array1 = CreateSetArrayParam (location, tokenno, dest, param1);
7299 336 : array2 = CreateSetArrayParam (location, tokenno, src, param2);
7300 336 : highbit = CalcHighSetBit (location, settype);
7301 336 : m2statement_BuildParam (location, m2convert_ToCardinal (location, SymbolConversion_Mod2Gcc (count))); /* Parameter 4. */
7302 336 : m2statement_BuildParam (location, m2convert_ToCardinal (location, highbit)); /* Parameter 3. */
7303 336 : m2statement_BuildParam (location, array2); /* Parameter 2. */
7304 336 : m2statement_BuildParam (location, array1); /* Parameter 1. */
7305 336 : call = m2statement_BuildProcedureCallTree (location, SymbolConversion_Mod2Gcc (procedure), NULL); /* Parameter 1. */
7306 336 : m2statement_SetLastFunction (NULL);
7307 336 : m2type_AddStatement (location, call);
7308 336 : }
7309 :
7310 :
7311 : /*
7312 : CodeNarrowSetShift -
7313 : */
7314 :
7315 472 : static void CodeNarrowSetShift (unsigned int tokenno, unsigned int settype, unsigned int dest, unsigned int src, unsigned int count)
7316 : {
7317 472 : location_t location;
7318 472 : tree nbits;
7319 :
7320 472 : location = M2LexBuf_TokenToLocation (tokenno);
7321 472 : nbits = CalcBitsInSet (location, settype);
7322 472 : m2expr_BuildLogicalShift (location, SymbolConversion_Mod2Gcc (dest), SymbolConversion_Mod2Gcc (src), SymbolConversion_Mod2Gcc (count), nbits, false);
7323 472 : }
7324 :
7325 :
7326 : /*
7327 : CodeNarrowSetRotate -
7328 : */
7329 :
7330 274 : static void CodeNarrowSetRotate (unsigned int tokenno, unsigned int settype, unsigned int dest, unsigned int src, unsigned int count)
7331 : {
7332 274 : location_t location;
7333 274 : tree nbits;
7334 :
7335 274 : location = M2LexBuf_TokenToLocation (tokenno);
7336 274 : nbits = CalcBitsInSet (location, settype);
7337 274 : m2expr_BuildLogicalRotate (location, SymbolConversion_Mod2Gcc (dest), SymbolConversion_Mod2Gcc (src), SymbolConversion_Mod2Gcc (count), nbits, false);
7338 274 : }
7339 :
7340 :
7341 : /*
7342 : CodeBinarySetShiftRotate - encode a binary set arithmetic operation.
7343 : */
7344 :
7345 1082 : static void CodeBinarySetShiftRotate (unsigned int quad, bool isshift)
7346 : {
7347 1082 : M2Quads_QuadOperator op;
7348 1082 : unsigned int combined;
7349 1082 : unsigned int lastpos;
7350 1082 : unsigned int destpos;
7351 1082 : unsigned int srcpos;
7352 1082 : unsigned int countpos;
7353 1082 : unsigned int dest;
7354 1082 : unsigned int src;
7355 1082 : unsigned int count;
7356 1082 : bool overflowChecking;
7357 1082 : bool constExpr;
7358 1082 : unsigned int settype;
7359 :
7360 1082 : M2Quads_GetQuadOtok (quad, &lastpos, &op, &dest, &src, &count, &overflowChecking, &constExpr, &destpos, &srcpos, &countpos);
7361 : /* Firstly ensure that constant literals are declared. */
7362 1082 : M2GCCDeclare_DeclareConstant (countpos, count);
7363 1082 : M2GCCDeclare_DeclareConstant (srcpos, src);
7364 1082 : M2GCCDeclare_DeclareConstructor (countpos, quad, count);
7365 1082 : M2GCCDeclare_DeclareConstructor (srcpos, quad, src);
7366 1082 : if (SymbolTable_IsConst (dest))
7367 : {
7368 0 : combined = M2LexBuf_MakeVirtual2Tok (srcpos, countpos);
7369 0 : if ((SymbolTable_IsValueSolved (src)) && (SymbolTable_IsValueSolved (count)))
7370 : {
7371 0 : M2Debug_Assert ((M2Base_MixTypes (FindType (count), FindType (src), combined)) != SymbolTable_NulSym);
7372 0 : SymbolTable_PutConst (dest, FindType (count));
7373 0 : SymbolTable_PushValue (src);
7374 0 : SymbolTable_PushValue (count);
7375 0 : if (isshift)
7376 : {
7377 0 : M2ALU_SetShift (combined);
7378 : }
7379 : else
7380 : {
7381 0 : M2ALU_SetRotate (combined);
7382 : }
7383 0 : SymbolTable_PopValue (dest);
7384 0 : SymbolTable_PutConstSet (dest);
7385 : }
7386 : else
7387 : {
7388 0 : M2MetaError_MetaErrorT0 (combined, (const char *) "{%E}constant expression cannot be evaluated", 43);
7389 : }
7390 : }
7391 : else
7392 : {
7393 1082 : combined = M2LexBuf_MakeVirtualTok (destpos, srcpos, countpos);
7394 1082 : settype = SymbolTable_GetDType (dest);
7395 1082 : M2Debug_Assert (SymbolTable_IsSet (settype));
7396 : /* Check for narrow and wide sets and call M2WIDESET if appropriate. */
7397 1082 : if (SymbolTable_GetSetInWord (settype))
7398 : {
7399 746 : if (isshift)
7400 : {
7401 472 : CodeNarrowSetShift (combined, settype, dest, src, count);
7402 : }
7403 : else
7404 : {
7405 274 : CodeNarrowSetRotate (combined, settype, dest, src, count);
7406 : }
7407 : }
7408 : else
7409 : {
7410 336 : if (isshift)
7411 : {
7412 204 : SetWideSetShiftRotate (combined, NameKey_MakeKey ((const char *) "Shift", 5), settype, dest, src, count);
7413 : }
7414 : else
7415 : {
7416 132 : SetWideSetShiftRotate (combined, NameKey_MakeKey ((const char *) "Rotate", 6), settype, dest, src, count);
7417 : }
7418 : }
7419 : }
7420 1082 : }
7421 :
7422 :
7423 : /*
7424 : FoldSetShift - check whether we can fold a logical shift.
7425 : */
7426 :
7427 27654 : static void FoldSetShift (unsigned int tokenno, M2GCCDeclare_WalkAction p, unsigned int quad, unsigned int Dest, unsigned int Src, unsigned int ShiftCount)
7428 : {
7429 0 : FoldBinarySet (tokenno, p, (M2GenGCC_ProcedureCardinal) {(M2GenGCC_ProcedureCardinal_t) M2ALU_SetShift}, quad, Dest, Src, ShiftCount);
7430 0 : }
7431 :
7432 :
7433 : /*
7434 : CodeSetShift - encode set arithmetic shift.
7435 : */
7436 :
7437 676 : static void CodeSetShift (unsigned int quad)
7438 : {
7439 676 : CodeBinarySetShiftRotate (quad, true);
7440 676 : }
7441 :
7442 :
7443 : /*
7444 : FoldSetRotate - check whether we can fold a logical rotate.
7445 : */
7446 :
7447 23892 : static void FoldSetRotate (unsigned int tokenno, M2GCCDeclare_WalkAction p, unsigned int quad, unsigned int Dest, unsigned int Src, unsigned int RotateCount)
7448 : {
7449 0 : FoldBinarySet (tokenno, p, (M2GenGCC_ProcedureCardinal) {(M2GenGCC_ProcedureCardinal_t) M2ALU_SetRotate}, quad, Dest, Src, RotateCount);
7450 0 : }
7451 :
7452 :
7453 : /*
7454 : CodeSetRotate - encode set arithmetic rotate.
7455 : */
7456 :
7457 406 : static void CodeSetRotate (unsigned int quad)
7458 : {
7459 406 : CodeBinarySetShiftRotate (quad, false);
7460 406 : }
7461 :
7462 :
7463 : /*
7464 : CodeSetLogicalDifference - encode set arithmetic logical difference.
7465 : */
7466 :
7467 66 : static void CodeSetLogicalDifference (unsigned int quad)
7468 : {
7469 66 : CodeBinarySet ((M2GenGCC_ProcedureCardinal) {(M2GenGCC_ProcedureCardinal_t) M2ALU_SetAnd}, (M2GenGCC_BinaryFunction) {(M2GenGCC_BinaryFunction_t) m2expr_BuildLogicalDifference}, NameKey_MakeKey ((const char *) "LogicalDifference", 17), quad);
7470 66 : }
7471 :
7472 :
7473 : /*
7474 : FoldSymmetricDifference - check whether we can fold a logical difference.
7475 : */
7476 :
7477 664 : static void FoldSymmetricDifference (unsigned int tokenno, M2GCCDeclare_WalkAction p, unsigned int quad, unsigned int op1, unsigned int op2, unsigned int op3)
7478 : {
7479 0 : FoldBinarySet (tokenno, p, (M2GenGCC_ProcedureCardinal) {(M2GenGCC_ProcedureCardinal_t) M2ALU_SetSymmetricDifference}, quad, op1, op2, op3);
7480 0 : }
7481 :
7482 :
7483 : /*
7484 : CodeSetSymmetricDifference - code set difference.
7485 : A logical xor expression.
7486 : */
7487 :
7488 124 : static void CodeSetSymmetricDifference (unsigned int quad)
7489 : {
7490 124 : CodeBinarySet ((M2GenGCC_ProcedureCardinal) {(M2GenGCC_ProcedureCardinal_t) M2ALU_SetSymmetricDifference}, (M2GenGCC_BinaryFunction) {(M2GenGCC_BinaryFunction_t) m2expr_BuildSymmetricDifference}, NameKey_MakeKey ((const char *) "SymmetricDifference", 19), quad);
7491 124 : }
7492 :
7493 :
7494 : /*
7495 : CodeUnarySet - encode a unary set arithmetic operation.
7496 : Set operands may be longer than a word.
7497 : */
7498 :
7499 78 : static void CodeUnarySet (M2GenGCC_ProcedureCardinal constop, M2GenGCC_UnaryFunction unfunc, unsigned int tokenno, NameKey_Name wideprocname, unsigned int quad, unsigned int result, unsigned int expr)
7500 : {
7501 78 : location_t location;
7502 78 : unsigned int settype;
7503 :
7504 : /* Firstly ensure that constant literals are declared. */
7505 78 : M2GCCDeclare_DeclareConstant (tokenno, expr);
7506 78 : M2GCCDeclare_DeclareConstructor (tokenno, quad, expr);
7507 78 : location = M2LexBuf_TokenToLocation (tokenno);
7508 78 : if (SymbolTable_IsConst (result))
7509 : {
7510 0 : if (SymbolTable_IsValueSolved (expr))
7511 : {
7512 0 : M2Debug_Assert ((FindType (expr)) != SymbolTable_NulSym);
7513 0 : SymbolTable_PutConst (result, FindType (expr));
7514 0 : SymbolTable_PushValue (expr);
7515 0 : (*constop.proc) (tokenno);
7516 0 : SymbolTable_PopValue (result);
7517 0 : SymbolTable_PushValue (result);
7518 0 : SymbolTable_PutConstSet (result);
7519 0 : M2GCCDeclare_ConstantKnownAndUsed (result, m2decl_DeclareKnownConstant (location, SymbolConversion_Mod2Gcc (SymbolTable_GetType (expr)), M2ALU_PopSetTree (tokenno)));
7520 : }
7521 : else
7522 : {
7523 0 : M2MetaError_MetaErrorT0 (tokenno, (const char *) "{%E}constant expression cannot be evaluated", 43);
7524 : }
7525 : }
7526 : else
7527 : {
7528 78 : checkDeclare (result);
7529 78 : settype = SymbolTable_GetLType (result);
7530 78 : M2Debug_Assert (SymbolTable_IsSet (settype));
7531 78 : if (SymbolTable_GetSetInWord (settype))
7532 : {
7533 72 : SetNarrowUnary (location, unfunc, settype, result, expr);
7534 : }
7535 : else
7536 : {
7537 6 : SetWideUnary (tokenno, wideprocname, settype, result, expr);
7538 : }
7539 : }
7540 78 : }
7541 :
7542 :
7543 : /*
7544 : FromM2WIDESETImport - returns M2WIDESET.name.
7545 : */
7546 :
7547 2178 : static unsigned int FromM2WIDESETImport (unsigned int tokenno, NameKey_Name name)
7548 : {
7549 2178 : unsigned int sym;
7550 2178 : unsigned int module;
7551 :
7552 2178 : sym = SymbolTable_NulSym;
7553 2178 : if (M2Options_GetWideset ())
7554 : {
7555 : /* avoid dangling else. */
7556 2178 : module = M2Batch_MakeDefinitionSource (tokenno, NameKey_MakeKey ((const char *) "M2WIDESET", 9));
7557 2178 : sym = SymbolTable_FromModuleGetSym (tokenno, name, module);
7558 2178 : if (SymbolTable_IsUnknown (sym))
7559 : {
7560 0 : M2MetaError_MetaErrorT2 (tokenno, (const char *) "procedure function {%1Aad} is not available from {%2ad}", 55, sym, module);
7561 : }
7562 : }
7563 : else
7564 : {
7565 0 : M2MetaError_MetaErrorT0 (tokenno, (const char *) "{%0A}wideset is not available due to -fno-wideset", 49);
7566 : }
7567 2178 : return sym;
7568 : /* static analysis guarentees a RETURN statement will be used before here. */
7569 : __builtin_unreachable ();
7570 : }
7571 :
7572 :
7573 : /*
7574 : SetWideUnaryLibrary - call wideprocname (result, expr) passing result and expr
7575 : as an array of byte.
7576 : */
7577 :
7578 2 : static void SetWideUnaryLibrary (unsigned int tokenno, NameKey_Name wideprocname, unsigned int settype, unsigned int result, unsigned int expr)
7579 : {
7580 2 : location_t location;
7581 2 : unsigned int procedure;
7582 2 : unsigned int param1;
7583 2 : unsigned int param2;
7584 2 : tree highbit;
7585 2 : tree array1;
7586 2 : tree array2;
7587 2 : tree call;
7588 :
7589 2 : procedure = FromM2WIDESETImport (tokenno, wideprocname);
7590 2 : checkDeclare (procedure);
7591 2 : location = M2LexBuf_TokenToLocation (tokenno);
7592 2 : highbit = m2convert_ToCardinal (location, CalcBitsInSet (location, settype));
7593 2 : param1 = SymbolTable_GetNthParamAnyClosest (procedure, 1, SymbolTable_GetMainModule ());
7594 2 : param2 = SymbolTable_GetNthParamAnyClosest (procedure, 2, SymbolTable_GetMainModule ());
7595 2 : array1 = CreateSetArrayParam (location, tokenno, result, param1);
7596 2 : array2 = CreateSetArrayParam (location, tokenno, expr, param2);
7597 2 : m2statement_BuildParam (location, highbit); /* 3rd Parameter. */
7598 2 : m2statement_BuildParam (location, array2); /* 2nd Parameter. */
7599 2 : m2statement_BuildParam (location, array1); /* 1st Parameter. */
7600 2 : call = m2statement_BuildProcedureCallTree (location, SymbolConversion_Mod2Gcc (procedure), NULL); /* 1st Parameter. */
7601 2 : m2statement_SetLastFunction (NULL);
7602 2 : m2type_AddStatement (location, call);
7603 2 : }
7604 :
7605 :
7606 : /*
7607 : SetWideUnaryBuiltinNot - build an builtin wideset NOT operation.
7608 : */
7609 :
7610 4 : static void SetWideUnaryBuiltinNot (unsigned int tokenno, unsigned int result, unsigned int expr)
7611 : {
7612 4 : location_t location;
7613 4 : tree byte;
7614 4 : tree lhs;
7615 4 : tree rhs;
7616 4 : tree index;
7617 4 : tree high;
7618 :
7619 4 : location = M2LexBuf_TokenToLocation (tokenno);
7620 4 : high = ResolveHigh (tokenno, 1, result);
7621 4 : index = m2expr_GetIntegerZero (location);
7622 4 : byte = SymbolConversion_Mod2Gcc (M2System_Byte);
7623 64 : do {
7624 64 : rhs = m2expr_BuildArray (location, byte, SymbolConversion_Mod2Gcc (expr), index, m2expr_GetIntegerZero (location));
7625 64 : rhs = m2expr_BuildSetNegate (location, rhs);
7626 64 : rhs = m2convert_BuildConvert (location, byte, rhs, false);
7627 64 : lhs = m2expr_BuildArray (location, byte, SymbolConversion_Mod2Gcc (result), index, m2expr_GetIntegerZero (location));
7628 64 : m2statement_BuildAssignmentStatement (location, lhs, rhs);
7629 64 : M2ALU_PushIntegerTree (index);
7630 64 : M2ALU_PushCard (1);
7631 64 : M2ALU_Addn ();
7632 64 : index = M2ALU_PopIntegerTree ();
7633 64 : } while (! ((m2expr_CompareTrees (index, high)) > 0));
7634 4 : }
7635 :
7636 :
7637 : /*
7638 : SetWideUnary - either call the library wideprocname or the builtin
7639 : version depending upon the optimization setting.
7640 : */
7641 :
7642 6 : static void SetWideUnary (unsigned int tokenno, NameKey_Name wideprocname, unsigned int settype, unsigned int result, unsigned int expr)
7643 : {
7644 6 : if (M2Options_OptimizeSets && (wideprocname == (NameKey_MakeKey ((const char *) "Not", 3))))
7645 : {
7646 4 : SetWideUnaryBuiltinNot (tokenno, result, expr);
7647 : }
7648 : else
7649 : {
7650 2 : SetWideUnaryLibrary (tokenno, wideprocname, settype, result, expr);
7651 : }
7652 6 : }
7653 :
7654 :
7655 : /*
7656 : SetNarrowUnary - create tree consisting of:
7657 : result := unfunc (expr)
7658 : result and expr can be lvalues.
7659 : */
7660 :
7661 72 : static void SetNarrowUnary (location_t location, M2GenGCC_UnaryFunction unfunc, unsigned int settype, unsigned int result, unsigned int expr)
7662 : {
7663 72 : bool isResultL;
7664 72 : bool isExprL;
7665 :
7666 72 : isResultL = (SymbolTable_GetMode (result)) == SymbolTable_LeftValue;
7667 72 : isExprL = (SymbolTable_GetMode (expr)) == SymbolTable_LeftValue;
7668 72 : m2statement_BuildAssignmentStatement (location, getrvalue (location, result, settype, isResultL), (tree) ((*unfunc.proc) (location, getrvalue (location, expr, settype, isExprL))));
7669 72 : }
7670 :
7671 :
7672 : /*
7673 : FoldIncl - check whether we can fold the InclOp.
7674 : result := result + (1 << expr)
7675 : */
7676 :
7677 27730 : static void FoldIncl (unsigned int tokenno, M2GCCDeclare_WalkAction p, unsigned int quad, unsigned int result, unsigned int expr)
7678 : {
7679 : /* firstly ensure that constant literals are declared */
7680 27730 : M2GCCDeclare_TryDeclareConstant (tokenno, expr);
7681 27730 : if ((SymbolTable_IsConst (result)) && (SymbolTable_IsConst (expr)))
7682 : {
7683 0 : if ((SymbolConversion_GccKnowsAbout (expr)) && (SymbolTable_IsValueSolved (result)))
7684 : {
7685 : /* fine, we can take advantage of this and fold constants */
7686 0 : SymbolTable_PushValue (result);
7687 0 : M2ALU_AddBit (tokenno, expr);
7688 0 : SymbolConversion_AddModGcc (result, M2ALU_PopSetTree (tokenno));
7689 0 : (*p.proc) (result);
7690 0 : NoChange = false;
7691 0 : M2Quads_SubQuad (quad);
7692 : }
7693 : }
7694 27730 : }
7695 :
7696 :
7697 : /*
7698 : FoldIfLess - check to see if it is possible to evaluate
7699 : if op1 < op2 then goto op3.
7700 : */
7701 :
7702 37942 : static void FoldIfLess (unsigned int tokenno, unsigned int quad, unsigned int left, unsigned int right, unsigned int destQuad)
7703 : {
7704 : /* Firstly ensure that constant literals are declared. */
7705 37942 : M2GCCDeclare_TryDeclareConstant (tokenno, left);
7706 37942 : M2GCCDeclare_TryDeclareConstant (tokenno, right);
7707 37942 : if ((SymbolTable_IsConst (left)) && (SymbolTable_IsConst (right)))
7708 : {
7709 2028 : if ((SymbolTable_IsValueSolved (left)) && (SymbolTable_IsValueSolved (right)))
7710 : {
7711 : /* We can take advantage of the known values and evaluate the condition. */
7712 2028 : SymbolTable_PushValue (left);
7713 2028 : SymbolTable_PushValue (right);
7714 2028 : if (M2ALU_Less (tokenno))
7715 : {
7716 978 : M2Quads_PutQuad (quad, M2Quads_GotoOp, SymbolTable_NulSym, SymbolTable_NulSym, destQuad);
7717 : }
7718 : else
7719 : {
7720 1050 : M2Quads_SubQuad (quad);
7721 : }
7722 2028 : NoChange = false;
7723 : }
7724 : }
7725 37942 : }
7726 :
7727 :
7728 : /*
7729 : FoldIfGre - check to see if it is possible to evaluate
7730 : if op1 > op2 then goto op3.
7731 : */
7732 :
7733 29184 : static void FoldIfGre (unsigned int tokenno, unsigned int quad, unsigned int left, unsigned int right, unsigned int destQuad)
7734 : {
7735 : /* Firstly ensure that constant literals are declared. */
7736 29184 : M2GCCDeclare_TryDeclareConstant (tokenno, left);
7737 29184 : M2GCCDeclare_TryDeclareConstant (tokenno, right);
7738 29184 : if ((SymbolTable_IsConst (left)) && (SymbolTable_IsConst (right)))
7739 : {
7740 72 : if ((SymbolTable_IsValueSolved (left)) && (SymbolTable_IsValueSolved (right)))
7741 : {
7742 : /* We can take advantage of the known values and evaluate the condition. */
7743 72 : SymbolTable_PushValue (left);
7744 72 : SymbolTable_PushValue (right);
7745 72 : if (M2ALU_Gre (tokenno))
7746 : {
7747 12 : M2Quads_PutQuad (quad, M2Quads_GotoOp, SymbolTable_NulSym, SymbolTable_NulSym, destQuad);
7748 : }
7749 : else
7750 : {
7751 60 : M2Quads_SubQuad (quad);
7752 : }
7753 72 : NoChange = false;
7754 : }
7755 : }
7756 29184 : }
7757 :
7758 :
7759 : /*
7760 : FoldIfLessEqu - check to see if it is possible to evaluate
7761 : if op1 <= op2 then goto op3.
7762 : */
7763 :
7764 32162 : static void FoldIfLessEqu (unsigned int tokenno, unsigned int quad, unsigned int left, unsigned int right, unsigned int destQuad)
7765 : {
7766 : /* Firstly ensure that constant literals are declared. */
7767 32162 : M2GCCDeclare_TryDeclareConstant (tokenno, left);
7768 32162 : M2GCCDeclare_TryDeclareConstant (tokenno, right);
7769 32162 : if ((SymbolTable_IsConst (left)) && (SymbolTable_IsConst (right)))
7770 : {
7771 42 : if ((SymbolTable_IsValueSolved (left)) && (SymbolTable_IsValueSolved (right)))
7772 : {
7773 : /* We can take advantage of the known values and evaluate the condition. */
7774 42 : SymbolTable_PushValue (left);
7775 42 : SymbolTable_PushValue (right);
7776 42 : if (M2ALU_LessEqu (tokenno))
7777 : {
7778 36 : M2Quads_PutQuad (quad, M2Quads_GotoOp, SymbolTable_NulSym, SymbolTable_NulSym, destQuad);
7779 : }
7780 : else
7781 : {
7782 6 : M2Quads_SubQuad (quad);
7783 : }
7784 42 : NoChange = false;
7785 : }
7786 : }
7787 32162 : }
7788 :
7789 :
7790 : /*
7791 : FoldIfGreEqu - check to see if it is possible to evaluate
7792 : if op1 >= op2 then goto op3.
7793 : */
7794 :
7795 47650 : static void FoldIfGreEqu (unsigned int tokenno, unsigned int quad, unsigned int left, unsigned int right, unsigned int destQuad)
7796 : {
7797 : /* Firstly ensure that constant literals are declared. */
7798 47650 : M2GCCDeclare_TryDeclareConstant (tokenno, left);
7799 47650 : M2GCCDeclare_TryDeclareConstant (tokenno, right);
7800 47650 : if ((SymbolTable_IsConst (left)) && (SymbolTable_IsConst (right)))
7801 : {
7802 8202 : if ((SymbolTable_IsValueSolved (left)) && (SymbolTable_IsValueSolved (right)))
7803 : {
7804 : /* We can take advantage of the known values and evaluate the condition. */
7805 3888 : SymbolTable_PushValue (left);
7806 3888 : SymbolTable_PushValue (right);
7807 3888 : if (M2ALU_GreEqu (tokenno))
7808 : {
7809 3072 : M2Quads_PutQuad (quad, M2Quads_GotoOp, SymbolTable_NulSym, SymbolTable_NulSym, destQuad);
7810 : }
7811 : else
7812 : {
7813 816 : M2Quads_SubQuad (quad);
7814 : }
7815 3888 : NoChange = false;
7816 : }
7817 : }
7818 47650 : }
7819 :
7820 :
7821 : /*
7822 : FoldIfIn - check whether we can fold the IfInOp
7823 : if op1 in op2 then goto op3
7824 : */
7825 :
7826 53420 : static void FoldIfIn (unsigned int tokenno, unsigned int quad, unsigned int left, unsigned int right, unsigned int destQuad)
7827 : {
7828 : /* Firstly ensure that constant literals are declared. */
7829 53420 : M2GCCDeclare_TryDeclareConstant (tokenno, left);
7830 53420 : M2GCCDeclare_TryDeclareConstant (tokenno, right);
7831 53420 : if ((SymbolTable_IsConst (left)) && (SymbolTable_IsConst (right)))
7832 : {
7833 0 : if ((SymbolTable_IsValueSolved (left)) && (SymbolTable_IsValueSolved (right)))
7834 : {
7835 0 : if (CheckBinaryExpressionTypes (quad, (M2GCCDeclare_WalkAction) {(M2GCCDeclare_WalkAction_t) NoWalkProcedure}))
7836 : {
7837 : /* We can take advantage of the known values and evaluate the condition. */
7838 0 : SymbolTable_PushValue (right);
7839 0 : if (M2ALU_SetIn (tokenno, left))
7840 : {
7841 0 : M2Quads_PutQuad (quad, M2Quads_GotoOp, SymbolTable_NulSym, SymbolTable_NulSym, destQuad);
7842 : }
7843 : else
7844 : {
7845 0 : M2Quads_SubQuad (quad);
7846 : }
7847 : }
7848 : else
7849 : {
7850 0 : M2Quads_SubQuad (quad);
7851 : }
7852 0 : NoChange = false;
7853 : }
7854 : }
7855 53420 : }
7856 :
7857 :
7858 : /*
7859 : FoldIfNotIn - check whether we can fold the IfNotInOp
7860 : if not (op1 in op2) then goto op3
7861 : */
7862 :
7863 9464 : static void FoldIfNotIn (unsigned int tokenno, unsigned int quad, unsigned int left, unsigned int right, unsigned int destQuad)
7864 : {
7865 : /* Firstly ensure that constant literals are declared. */
7866 9464 : M2GCCDeclare_TryDeclareConstant (tokenno, left);
7867 9464 : M2GCCDeclare_TryDeclareConstant (tokenno, right);
7868 9464 : if ((SymbolTable_IsConst (left)) && (SymbolTable_IsConst (right)))
7869 : {
7870 0 : if ((SymbolTable_IsValueSolved (left)) && (SymbolTable_IsValueSolved (right)))
7871 : {
7872 0 : if (CheckBinaryExpressionTypes (quad, (M2GCCDeclare_WalkAction) {(M2GCCDeclare_WalkAction_t) NoWalkProcedure}))
7873 : {
7874 : /* We can take advantage of the known values and evaluate the
7875 : condition. */
7876 0 : SymbolTable_PushValue (right);
7877 0 : if (! (M2ALU_SetIn (tokenno, left)))
7878 : {
7879 0 : M2Quads_PutQuad (quad, M2Quads_GotoOp, SymbolTable_NulSym, SymbolTable_NulSym, destQuad);
7880 : }
7881 : else
7882 : {
7883 0 : M2Quads_SubQuad (quad);
7884 : }
7885 : }
7886 : else
7887 : {
7888 0 : M2Quads_SubQuad (quad);
7889 : }
7890 0 : NoChange = false;
7891 : }
7892 : }
7893 9464 : }
7894 :
7895 :
7896 : /*
7897 : FoldIfEqu - check to see if it is possible to evaluate
7898 : if op1 = op2 then goto op3.
7899 : */
7900 :
7901 687321 : static void FoldIfEqu (unsigned int tokenno, unsigned int quad, unsigned int left, unsigned int right, unsigned int destQuad)
7902 : {
7903 : /* Firstly ensure that constant literals are declared. */
7904 687321 : M2GCCDeclare_TryDeclareConstant (tokenno, left);
7905 687321 : M2GCCDeclare_TryDeclareConstant (tokenno, right);
7906 687321 : if ((SymbolTable_IsConst (left)) && (SymbolTable_IsConst (right)))
7907 : {
7908 1214 : if ((SymbolTable_IsValueSolved (left)) && (SymbolTable_IsValueSolved (right)))
7909 : {
7910 : /* We can take advantage of the known values and evaluate the
7911 : condition. */
7912 734 : SymbolTable_PushValue (left);
7913 734 : SymbolTable_PushValue (right);
7914 734 : if (M2ALU_Equ (tokenno))
7915 : {
7916 404 : M2Quads_PutQuad (quad, M2Quads_GotoOp, SymbolTable_NulSym, SymbolTable_NulSym, destQuad);
7917 : }
7918 : else
7919 : {
7920 330 : M2Quads_SubQuad (quad);
7921 : }
7922 734 : NoChange = false;
7923 : }
7924 : }
7925 687321 : }
7926 :
7927 :
7928 : /*
7929 : FoldIfNotEqu - check to see if it is possible to evaluate
7930 : if op1 # op2 then goto op3.
7931 : */
7932 :
7933 343129 : static void FoldIfNotEqu (unsigned int tokenno, unsigned int quad, unsigned int left, unsigned int right, unsigned int destQuad)
7934 : {
7935 : /* Firstly ensure that constant literals are declared. */
7936 343129 : M2GCCDeclare_TryDeclareConstant (tokenno, left);
7937 343129 : M2GCCDeclare_TryDeclareConstant (tokenno, right);
7938 343129 : if ((SymbolTable_IsConst (left)) && (SymbolTable_IsConst (right)))
7939 : {
7940 3570 : if ((SymbolTable_IsValueSolved (left)) && (SymbolTable_IsValueSolved (right)))
7941 : {
7942 : /* We can take advantage of the known values and evaluate the
7943 : condition. */
7944 3504 : SymbolTable_PushValue (left);
7945 3504 : SymbolTable_PushValue (right);
7946 3504 : if (M2ALU_NotEqu (tokenno))
7947 : {
7948 2654 : M2Quads_PutQuad (quad, M2Quads_GotoOp, SymbolTable_NulSym, SymbolTable_NulSym, destQuad);
7949 : }
7950 : else
7951 : {
7952 850 : M2Quads_SubQuad (quad);
7953 : }
7954 3504 : NoChange = false;
7955 : }
7956 : }
7957 343129 : }
7958 :
7959 :
7960 : /*
7961 : GetSetLimits - assigns low and high to the limits of the declared, set.
7962 : */
7963 :
7964 6074 : static void GetSetLimits (unsigned int set, unsigned int *low, unsigned int *high)
7965 : {
7966 6074 : unsigned int type;
7967 :
7968 6074 : type = SymbolTable_GetType (set);
7969 6074 : if (SymbolTable_IsSubrange (type))
7970 : {
7971 4762 : SymbolTable_GetSubrange (type, high, low);
7972 : }
7973 : else
7974 : {
7975 1312 : (*low) = M2GCCDeclare_GetTypeMin (type);
7976 1312 : (*high) = M2GCCDeclare_GetTypeMax (type);
7977 : }
7978 6074 : }
7979 :
7980 :
7981 : /*
7982 : IsElementInRange - returns TRUE if expr references a bit in setvar
7983 : which is in the range [low..high]. If expr is a
7984 : variable it returns TRUE. FALSE is returned if we
7985 : know expr to be out of bounds.
7986 : */
7987 :
7988 4388 : static bool IsElementInRange (unsigned int tokenno, unsigned int settype, unsigned int setvar, unsigned int expr)
7989 : {
7990 4388 : unsigned int low;
7991 4388 : unsigned int high;
7992 :
7993 4388 : if (SymbolTable_IsConst (expr))
7994 : {
7995 1692 : GetSetLimits (settype, &low, &high);
7996 1692 : SymbolTable_PushValue (expr);
7997 1692 : SymbolTable_PushValue (high);
7998 1692 : if (M2ALU_Gre (tokenno))
7999 : {
8000 0 : M2MetaError_MetaErrorT1 (tokenno, (const char *) "bit exceeds the range of set {%1Eatd}", 37, setvar);
8001 0 : return false;
8002 : }
8003 1692 : SymbolTable_PushValue (expr);
8004 1692 : SymbolTable_PushValue (low);
8005 1692 : if (M2ALU_Less (tokenno))
8006 : {
8007 6 : M2MetaError_MetaErrorT1 (tokenno, (const char *) "bit underflows the range of set {%1Eatd}", 40, setvar);
8008 6 : return false;
8009 : }
8010 : }
8011 : return true;
8012 : /* static analysis guarentees a RETURN statement will be used before here. */
8013 : __builtin_unreachable ();
8014 : }
8015 :
8016 :
8017 : /*
8018 : SetElementToBit -
8019 : */
8020 :
8021 4382 : static tree SetElementToBit (location_t location, unsigned int settype, unsigned int expr)
8022 : {
8023 4382 : unsigned int lowelement;
8024 4382 : unsigned int highelement;
8025 4382 : tree low;
8026 :
8027 4382 : GetSetLimits (settype, &lowelement, &highelement);
8028 4382 : SymbolTable_PushValue (lowelement);
8029 4382 : low = M2ALU_PopIntegerTree ();
8030 4382 : return m2expr_BuildSub (location, m2convert_ToCardinal (location, SymbolConversion_Mod2Gcc (expr)), m2convert_ToCardinal (location, low), false);
8031 : /* static analysis guarentees a RETURN statement will be used before here. */
8032 : __builtin_unreachable ();
8033 : }
8034 :
8035 :
8036 : /*
8037 : CodeNarrowIncl - result |= (1 << expr).
8038 : */
8039 :
8040 892 : static void CodeNarrowIncl (location_t location, unsigned int settype, unsigned int result, unsigned int expr)
8041 : {
8042 892 : tree bit;
8043 892 : bool isLvalue;
8044 :
8045 892 : bit = SetElementToBit (location, settype, expr);
8046 892 : isLvalue = (SymbolTable_GetMode (result)) == SymbolTable_LeftValue;
8047 892 : m2statement_BuildAssignmentStatement (location, getrvalue (location, result, settype, isLvalue), m2convert_ToBitset (location, m2expr_BuildLogicalOr (location, getrvalue (location, result, settype, isLvalue), m2expr_BuildLSL (location, m2expr_GetWordOne (location), bit, false))));
8048 892 : }
8049 :
8050 :
8051 : /*
8052 : CodeNarrowExcl - result &= (~ (1 << expr)).
8053 : */
8054 :
8055 566 : static void CodeNarrowExcl (location_t location, unsigned int settype, unsigned int result, unsigned int expr)
8056 : {
8057 566 : tree bit;
8058 566 : tree mask;
8059 566 : bool isLvalue;
8060 :
8061 566 : bit = SetElementToBit (location, settype, expr);
8062 566 : mask = m2expr_BuildSetNegate (location, m2expr_BuildLSL (location, m2expr_GetWordOne (location), m2convert_ToWord (location, bit), false));
8063 566 : isLvalue = (SymbolTable_GetMode (result)) == SymbolTable_LeftValue;
8064 566 : m2statement_BuildAssignmentStatement (location, getrvalue (location, result, settype, isLvalue), m2convert_ToBitset (location, m2expr_BuildLogicalAnd (location, getrvalue (location, result, settype, isLvalue), mask)));
8065 566 : }
8066 :
8067 :
8068 : /*
8069 : SetWideUnaryBuiltinIncl -
8070 : */
8071 :
8072 128 : static void SetWideUnaryBuiltinIncl (location_t location, tree dest, tree bitno)
8073 : {
8074 128 : m2statement_BuildAssignmentStatement (location, dest, m2convert_BuildConvert (location, SymbolConversion_Mod2Gcc (M2System_Byte), m2expr_BuildLogicalOr (location, dest, m2expr_BuildLSL (location, m2expr_GetWordOne (location), bitno, false)), false));
8075 128 : }
8076 :
8077 :
8078 : /*
8079 : SetWideUnaryBuiltinExcl -
8080 : */
8081 :
8082 80 : static void SetWideUnaryBuiltinExcl (location_t location, tree dest, tree bitno)
8083 : {
8084 80 : tree mask;
8085 :
8086 80 : mask = m2expr_BuildSetNegate (location, m2expr_BuildLSL (location, m2expr_GetWordOne (location), m2convert_ToWord (location, bitno), false));
8087 80 : m2statement_BuildAssignmentStatement (location, dest, m2convert_BuildConvert (location, SymbolConversion_Mod2Gcc (M2System_Byte), m2expr_BuildLogicalAnd (location, dest, mask), false));
8088 80 : }
8089 :
8090 208 : static void SetWideUnaryBuiltinInclExcl (unsigned int tokenno, unsigned int settype, unsigned int des, unsigned int expr, bool incl)
8091 : {
8092 208 : tree bitsperbyte;
8093 208 : tree byteno;
8094 208 : tree bitno;
8095 208 : tree dest;
8096 208 : tree bit;
8097 208 : location_t location;
8098 :
8099 : /*
8100 : SetWideUnaryBuiltinIncl -
8101 : */
8102 208 : location = M2LexBuf_TokenToLocation (tokenno);
8103 208 : bit = m2convert_ToCardinal (location, SetElementToBit (location, settype, expr));
8104 208 : bitsperbyte = m2convert_ToCardinal (location, m2expr_GetSizeOfInBits (SymbolConversion_Mod2Gcc (M2System_Byte)));
8105 208 : byteno = m2expr_BuildDivFloor (location, bit, bitsperbyte, false);
8106 208 : bitno = m2expr_BuildModFloor (location, bit, bitsperbyte, false);
8107 208 : dest = m2expr_BuildArray (location, SymbolConversion_Mod2Gcc (M2System_Byte), getrvalue (location, des, SymbolTable_GetType (des), (SymbolTable_GetMode (des)) == SymbolTable_LeftValue), byteno, m2expr_GetIntegerZero (location));
8108 208 : if (incl)
8109 : {
8110 128 : SetWideUnaryBuiltinIncl (location, dest, bitno);
8111 : }
8112 : else
8113 : {
8114 80 : SetWideUnaryBuiltinExcl (location, dest, bitno);
8115 : }
8116 208 : }
8117 :
8118 :
8119 : /*
8120 : SetWideInclExcl - generates M2WIDESET.procedurename (result, expr).
8121 : */
8122 :
8123 532 : static void SetWideInclExcl (unsigned int tokenno, unsigned int settype, unsigned int result, unsigned int expr, NameKey_Name procedurename)
8124 : {
8125 532 : if (M2Options_OptimizeSets)
8126 : {
8127 208 : if (procedurename == (NameKey_MakeKey ((const char *) "Incl", 4)))
8128 : {
8129 128 : SetWideUnaryBuiltinInclExcl (tokenno, settype, result, expr, true);
8130 : }
8131 80 : else if (procedurename == (NameKey_MakeKey ((const char *) "Excl", 4)))
8132 : {
8133 : /* avoid dangling else. */
8134 80 : SetWideUnaryBuiltinInclExcl (tokenno, settype, result, expr, false);
8135 : }
8136 : else
8137 : {
8138 : /* avoid dangling else. */
8139 0 : M2Error_InternalError ((const char *) "expecting Incl or Excl procedure", 32);
8140 : }
8141 : }
8142 : else
8143 : {
8144 324 : SetWideInclExclLibrary (tokenno, settype, result, expr, procedurename);
8145 : }
8146 532 : }
8147 :
8148 :
8149 : /*
8150 : SetWideInclExclLibrary -
8151 : */
8152 :
8153 324 : static void SetWideInclExclLibrary (unsigned int tokenno, unsigned int settype, unsigned int result, unsigned int expr, NameKey_Name procedurename)
8154 : {
8155 324 : location_t location;
8156 324 : unsigned int procedure;
8157 324 : unsigned int setparam;
8158 324 : tree highbit;
8159 324 : tree bit;
8160 324 : tree setarray;
8161 324 : tree call;
8162 :
8163 324 : procedure = FromM2WIDESETImport (tokenno, procedurename);
8164 324 : location = M2LexBuf_TokenToLocation (tokenno);
8165 324 : bit = SetElementToBit (location, settype, expr);
8166 324 : highbit = m2convert_ToCardinal (location, CalcBitsInSet (location, settype));
8167 324 : setparam = SymbolTable_GetNthParamAnyClosest (procedure, 1, SymbolTable_GetMainModule ());
8168 324 : setarray = CreateSetArrayParam (location, tokenno, result, setparam);
8169 324 : m2statement_BuildParam (location, highbit); /* 3rd Parameter. */
8170 324 : m2statement_BuildParam (location, m2convert_ToCardinal (location, bit)); /* 2nd Parameter. */
8171 324 : m2statement_BuildParam (location, setarray); /* 1st Parameter. */
8172 324 : call = m2statement_BuildProcedureCallTree (location, SymbolConversion_Mod2Gcc (procedure), NULL); /* 1st Parameter. */
8173 324 : m2statement_SetLastFunction (NULL);
8174 324 : m2type_AddStatement (location, call);
8175 324 : }
8176 :
8177 :
8178 : /*
8179 : CodeIncl - encode an InclOp:
8180 : result |= (1 << expr).
8181 : */
8182 :
8183 1226 : static void CodeIncl (unsigned int quad)
8184 : {
8185 1226 : bool overflow;
8186 1226 : bool constExpr;
8187 1226 : M2Quads_QuadOperator op;
8188 1226 : unsigned int tokenno;
8189 1226 : unsigned int result;
8190 1226 : unsigned int expr;
8191 1226 : unsigned int settype;
8192 1226 : unsigned int nooperand;
8193 1226 : unsigned int nopos;
8194 1226 : location_t location;
8195 :
8196 1226 : M2Quads_GetQuadOtok (quad, &tokenno, &op, &result, &nooperand, &expr, &overflow, &constExpr, &nopos, &nopos, &nopos);
8197 : /* Firstly ensure that constant literals are declared */
8198 1226 : M2GCCDeclare_DeclareConstant (tokenno, expr);
8199 1226 : location = M2LexBuf_TokenToLocation (tokenno);
8200 1226 : checkDeclare (result);
8201 1226 : settype = SymbolTable_GetLType (result);
8202 1226 : M2Debug_Assert (SymbolTable_IsSet (settype));
8203 1226 : if (SymbolTable_IsConst (result))
8204 : {
8205 0 : if (SymbolTable_IsConst (expr))
8206 : {
8207 0 : M2Error_InternalError ((const char *) "this quadruple should have been removed by FoldIncl", 51);
8208 : }
8209 : else
8210 : {
8211 0 : M2Error_InternalError ((const char *) "should not get to here (why are we generating <incl const, var> ?)", 66);
8212 : }
8213 : }
8214 : else
8215 : {
8216 1226 : if (IsElementInRange (tokenno, settype, result, expr))
8217 : {
8218 : /* avoid gcc warning by using compound statement even if not strictly necessary. */
8219 1226 : if (SymbolTable_GetSetInWord (settype))
8220 : {
8221 892 : CodeNarrowIncl (location, settype, result, expr);
8222 : }
8223 : else
8224 : {
8225 334 : SetWideInclExcl (tokenno, settype, result, expr, NameKey_MakeKey ((const char *) "Incl", 4));
8226 : }
8227 : }
8228 : }
8229 1226 : }
8230 :
8231 :
8232 : /*
8233 : FoldExcl - check whether we can fold the InclOp.
8234 : result &= ~ (1 << expr).
8235 : */
8236 :
8237 15594 : static void FoldExcl (unsigned int tokenno, M2GCCDeclare_WalkAction p, unsigned int quad, unsigned int result, unsigned int expr)
8238 : {
8239 : /* Firstly ensure that constant literals are declared */
8240 15594 : M2GCCDeclare_TryDeclareConstant (tokenno, expr);
8241 15594 : if ((SymbolTable_IsConst (result)) && (SymbolTable_IsConst (expr)))
8242 : {
8243 0 : if ((SymbolConversion_GccKnowsAbout (expr)) && (SymbolTable_IsValueSolved (result)))
8244 : {
8245 0 : SymbolTable_PushValue (result);
8246 0 : M2ALU_SubBit (tokenno, expr);
8247 0 : SymbolConversion_AddModGcc (result, M2ALU_PopSetTree (tokenno));
8248 0 : (*p.proc) (result);
8249 0 : NoChange = false;
8250 0 : M2Quads_SubQuad (quad);
8251 : }
8252 : }
8253 15594 : }
8254 :
8255 :
8256 : /*
8257 : CodeExcl - encode an ExclOp:
8258 : result &= (~ (1 << expr)).
8259 : */
8260 :
8261 764 : static void CodeExcl (unsigned int quad)
8262 : {
8263 764 : bool overflow;
8264 764 : bool constExpr;
8265 764 : M2Quads_QuadOperator op;
8266 764 : unsigned int tokenno;
8267 764 : unsigned int result;
8268 764 : unsigned int expr;
8269 764 : unsigned int settype;
8270 764 : unsigned int nooperand;
8271 764 : unsigned int nopos;
8272 764 : location_t location;
8273 :
8274 764 : M2Quads_GetQuadOtok (quad, &tokenno, &op, &result, &nooperand, &expr, &overflow, &constExpr, &nopos, &nopos, &nopos);
8275 : /* Firstly ensure that constant literals are declared */
8276 764 : M2GCCDeclare_DeclareConstant (tokenno, expr);
8277 764 : location = M2LexBuf_TokenToLocation (tokenno);
8278 764 : checkDeclare (result);
8279 764 : settype = SymbolTable_GetLType (result);
8280 764 : M2Debug_Assert (SymbolTable_IsSet (settype));
8281 764 : if (SymbolTable_IsConst (result))
8282 : {
8283 0 : if (SymbolTable_IsConst (expr))
8284 : {
8285 0 : M2Error_InternalError ((const char *) "this quadruple should have been removed by FoldExcl", 51);
8286 : }
8287 : else
8288 : {
8289 0 : M2Error_InternalError ((const char *) "should not get to here (why are we generating <excl const, var> ?)", 66);
8290 : }
8291 : }
8292 : else
8293 : {
8294 764 : if (IsElementInRange (tokenno, settype, result, expr))
8295 : {
8296 : /* avoid gcc warning by using compound statement even if not strictly necessary. */
8297 764 : if (SymbolTable_GetSetInWord (settype))
8298 : {
8299 566 : CodeNarrowExcl (location, settype, result, expr);
8300 : }
8301 : else
8302 : {
8303 198 : SetWideInclExcl (tokenno, settype, result, expr, NameKey_MakeKey ((const char *) "Excl", 4));
8304 : }
8305 : }
8306 : }
8307 764 : }
8308 :
8309 :
8310 : /*
8311 : FoldUnary - check whether we can fold the unop operation.
8312 : */
8313 :
8314 39783 : static void FoldUnary (unsigned int tokenno, M2GCCDeclare_WalkAction p, m2expr_BuildUnaryProcedure unop, tree ZConstToTypedConst, unsigned int quad, unsigned int result, unsigned int expr)
8315 : {
8316 39783 : tree tv;
8317 39783 : location_t location;
8318 :
8319 : /* firstly ensure that any constant literal is declared */
8320 39783 : M2GCCDeclare_TryDeclareConstant (tokenno, expr);
8321 39783 : location = M2LexBuf_TokenToLocation (tokenno);
8322 39783 : if (SymbolTable_IsConst (expr))
8323 : {
8324 19547 : if (SymbolConversion_GccKnowsAbout (expr))
8325 : {
8326 : /* avoid gcc warning by using compound statement even if not strictly necessary. */
8327 : /* fine, we can take advantage of this and fold constants */
8328 19547 : if (SymbolTable_IsConst (result))
8329 : {
8330 19547 : if (ZConstToTypedConst == ((tree) (NULL)))
8331 : {
8332 : /* avoid gcc warning by using compound statement even if not strictly necessary. */
8333 19547 : if (((SymbolTable_GetType (expr)) == SymbolTable_NulSym) || (M2Base_IsOrdinalType (SymbolTable_SkipType (SymbolTable_GetType (expr)))))
8334 : {
8335 19103 : ZConstToTypedConst = m2type_GetM2ZType ();
8336 : }
8337 444 : else if ((M2Base_IsRealType (SymbolTable_SkipType (SymbolTable_GetType (expr)))) || (M2System_IsRealN (SymbolTable_SkipType (SymbolTable_GetType (expr)))))
8338 : {
8339 : /* avoid dangling else. */
8340 264 : ZConstToTypedConst = m2type_GetM2RType ();
8341 : }
8342 180 : else if ((M2Base_IsComplexType (SymbolTable_SkipType (SymbolTable_GetType (expr)))) || (M2System_IsComplexN (SymbolTable_SkipType (SymbolTable_GetType (expr)))))
8343 : {
8344 : /* avoid dangling else. */
8345 180 : ZConstToTypedConst = m2type_GetM2CType ();
8346 : }
8347 : }
8348 19547 : if ((SymbolTable_GetType (result)) == SymbolTable_NulSym)
8349 : {
8350 0 : SymbolTable_PutConst (result, M2Base_NegateType (SymbolTable_GetType (expr))); /* , tokenno */
8351 : }
8352 19547 : tv = (*unop.proc) (location, LValueToGenericPtrOrConvert (expr, ZConstToTypedConst), false);
8353 19547 : M2ALU_CheckOrResetOverflow (tokenno, tv, M2Quads_MustCheckOverflow (quad));
8354 19547 : SymbolConversion_AddModGcc (result, m2decl_DeclareKnownConstant (location, ZConstToTypedConst, tv));
8355 19547 : (*p.proc) (result);
8356 19547 : NoChange = false;
8357 19547 : M2Quads_SubQuad (quad);
8358 : }
8359 : /* we can still fold the expression, but not the assignment, however, we will
8360 : not do this here but in CodeUnary
8361 : */
8362 : }
8363 : }
8364 39783 : }
8365 :
8366 :
8367 : /*
8368 : FoldUnarySet - check whether we can fold the doOp operation.
8369 : */
8370 :
8371 60 : static void FoldUnarySet (unsigned int tokenno, M2GCCDeclare_WalkAction p, M2GenGCC_ProcedureCardinal doOp, unsigned int quad, unsigned int result, unsigned int expr)
8372 : {
8373 60 : location_t location;
8374 :
8375 : /* firstly try and ensure that constants are declared */
8376 60 : M2GCCDeclare_TryDeclareConstant (tokenno, expr);
8377 60 : location = M2LexBuf_TokenToLocation (tokenno);
8378 60 : if (((SymbolTable_IsConst (expr)) && (SymbolTable_IsConstSet (expr))) && (SymbolTable_IsConst (result)))
8379 : {
8380 60 : if ((SymbolTable_IsValueSolved (expr)) && ((SymbolTable_GetType (expr)) != SymbolTable_NulSym))
8381 : {
8382 60 : SymbolTable_PutConst (result, FindType (expr));
8383 60 : SymbolTable_PushValue (expr);
8384 60 : (*doOp.proc) (tokenno);
8385 60 : SymbolTable_PopValue (result);
8386 60 : SymbolTable_PushValue (result);
8387 60 : SymbolTable_PutConstSet (result);
8388 60 : SymbolConversion_AddModGcc (result, m2decl_DeclareKnownConstant (location, SymbolConversion_Mod2Gcc (SymbolTable_GetType (expr)), M2ALU_PopSetTree (tokenno)));
8389 60 : (*p.proc) (result);
8390 60 : NoChange = false;
8391 60 : M2Quads_SubQuad (quad);
8392 : }
8393 : }
8394 60 : }
8395 :
8396 :
8397 : /*
8398 : CodeUnaryCheck - encode a unary arithmetic operation.
8399 : */
8400 :
8401 912 : static void CodeUnaryCheck (m2expr_BuildUnaryCheckProcedure unop, tree ZConstToTypedConst, unsigned int quad, unsigned int result, unsigned int expr)
8402 : {
8403 912 : unsigned int lowestType;
8404 912 : tree min;
8405 912 : tree max;
8406 912 : tree lowest;
8407 912 : tree tv;
8408 912 : location_t location;
8409 :
8410 : /* firstly ensure that any constant literal is declared */
8411 912 : M2GCCDeclare_DeclareConstant (CurrentQuadToken, expr);
8412 912 : M2GCCDeclare_DeclareConstructor (CurrentQuadToken, quad, expr);
8413 912 : location = M2LexBuf_TokenToLocation (CurrentQuadToken);
8414 912 : lowestType = SymbolTable_GetLType (result);
8415 912 : if (lowestType == SymbolTable_NulSym)
8416 : {
8417 : lowest = NULL;
8418 : }
8419 : else
8420 : {
8421 912 : lowest = SymbolConversion_Mod2Gcc (lowestType);
8422 : }
8423 912 : if (M2Range_GetMinMax (CurrentQuadToken, lowestType, &min, &max))
8424 : {
8425 848 : tv = (*unop.proc) (location, M2GenGCC_LValueToGenericPtr (location, expr), lowest, min, max);
8426 : }
8427 : else
8428 : {
8429 64 : tv = (*unop.proc) (location, M2GenGCC_LValueToGenericPtr (location, expr), NULL, NULL, NULL);
8430 : }
8431 912 : M2ALU_CheckOrResetOverflow (CurrentQuadToken, tv, M2Quads_MustCheckOverflow (quad));
8432 912 : if (SymbolTable_IsConst (result))
8433 : {
8434 0 : if (ZConstToTypedConst == ((tree) (NULL)))
8435 : {
8436 0 : ZConstToTypedConst = (tree) (SymbolConversion_Mod2Gcc (SymbolTable_GetType (expr)));
8437 : }
8438 : /* still have a constant which was not resolved, pass it to gcc */
8439 0 : SymbolTable_PutConst (result, FindType (expr));
8440 0 : M2GCCDeclare_ConstantKnownAndUsed (result, m2decl_DeclareKnownConstant (location, ZConstToTypedConst, tv));
8441 : }
8442 : else
8443 : {
8444 912 : if (M2SSA_EnableSSA && (SymbolTable_IsVariableSSA (result)))
8445 : {
8446 : Replace (result, tv);
8447 : }
8448 : else
8449 : {
8450 912 : m2statement_BuildAssignmentStatement (location, SymbolConversion_Mod2Gcc (result), tv);
8451 : }
8452 : }
8453 912 : }
8454 :
8455 :
8456 : /*
8457 : CodeUnary - encode a unary arithmetic operation.
8458 : */
8459 :
8460 0 : static void CodeUnary (m2expr_BuildUnaryProcedure unop, tree ZConstToTypedConst, unsigned int quad, unsigned int result, unsigned int expr)
8461 : {
8462 0 : tree tv;
8463 0 : location_t location;
8464 :
8465 : /* firstly ensure that any constant literal is declared */
8466 0 : M2GCCDeclare_DeclareConstant (CurrentQuadToken, expr);
8467 0 : M2GCCDeclare_DeclareConstructor (CurrentQuadToken, quad, expr);
8468 0 : location = M2LexBuf_TokenToLocation (CurrentQuadToken);
8469 0 : tv = (*unop.proc) (location, M2GenGCC_LValueToGenericPtr (location, expr), false);
8470 0 : M2ALU_CheckOrResetOverflow (CurrentQuadToken, tv, M2Quads_MustCheckOverflow (quad));
8471 0 : if (SymbolTable_IsConst (result))
8472 : {
8473 0 : if (ZConstToTypedConst == ((tree) (NULL)))
8474 : {
8475 0 : ZConstToTypedConst = (tree) (SymbolConversion_Mod2Gcc (SymbolTable_GetType (expr)));
8476 : }
8477 : /* still have a constant which was not resolved, pass it to gcc */
8478 0 : SymbolTable_PutConst (result, FindType (expr));
8479 0 : M2GCCDeclare_ConstantKnownAndUsed (result, m2decl_DeclareKnownConstant (location, ZConstToTypedConst, tv));
8480 : }
8481 : else
8482 : {
8483 0 : if (M2SSA_EnableSSA && (SymbolTable_IsVariableSSA (result)))
8484 : {
8485 : Replace (result, tv);
8486 : }
8487 : else
8488 : {
8489 0 : m2statement_BuildAssignmentStatement (location, SymbolConversion_Mod2Gcc (result), tv);
8490 : }
8491 : }
8492 0 : }
8493 :
8494 :
8495 : /*
8496 : FoldNegate - check unary negate for constant folding.
8497 : */
8498 :
8499 39843 : static void FoldNegate (unsigned int tokenno, M2GCCDeclare_WalkAction p, unsigned int quad, unsigned int result, unsigned int expr)
8500 : {
8501 39843 : if (SymbolTable_IsConstSet (expr))
8502 : {
8503 60 : FoldUnarySet (tokenno, p, (M2GenGCC_ProcedureCardinal) {(M2GenGCC_ProcedureCardinal_t) M2ALU_SetNegate}, quad, result, expr);
8504 : }
8505 : else
8506 : {
8507 39783 : FoldUnary (tokenno, p, (m2expr_BuildUnaryProcedure) {(m2expr_BuildUnaryProcedure_t) m2expr_BuildNegate}, NULL, quad, result, expr);
8508 : }
8509 39843 : }
8510 :
8511 :
8512 : /*
8513 : CodeNegateChecked - code a negate instruction, determine whether checking
8514 : is required.
8515 : */
8516 :
8517 996 : static void CodeNegateChecked (unsigned int quad)
8518 : {
8519 996 : unsigned int operatorpos;
8520 996 : unsigned int resultpos;
8521 996 : unsigned int nopos;
8522 996 : unsigned int exprpos;
8523 996 : unsigned int result;
8524 996 : unsigned int noop;
8525 996 : unsigned int expr;
8526 996 : bool typeChecking;
8527 996 : bool constExpr;
8528 996 : bool overflowChecking;
8529 996 : M2Quads_QuadOperator op;
8530 :
8531 996 : M2Quads_GetQuadOTypetok (quad, &operatorpos, &op, &result, &noop, &expr, &overflowChecking, &typeChecking, &constExpr, &resultpos, &nopos, &exprpos);
8532 996 : if ((SymbolTable_IsConstSet (expr)) || (SymbolTable_IsSet (SymbolTable_GetType (expr))))
8533 : {
8534 78 : CodeUnarySet ((M2GenGCC_ProcedureCardinal) {(M2GenGCC_ProcedureCardinal_t) M2ALU_SetNegate}, (M2GenGCC_UnaryFunction) {(M2GenGCC_UnaryFunction_t) m2expr_BuildSetNegate}, operatorpos, NameKey_MakeKey ((const char *) "Not", 3), quad, result, expr);
8535 : }
8536 918 : else if (UnaryOperand (quad, expr))
8537 : {
8538 : /* avoid dangling else. */
8539 912 : if (M2Quads_MustCheckOverflow (quad))
8540 : {
8541 912 : CodeUnaryCheck ((m2expr_BuildUnaryCheckProcedure) {(m2expr_BuildUnaryCheckProcedure_t) m2expr_BuildNegateCheck}, NULL, quad, result, expr);
8542 : }
8543 : else
8544 : {
8545 0 : CodeUnary ((m2expr_BuildUnaryProcedure) {(m2expr_BuildUnaryProcedure_t) m2expr_BuildNegate}, NULL, quad, result, expr);
8546 : }
8547 : }
8548 996 : }
8549 :
8550 :
8551 : /*
8552 : FoldSize - check unary SIZE for constant folding.
8553 : */
8554 :
8555 7484 : static void FoldSize (unsigned int tokenno, M2GCCDeclare_WalkAction p, unsigned int quad, unsigned int op1, unsigned int op2, unsigned int op3)
8556 : {
8557 7484 : tree t;
8558 7484 : location_t location;
8559 :
8560 7484 : location = M2LexBuf_TokenToLocation (tokenno);
8561 7484 : if ((SymbolTable_IsConst (op1)) && (M2GCCDeclare_CompletelyResolved (op3)))
8562 : {
8563 : /* avoid gcc warning by using compound statement even if not strictly necessary. */
8564 6674 : if (op2 == SymbolTable_NulSym)
8565 : {
8566 6674 : t = m2expr_BuildSize (location, SymbolConversion_Mod2Gcc (op3), false);
8567 6674 : M2ALU_PushIntegerTree (t);
8568 6674 : SymbolTable_PopValue (op1);
8569 6674 : SymbolTable_PutConst (op1, M2Base_Cardinal);
8570 6674 : (*p.proc) (op1);
8571 6674 : NoChange = false;
8572 6674 : M2Quads_SubQuad (quad);
8573 6674 : t = m2block_RememberConstant (t);
8574 : }
8575 0 : else if (SymbolConversion_GccKnowsAbout (op2))
8576 : {
8577 : /* avoid dangling else. */
8578 : /* ignore the chosen varients as we implement it as a C union */
8579 0 : t = m2expr_BuildSize (location, SymbolConversion_Mod2Gcc (op3), false);
8580 0 : M2ALU_PushIntegerTree (t);
8581 0 : SymbolTable_PopValue (op1);
8582 0 : SymbolTable_PutConst (op1, M2Base_Cardinal);
8583 0 : (*p.proc) (op1);
8584 0 : NoChange = false;
8585 0 : M2Quads_SubQuad (quad);
8586 0 : t = m2block_RememberConstant (t);
8587 : }
8588 : }
8589 7484 : }
8590 :
8591 :
8592 : /*
8593 : CodeSize - encode the inbuilt SIZE function.
8594 : */
8595 :
8596 0 : static void CodeSize (unsigned int result, unsigned int sym)
8597 : {
8598 0 : location_t location;
8599 :
8600 0 : location = M2LexBuf_TokenToLocation (CurrentQuadToken);
8601 0 : M2ALU_PushIntegerTree (m2expr_BuildSize (location, SymbolConversion_Mod2Gcc (sym), false));
8602 0 : if (SymbolTable_IsConst (result))
8603 : {
8604 0 : SymbolTable_PopValue (result);
8605 0 : SymbolTable_PutConst (result, M2Base_Cardinal);
8606 0 : SymbolTable_PushValue (result);
8607 0 : M2GCCDeclare_ConstantKnownAndUsed (result, m2decl_DeclareKnownConstant (location, m2type_GetIntegerType (), M2ALU_PopIntegerTree ()));
8608 : }
8609 : else
8610 : {
8611 0 : m2statement_BuildAssignmentStatement (location, SymbolConversion_Mod2Gcc (result), M2ALU_PopIntegerTree ());
8612 : }
8613 0 : }
8614 :
8615 :
8616 : /*
8617 : FoldRecordField - check whether we can fold an RecordFieldOp quadruple.
8618 : Very similar to FoldBinary, except that we need to
8619 : hard code a few parameters to the gcc backend.
8620 : */
8621 :
8622 0 : static void FoldRecordField (unsigned int tokenno, M2GCCDeclare_WalkAction p, unsigned int quad, unsigned int result, unsigned int record, unsigned int field)
8623 : {
8624 0 : unsigned int recordType;
8625 0 : unsigned int fieldType;
8626 0 : tree ptr;
8627 0 : location_t location;
8628 :
8629 0 : return; /* this procedure should no longer be called */
8630 : location = M2LexBuf_TokenToLocation (tokenno);
8631 : /* firstly ensure that any constant literal is declared */
8632 : M2GCCDeclare_TryDeclareConstant (tokenno, record);
8633 : if ((SymbolTable_IsRecordField (record)) || (SymbolTable_IsFieldVarient (record)))
8634 : {
8635 : recordType = SymbolTable_GetType (record);
8636 : fieldType = SymbolTable_GetType (field);
8637 : if ((((((SymbolConversion_GccKnowsAbout (record)) && (SymbolConversion_GccKnowsAbout (field))) && (SymbolConversion_GccKnowsAbout (recordType))) && (SymbolConversion_GccKnowsAbout (fieldType))) && (M2GCCDeclare_CompletelyResolved (recordType))) && (M2GCCDeclare_CompletelyResolved (fieldType)))
8638 : {
8639 : /* avoid gcc warning by using compound statement even if not strictly necessary. */
8640 : /* fine, we can take advantage of this and fold constants */
8641 : if (SymbolTable_IsConst (result))
8642 : {
8643 : ptr = m2expr_BuildComponentRef (location, SymbolConversion_Mod2Gcc (record), SymbolConversion_Mod2Gcc (field));
8644 : if (! (SymbolTable_IsValueSolved (result)))
8645 : {
8646 : M2ALU_PushIntegerTree (ptr);
8647 : SymbolTable_PopValue (result);
8648 : }
8649 : SymbolTable_PutConst (result, fieldType);
8650 : SymbolConversion_AddModGcc (result, m2decl_DeclareKnownConstant (location, SymbolConversion_Mod2Gcc (fieldType), ptr));
8651 : (*p.proc) (result);
8652 : NoChange = false;
8653 : M2Quads_SubQuad (quad);
8654 : }
8655 : /* we can still fold the expression, but not the assignment, however, we will
8656 : not do this here but in CodeOffset
8657 : */
8658 : }
8659 : }
8660 : }
8661 :
8662 :
8663 : /*
8664 : CodeRecordField - encode a reference to a field within a record.
8665 : */
8666 :
8667 143644 : static void CodeRecordField (unsigned int result, unsigned int record, unsigned int field)
8668 : {
8669 143644 : unsigned int recordType;
8670 143644 : unsigned int fieldType;
8671 143644 : tree ptr;
8672 143644 : location_t location;
8673 :
8674 143644 : location = M2LexBuf_TokenToLocation (CurrentQuadToken);
8675 : /* firstly ensure that any constant literal is declared */
8676 143644 : if ((SymbolTable_IsRecordField (field)) || (SymbolTable_IsFieldVarient (field)))
8677 : {
8678 143644 : recordType = SymbolTable_GetType (record);
8679 143644 : fieldType = SymbolTable_GetType (field);
8680 143644 : if ((((((SymbolConversion_GccKnowsAbout (record)) && (SymbolConversion_GccKnowsAbout (field))) && (SymbolConversion_GccKnowsAbout (recordType))) && (SymbolConversion_GccKnowsAbout (fieldType))) && (M2GCCDeclare_CompletelyResolved (recordType))) && (M2GCCDeclare_CompletelyResolved (fieldType)))
8681 : {
8682 143644 : if ((SymbolTable_GetMode (record)) == SymbolTable_LeftValue)
8683 : {
8684 49518 : ptr = m2expr_BuildComponentRef (location, m2expr_BuildIndirect (location, SymbolConversion_Mod2Gcc (record), SymbolConversion_Mod2Gcc (recordType)), SymbolConversion_Mod2Gcc (field));
8685 : }
8686 : else
8687 : {
8688 94126 : ptr = m2expr_BuildComponentRef (location, SymbolConversion_Mod2Gcc (record), SymbolConversion_Mod2Gcc (field));
8689 : }
8690 143644 : SymbolConversion_AddModGcc (result, ptr);
8691 : }
8692 : else
8693 : {
8694 0 : M2Error_InternalError ((const char *) "symbol type should have been declared by now", 44);
8695 : }
8696 : }
8697 : else
8698 : {
8699 0 : M2Error_InternalError ((const char *) "not expecting this type of symbol", 33);
8700 : }
8701 143644 : }
8702 :
8703 :
8704 : /*
8705 : BuildHighFromChar -
8706 : */
8707 :
8708 51242 : static tree BuildHighFromChar (unsigned int operand)
8709 : {
8710 51242 : location_t location;
8711 :
8712 51242 : location = M2LexBuf_TokenToLocation (SymbolTable_GetDeclaredMod (operand));
8713 51242 : if ((SymbolTable_IsConstString (operand)) && ((SymbolTable_IsConstStringM2nul (operand)) || (SymbolTable_IsConstStringCnul (operand))))
8714 : {
8715 50174 : return m2expr_GetCardinalOne (location);
8716 : }
8717 1068 : return m2expr_GetCardinalZero (location);
8718 : /* static analysis guarentees a RETURN statement will be used before here. */
8719 : __builtin_unreachable ();
8720 : }
8721 :
8722 :
8723 : /*
8724 : SkipToArray -
8725 : */
8726 :
8727 21514 : static unsigned int SkipToArray (unsigned int operand, unsigned int dim)
8728 : {
8729 21514 : unsigned int type;
8730 :
8731 22162 : while (dim > 1)
8732 : {
8733 648 : type = SymbolTable_SkipType (SymbolTable_GetType (operand));
8734 648 : if (SymbolTable_IsArray (type))
8735 : {
8736 648 : operand = type;
8737 : }
8738 648 : dim -= 1;
8739 : }
8740 21514 : return operand;
8741 : /* static analysis guarentees a RETURN statement will be used before here. */
8742 : __builtin_unreachable ();
8743 : }
8744 :
8745 :
8746 : /*
8747 : BuildHighFromArray -
8748 : */
8749 :
8750 21514 : static tree BuildHighFromArray (unsigned int tokenno, unsigned int dim, unsigned int operand)
8751 : {
8752 21514 : unsigned int Type;
8753 21514 : location_t location;
8754 :
8755 21514 : location = M2LexBuf_TokenToLocation (tokenno);
8756 21514 : Type = SymbolTable_SkipType (SymbolTable_GetType (SkipToArray (operand, dim)));
8757 21514 : return BuildHighFromStaticArray (location, Type); /* dim, */
8758 : /* static analysis guarentees a RETURN statement will be used before here. */
8759 : __builtin_unreachable ();
8760 : }
8761 :
8762 :
8763 : /*
8764 : BuildHighFromSetArray -
8765 : */
8766 :
8767 3360 : static tree BuildHighFromSetArray (unsigned int tokenno, unsigned int settype)
8768 : {
8769 3360 : location_t location;
8770 :
8771 3360 : location = M2LexBuf_TokenToLocation (tokenno);
8772 3360 : return BuildHighFromStaticArray (location, SymbolTable_GetSetArray (settype));
8773 : /* static analysis guarentees a RETURN statement will be used before here. */
8774 : __builtin_unreachable ();
8775 : }
8776 :
8777 :
8778 : /*
8779 : BuildHighFromStaticArray -
8780 : */
8781 :
8782 24874 : static tree BuildHighFromStaticArray (location_t location, unsigned int Type)
8783 : {
8784 24874 : unsigned int High;
8785 24874 : unsigned int Low;
8786 24874 : unsigned int Subscript;
8787 24874 : unsigned int Subrange;
8788 :
8789 24874 : M2Debug_Assert (SymbolTable_IsArray (Type)); /* dim, */
8790 24874 : Subscript = SymbolTable_GetArraySubscript (Type);
8791 24874 : Subrange = SymbolTable_SkipType (SymbolTable_GetType (Subscript));
8792 24874 : if (SymbolTable_IsEnumeration (Subrange))
8793 : {
8794 : /* avoid dangling else. */
8795 96 : M2Base_GetBaseTypeMinMax (Subrange, &Low, &High);
8796 96 : if (SymbolConversion_GccKnowsAbout (High))
8797 : {
8798 96 : return (tree) (SymbolConversion_Mod2Gcc (High));
8799 : }
8800 : }
8801 24778 : else if (SymbolTable_IsSubrange (Subrange))
8802 : {
8803 : /* avoid dangling else. */
8804 24778 : SymbolTable_GetSubrange (Subrange, &High, &Low);
8805 24778 : if ((SymbolConversion_GccKnowsAbout (Low)) && (SymbolConversion_GccKnowsAbout (High)))
8806 : {
8807 24778 : return m2expr_BuildSub (location, SymbolConversion_Mod2Gcc (High), SymbolConversion_Mod2Gcc (Low), true);
8808 : }
8809 : }
8810 : else
8811 : {
8812 : /* avoid dangling else. */
8813 0 : M2MetaError_MetaError1 ((const char *) "array subscript {%1EDad:for} must be a subrange or enumeration type", 67, Type);
8814 0 : return (tree) (NULL);
8815 : }
8816 0 : if (SymbolConversion_GccKnowsAbout (High))
8817 : {
8818 0 : return (tree) (SymbolConversion_Mod2Gcc (High));
8819 : }
8820 : else
8821 : {
8822 : return (tree) (NULL);
8823 : }
8824 : /* static analysis guarentees a RETURN statement will be used before here. */
8825 : __builtin_unreachable ();
8826 : }
8827 :
8828 :
8829 : /*
8830 : BuildHighFromString -
8831 : */
8832 :
8833 904714 : static tree BuildHighFromString (unsigned int operand)
8834 : {
8835 904714 : location_t location;
8836 :
8837 904714 : location = M2LexBuf_TokenToLocation (SymbolTable_GetDeclaredMod (operand));
8838 904714 : if ((SymbolConversion_GccKnowsAbout (operand)) && ((m2expr_StringLength (SymbolConversion_Mod2Gcc (operand))) > 0))
8839 : {
8840 904714 : return m2decl_BuildIntegerConstant (static_cast<int> ((m2expr_StringLength (SymbolConversion_Mod2Gcc (operand)))-1));
8841 : }
8842 : else
8843 : {
8844 0 : return m2expr_GetIntegerZero (location);
8845 : }
8846 : /* static analysis guarentees a RETURN statement will be used before here. */
8847 : __builtin_unreachable ();
8848 : }
8849 :
8850 :
8851 : /*
8852 : ResolveHigh - given an Modula-2 operand, it resolves the HIGH(operand)
8853 : and returns a GCC constant symbol containing the value of
8854 : HIGH(operand).
8855 : */
8856 :
8857 988252 : static tree ResolveHigh (unsigned int tokenno, unsigned int dim, unsigned int operand)
8858 : {
8859 988252 : unsigned int Type;
8860 988252 : location_t location;
8861 :
8862 988252 : Type = SymbolTable_SkipType (SymbolTable_GetType (operand));
8863 988252 : location = M2LexBuf_TokenToLocation (tokenno);
8864 988252 : if ((Type == M2Base_Char) && (dim == 1))
8865 : {
8866 51242 : return BuildHighFromChar (operand);
8867 : }
8868 937010 : else if ((SymbolTable_IsConstString (operand)) && (dim == 1))
8869 : {
8870 : /* avoid dangling else. */
8871 904714 : return BuildHighFromString (operand);
8872 : }
8873 32296 : else if (SymbolTable_IsArray (Type))
8874 : {
8875 : /* avoid dangling else. */
8876 21514 : return BuildHighFromArray (tokenno, dim, operand);
8877 : }
8878 10782 : else if (SymbolTable_IsSet (Type))
8879 : {
8880 : /* avoid dangling else. */
8881 3360 : return BuildHighFromSetArray (tokenno, Type);
8882 : }
8883 7422 : else if (SymbolTable_IsUnbounded (Type))
8884 : {
8885 : /* avoid dangling else. */
8886 7422 : return M2GenGCC_GetHighFromUnbounded (location, dim, operand);
8887 : }
8888 : else
8889 : {
8890 : /* avoid dangling else. */
8891 0 : M2MetaError_MetaErrorT1 (tokenno, (const char *) "base procedure HIGH expects a variable of type array or a constant string or CHAR as its parameter, rather than {%1Etad}", 120, operand);
8892 0 : return m2expr_GetIntegerZero (location);
8893 : }
8894 : /* static analysis guarentees a RETURN statement will be used before here. */
8895 : __builtin_unreachable ();
8896 : }
8897 :
8898 :
8899 : /*
8900 : IsUnboundedArray - return TRUE if symbol is an unbounded array.
8901 : */
8902 :
8903 1235639 : static bool IsUnboundedArray (unsigned int sym)
8904 : {
8905 1235639 : if ((SymbolTable_IsParameter (sym)) || (SymbolTable_IsVar (sym)))
8906 : {
8907 304018 : return SymbolTable_IsUnbounded (SymbolTable_GetType (sym));
8908 : }
8909 : return false;
8910 : /* static analysis guarentees a RETURN statement will be used before here. */
8911 : __builtin_unreachable ();
8912 : }
8913 :
8914 :
8915 : /*
8916 : FoldHigh - if the array is not dynamic then we should be able to
8917 : remove the HighOp quadruple and assign op1 with
8918 : the known compile time HIGH(array).
8919 : */
8920 :
8921 1235639 : static void FoldHigh (unsigned int tokenno, M2GCCDeclare_WalkAction p, unsigned int quad, unsigned int op1, unsigned int dim, unsigned int array)
8922 : {
8923 1235639 : tree t;
8924 1235639 : location_t location;
8925 :
8926 : /* Firstly ensure that any constant literal is declared. */
8927 1235639 : M2GCCDeclare_TryDeclareConstant (tokenno, array);
8928 1235639 : location = M2LexBuf_TokenToLocation (tokenno);
8929 1235639 : if (((! (IsUnboundedArray (array))) && (SymbolConversion_GccKnowsAbout (array))) && (M2GCCDeclare_CompletelyResolved (array)))
8930 : {
8931 944987 : t = ResolveHigh (tokenno, dim, array);
8932 : /* We can take advantage of this and fold constants. */
8933 944987 : if ((SymbolTable_IsConst (op1)) && (t != ((tree) (NULL))))
8934 : {
8935 210 : SymbolTable_PutConst (op1, M2Base_Cardinal);
8936 210 : SymbolConversion_AddModGcc (op1, m2decl_DeclareKnownConstant (location, m2type_GetCardinalType (), m2convert_ToCardinal (location, t)));
8937 210 : (*p.proc) (op1);
8938 210 : NoChange = false;
8939 210 : M2Quads_SubQuad (quad);
8940 : }
8941 : /* We can still fold the expression but not the assignment,
8942 : we will not do this here but in CodeHigh when the result
8943 : can be stored. */
8944 : }
8945 1235639 : }
8946 :
8947 :
8948 : /*
8949 : CodeHigh - encode a unary arithmetic operation.
8950 : */
8951 :
8952 39905 : static void CodeHigh (unsigned int result, unsigned int dim, unsigned int array)
8953 : {
8954 39905 : location_t location;
8955 :
8956 39905 : location = M2LexBuf_TokenToLocation (CurrentQuadToken);
8957 : /* Firstly ensure that any constant literal is declared. */
8958 39905 : M2GCCDeclare_DeclareConstant (CurrentQuadToken, array);
8959 39905 : if (SymbolTable_IsConst (result))
8960 : {
8961 : /* Still have a constant which was not resolved, pass it to gcc. */
8962 24 : M2GCCDeclare_ConstantKnownAndUsed (result, m2decl_DeclareKnownConstant (location, m2type_GetM2ZType (), ResolveHigh (CurrentQuadToken, dim, array)));
8963 : }
8964 : else
8965 : {
8966 39881 : m2statement_BuildAssignmentStatement (location, SymbolConversion_Mod2Gcc (result), m2convert_BuildConvert (location, SymbolConversion_Mod2Gcc (SymbolTable_GetType (result)), ResolveHigh (CurrentQuadToken, dim, array), false));
8967 : }
8968 39905 : }
8969 :
8970 :
8971 : /*
8972 : CodeUnbounded - codes the creation of an unbounded parameter variable.
8973 : result = &array. array can be an lvalue or rvalue.
8974 : */
8975 :
8976 34561 : static void CodeUnbounded (unsigned int result, unsigned int array)
8977 : {
8978 34561 : tree Addr;
8979 34561 : location_t location;
8980 :
8981 34561 : location = M2LexBuf_TokenToLocation (CurrentQuadToken);
8982 34561 : M2GCCDeclare_DeclareConstant (CurrentQuadToken, array);
8983 34561 : if ((SymbolTable_IsConstString (array)) || ((SymbolTable_IsConst (array)) && ((SymbolTable_GetSType (array)) == M2Base_Char)))
8984 : {
8985 25529 : m2statement_BuildAssignmentStatement (location, SymbolConversion_Mod2Gcc (result), m2expr_BuildAddr (location, M2GCCDeclare_PromoteToString (CurrentQuadToken, array), false));
8986 : }
8987 9032 : else if (SymbolTable_IsConstructor (array))
8988 : {
8989 : /* avoid dangling else. */
8990 12 : m2statement_BuildAssignmentStatement (location, SymbolConversion_Mod2Gcc (result), m2expr_BuildAddr (location, SymbolConversion_Mod2Gcc (array), true));
8991 : }
8992 9020 : else if (SymbolTable_IsUnbounded (SymbolTable_GetType (array)))
8993 : {
8994 : /* avoid dangling else. */
8995 4268 : if ((SymbolTable_GetMode (array)) == SymbolTable_LeftValue)
8996 : {
8997 : /* We already have the address of the array, convert it to type of result. */
8998 0 : Addr = m2convert_BuildConvert (location, SymbolConversion_Mod2Gcc (SymbolTable_GetType (result)), SymbolConversion_Mod2Gcc (array), false);
8999 : }
9000 : else
9001 : {
9002 : /* Access the address field from the unbounded record. */
9003 4268 : Addr = m2expr_BuildComponentRef (location, SymbolConversion_Mod2Gcc (array), SymbolConversion_Mod2Gcc (SymbolTable_GetUnboundedAddressOffset (SymbolTable_GetType (array))));
9004 : }
9005 : /* Store address in result. */
9006 4268 : m2statement_BuildAssignmentStatement (location, SymbolConversion_Mod2Gcc (result), Addr);
9007 : }
9008 4752 : else if ((SymbolTable_GetMode (array)) == SymbolTable_RightValue)
9009 : {
9010 : /* avoid dangling else. */
9011 : /* Static array, get the address and store into result. */
9012 4698 : m2statement_BuildAssignmentStatement (location, SymbolConversion_Mod2Gcc (result), m2expr_BuildAddr (location, SymbolConversion_Mod2Gcc (array), false));
9013 : }
9014 : else
9015 : {
9016 : /* avoid dangling else. */
9017 : /* Static array which is a left value, just copy the address into result. */
9018 54 : m2statement_BuildAssignmentStatement (location, SymbolConversion_Mod2Gcc (result), SymbolConversion_Mod2Gcc (array));
9019 : }
9020 34561 : }
9021 :
9022 :
9023 : /*
9024 : AreSubrangesKnown - returns TRUE if the subranges values used within, array, are known.
9025 : */
9026 :
9027 47900 : static bool AreSubrangesKnown (unsigned int array)
9028 : {
9029 47900 : unsigned int type;
9030 47900 : unsigned int subscript;
9031 47900 : unsigned int low;
9032 47900 : unsigned int high;
9033 :
9034 47900 : if (SymbolConversion_GccKnowsAbout (array))
9035 : {
9036 47900 : subscript = SymbolTable_GetArraySubscript (array);
9037 47900 : if (subscript == SymbolTable_NulSym)
9038 : {
9039 0 : M2Error_InternalError ((const char *) "not expecting a NulSym as a subscript", 37);
9040 : }
9041 : else
9042 : {
9043 47900 : type = SymbolTable_SkipType (SymbolTable_GetType (subscript));
9044 47900 : low = M2GCCDeclare_GetTypeMin (type);
9045 47900 : high = M2GCCDeclare_GetTypeMax (type);
9046 47900 : return (SymbolConversion_GccKnowsAbout (low)) && (SymbolConversion_GccKnowsAbout (high));
9047 : }
9048 : }
9049 : else
9050 : {
9051 : return false;
9052 : }
9053 : ReturnException ("/home/worker/buildworker/tiber-lcov/build/gcc/m2/gm2-compiler/M2GenGCC.def", 20, 1);
9054 : __builtin_unreachable ();
9055 : }
9056 :
9057 :
9058 : /*
9059 : CodeArray - res is an lvalue which will point to the array element.
9060 : */
9061 :
9062 47900 : static void CodeArray (unsigned int res, unsigned int index, unsigned int array)
9063 : {
9064 47900 : unsigned int resType;
9065 47900 : unsigned int arrayDecl;
9066 47900 : unsigned int type;
9067 47900 : unsigned int low;
9068 47900 : unsigned int subscript;
9069 47900 : tree a;
9070 47900 : tree ta;
9071 47900 : tree ti;
9072 47900 : tree tl;
9073 47900 : location_t location;
9074 :
9075 47900 : location = M2LexBuf_TokenToLocation (CurrentQuadToken);
9076 47900 : arrayDecl = SymbolTable_SkipType (SymbolTable_GetType (array));
9077 47900 : if (AreSubrangesKnown (arrayDecl))
9078 : {
9079 47900 : subscript = SymbolTable_GetArraySubscript (arrayDecl);
9080 47900 : type = SymbolTable_SkipType (SymbolTable_GetType (subscript));
9081 47900 : low = M2GCCDeclare_GetTypeMin (type);
9082 47900 : resType = SymbolTable_GetVarBackEndType (res);
9083 47900 : if (resType == SymbolTable_NulSym)
9084 : {
9085 0 : resType = SymbolTable_SkipType (SymbolTable_GetType (res));
9086 : }
9087 47900 : ta = SymbolConversion_Mod2Gcc (SymbolTable_SkipType (SymbolTable_GetType (arrayDecl)));
9088 47900 : if ((SymbolTable_GetMode (array)) == SymbolTable_LeftValue)
9089 : {
9090 1642 : a = m2expr_BuildIndirect (location, SymbolConversion_Mod2Gcc (array), SymbolConversion_Mod2Gcc (SymbolTable_SkipType (SymbolTable_GetType (array))));
9091 : }
9092 : else
9093 : {
9094 46258 : a = SymbolConversion_Mod2Gcc (array);
9095 : }
9096 47900 : if (SymbolTable_IsArrayLarge (arrayDecl))
9097 : {
9098 24 : tl = m2convert_BuildConvert (location, SymbolConversion_Mod2Gcc (type), SymbolConversion_Mod2Gcc (low), false);
9099 24 : ti = m2convert_BuildConvert (location, SymbolConversion_Mod2Gcc (type), SymbolConversion_Mod2Gcc (index), false);
9100 24 : ti = m2convert_BuildConvert (location, m2type_GetIntegerType (), m2expr_BuildSub (location, ti, tl, false), false);
9101 24 : tl = m2expr_GetIntegerZero (location);
9102 : }
9103 : else
9104 : {
9105 47876 : tl = m2convert_BuildConvert (location, m2type_GetIntegerType (), SymbolConversion_Mod2Gcc (low), false);
9106 47876 : ti = m2convert_BuildConvert (location, m2type_GetIntegerType (), SymbolConversion_Mod2Gcc (index), false);
9107 : }
9108 : /* ti := BuildConvert(location, GetIntegerType(), Mod2Gcc(high), FALSE) ; */
9109 47900 : m2statement_BuildAssignmentStatement (location, SymbolConversion_Mod2Gcc (res), m2convert_BuildConvert (location, SymbolConversion_Mod2Gcc (resType), m2expr_BuildAddr (location, m2expr_BuildArray (location, ta, a, ti, tl), false), false));
9110 : }
9111 : else
9112 : {
9113 0 : M2Error_InternalError ((const char *) "subranges not yet resolved", 26);
9114 : }
9115 47900 : }
9116 :
9117 :
9118 : /*
9119 : FoldElementSizeForArray - attempts to calculate the Subscript
9120 : multiplier for the index op3.
9121 : */
9122 :
9123 0 : static void FoldElementSizeForArray (unsigned int tokenno, unsigned int quad, M2GCCDeclare_WalkAction p, unsigned int result, unsigned int type)
9124 : {
9125 0 : unsigned int Subscript;
9126 0 : location_t location;
9127 :
9128 0 : location = M2LexBuf_TokenToLocation (tokenno);
9129 0 : if ((SymbolTable_IsConst (result)) && (! (SymbolConversion_GccKnowsAbout (result))))
9130 : {
9131 0 : Subscript = SymbolTable_GetArraySubscript (type);
9132 0 : if (SymbolTable_IsSizeSolved (Subscript))
9133 : {
9134 0 : SymbolTable_PutConst (result, M2Base_Integer);
9135 0 : SymbolTable_PushSize (Subscript);
9136 0 : SymbolConversion_AddModGcc (result, m2decl_DeclareKnownConstant (location, m2type_GetCardinalType (), m2convert_BuildConvert (location, m2type_GetCardinalType (), M2ALU_PopIntegerTree (), true)));
9137 0 : (*p.proc) (result);
9138 0 : NoChange = false;
9139 0 : M2Quads_SubQuad (quad);
9140 : }
9141 : }
9142 0 : }
9143 :
9144 :
9145 : /*
9146 : FoldElementSizeForUnbounded - Unbounded arrays only have one index,
9147 : therefore element size will be the
9148 : TSIZE(Type) where Type is defined as:
9149 : ARRAY OF Type.
9150 : */
9151 :
9152 10076 : static void FoldElementSizeForUnbounded (unsigned int tokenno, unsigned int quad, M2GCCDeclare_WalkAction p, unsigned int result, unsigned int ArrayType)
9153 : {
9154 10076 : unsigned int Type;
9155 10076 : location_t location;
9156 :
9157 10076 : location = M2LexBuf_TokenToLocation (tokenno);
9158 10076 : if (SymbolTable_IsConst (result))
9159 : {
9160 : /* avoid gcc warning by using compound statement even if not strictly necessary. */
9161 10076 : if (SymbolConversion_GccKnowsAbout (result))
9162 : {
9163 0 : M2Error_InternalError ((const char *) "cannot assign a value twice to a constant", 41);
9164 : }
9165 : else
9166 : {
9167 10076 : M2Debug_Assert (SymbolTable_IsUnbounded (ArrayType));
9168 10076 : Type = SymbolTable_GetType (ArrayType);
9169 10076 : if (SymbolConversion_GccKnowsAbout (Type))
9170 : {
9171 10076 : SymbolTable_PutConst (result, M2Base_Cardinal);
9172 10076 : SymbolConversion_AddModGcc (result, m2decl_DeclareKnownConstant (location, m2type_GetCardinalType (), m2convert_BuildConvert (location, m2type_GetCardinalType (), FindSize (tokenno, Type), true)));
9173 10076 : (*p.proc) (result);
9174 10076 : NoChange = false;
9175 10076 : M2Quads_SubQuad (quad);
9176 : }
9177 : }
9178 : }
9179 10076 : }
9180 :
9181 :
9182 : /*
9183 : FoldElementSize - folds the element size for an ArraySym or UnboundedSym.
9184 : ElementSize returns a constant which defines the
9185 : multiplier to be multiplied by this element index.
9186 : */
9187 :
9188 10076 : static void FoldElementSize (unsigned int tokenno, M2GCCDeclare_WalkAction p, unsigned int quad, unsigned int result, unsigned int type)
9189 : {
9190 10076 : if (SymbolTable_IsUnbounded (type))
9191 : {
9192 10076 : FoldElementSizeForUnbounded (tokenno, quad, p, result, type);
9193 : }
9194 0 : else if (SymbolTable_IsArray (type))
9195 : {
9196 : /* avoid dangling else. */
9197 0 : FoldElementSizeForArray (tokenno, quad, p, result, type);
9198 : }
9199 : else
9200 : {
9201 : /* avoid dangling else. */
9202 0 : M2Error_InternalError ((const char *) "expecting UnboundedSym or ArraySym", 34);
9203 : }
9204 10076 : }
9205 :
9206 :
9207 : /*
9208 : PopKindTree - returns a Tree from M2ALU of the type implied by, op.
9209 : */
9210 :
9211 20364 : static tree PopKindTree (unsigned int op, unsigned int tokenno)
9212 : {
9213 20364 : unsigned int type;
9214 :
9215 20364 : if ((SymbolTable_IsConst (op)) && (SymbolTable_IsConstString (op)))
9216 : {
9217 : /* Converting a nul char or char for example. */
9218 1852 : return M2ALU_PopIntegerTree ();
9219 : }
9220 : else
9221 : {
9222 18512 : type = SymbolTable_SkipType (SymbolTable_GetType (op));
9223 18512 : if (SymbolTable_IsSet (type))
9224 : {
9225 0 : return M2ALU_PopSetTree (tokenno);
9226 : }
9227 18512 : else if (M2Base_IsRealType (type))
9228 : {
9229 : /* avoid dangling else. */
9230 66 : return M2ALU_PopRealTree ();
9231 : }
9232 : else
9233 : {
9234 : /* avoid dangling else. */
9235 18446 : return M2ALU_PopIntegerTree ();
9236 : }
9237 : }
9238 : /* static analysis guarentees a RETURN statement will be used before here. */
9239 : __builtin_unreachable ();
9240 : }
9241 :
9242 :
9243 : /*
9244 : FoldConvert - attempts to fold expr to type into result
9245 : providing that result and expr are constants.
9246 : If required convert will alter the machine representation
9247 : of expr to comply with type.
9248 : */
9249 :
9250 361350 : static void FoldConvert (unsigned int tokenno, M2GCCDeclare_WalkAction p, unsigned int quad, unsigned int result, unsigned int type, unsigned int expr)
9251 : {
9252 361350 : tree tl;
9253 361350 : location_t location;
9254 :
9255 361350 : location = M2LexBuf_TokenToLocation (tokenno);
9256 : /* First ensure that constant literals are declared. */
9257 361350 : M2GCCDeclare_TryDeclareConstant (tokenno, expr);
9258 361350 : if (IsConstant (expr))
9259 : {
9260 203012 : if (((SymbolConversion_GccKnowsAbout (type)) && ((SymbolTable_IsProcedure (expr)) || (SymbolTable_IsValueSolved (expr)))) && (SymbolConversion_GccKnowsAbout (SymbolTable_SkipType (type))))
9261 : {
9262 : /* The type is known and expr is resolved so fold the convert. */
9263 197642 : if (SymbolTable_IsConst (result))
9264 : {
9265 6892 : SymbolTable_PutConst (result, type); /* Change result type just in case. */
9266 6892 : tl = SymbolConversion_Mod2Gcc (SymbolTable_SkipType (type)); /* Change result type just in case. */
9267 6892 : if (SymbolTable_IsProcedure (expr))
9268 : {
9269 0 : SymbolConversion_AddModGcc (result, m2convert_BuildConvert (location, tl, SymbolConversion_Mod2Gcc (expr), true));
9270 : }
9271 : else
9272 : {
9273 6892 : SymbolTable_PushValue (expr);
9274 6892 : if (SymbolTable_IsConstSet (expr))
9275 : {
9276 84 : if (SymbolTable_IsSet (SymbolTable_SkipType (type)))
9277 : {
9278 0 : M2Error_WriteFormat0 ((const char *) "cannot convert values between sets", 34);
9279 : }
9280 : else
9281 : {
9282 84 : M2ALU_PushIntegerTree (m2expr_FoldAndStrip (m2convert_BuildConvert (location, tl, M2ALU_PopSetTree (tokenno), true)));
9283 84 : SymbolTable_PopValue (result);
9284 84 : SymbolTable_PushValue (result);
9285 84 : SymbolConversion_AddModGcc (result, M2ALU_PopIntegerTree ());
9286 : }
9287 : }
9288 : else
9289 : {
9290 6808 : if (SymbolTable_IsSet (SymbolTable_SkipType (type)))
9291 : {
9292 0 : M2ALU_PushSetTree (tokenno, m2expr_FoldAndStrip (m2convert_BuildConvert (location, tl, PopKindTree (expr, tokenno), true)), SymbolTable_SkipType (type));
9293 0 : SymbolTable_PopValue (result);
9294 0 : SymbolTable_PutConstSet (result);
9295 0 : SymbolTable_PushValue (result);
9296 0 : SymbolConversion_AddModGcc (result, M2ALU_PopSetTree (tokenno));
9297 : }
9298 6808 : else if (M2Base_IsRealType (SymbolTable_SkipType (type)))
9299 : {
9300 : /* avoid dangling else. */
9301 60 : M2ALU_PushRealTree (m2expr_FoldAndStrip (m2convert_BuildConvert (location, tl, PopKindTree (expr, tokenno), true)));
9302 60 : SymbolTable_PopValue (result);
9303 60 : SymbolTable_PushValue (result);
9304 60 : SymbolConversion_AddModGcc (result, PopKindTree (result, tokenno));
9305 : }
9306 : else
9307 : {
9308 : /* avoid dangling else. */
9309 : /* Let CheckOverflow catch a potential overflow rather than BuildConvert. */
9310 6748 : M2ALU_PushIntegerTree (m2expr_FoldAndStrip (m2convert_BuildConvert (location, tl, PopKindTree (expr, tokenno), false)));
9311 6748 : SymbolTable_PopValue (result);
9312 6748 : SymbolTable_PushValue (result);
9313 6748 : M2ALU_CheckOrResetOverflow (tokenno, PopKindTree (result, tokenno), M2Quads_MustCheckOverflow (quad));
9314 6748 : SymbolTable_PushValue (result);
9315 6748 : SymbolConversion_AddModGcc (result, PopKindTree (result, tokenno));
9316 : }
9317 : }
9318 : }
9319 6892 : (*p.proc) (result);
9320 6892 : NoChange = false;
9321 6892 : M2Quads_SubQuad (quad);
9322 : }
9323 : }
9324 : }
9325 361350 : }
9326 :
9327 :
9328 : /*
9329 : CodeConvert - Converts, rhs, to, type, placing the result into lhs.
9330 : Convert will, if need be, alter the machine representation
9331 : of op3 to comply with TYPE op2.
9332 : */
9333 :
9334 51902 : static void CodeConvert (unsigned int quad, unsigned int lhs, unsigned int type, unsigned int rhs)
9335 : {
9336 51902 : tree tl;
9337 51902 : tree tr;
9338 51902 : location_t location;
9339 :
9340 : /* Firstly ensure that constant literals are declared. */
9341 51902 : M2GCCDeclare_DeclareConstant (CurrentQuadToken, rhs);
9342 51902 : M2GCCDeclare_DeclareConstructor (CurrentQuadToken, quad, rhs);
9343 51902 : location = M2LexBuf_TokenToLocation (CurrentQuadToken);
9344 51902 : tl = M2GenGCC_LValueToGenericPtr (location, type);
9345 51902 : if (SymbolTable_IsProcedure (rhs))
9346 : {
9347 31854 : tr = m2expr_BuildAddr (location, SymbolConversion_Mod2Gcc (rhs), false);
9348 : }
9349 : else
9350 : {
9351 20048 : tr = M2GenGCC_LValueToGenericPtr (location, rhs);
9352 20048 : tr = ConvertRHS (tr, type, rhs);
9353 : }
9354 51902 : if (SymbolTable_IsConst (lhs))
9355 : {
9356 : /* Fine, we can take advantage of this and fold constant. */
9357 0 : SymbolTable_PutConst (lhs, type);
9358 0 : tl = SymbolConversion_Mod2Gcc (SymbolTable_SkipType (type));
9359 0 : M2GCCDeclare_ConstantKnownAndUsed (lhs, m2convert_BuildConvert (location, tl, SymbolConversion_Mod2Gcc (rhs), true));
9360 : }
9361 : else
9362 : {
9363 51902 : m2statement_BuildAssignmentStatement (location, SymbolConversion_Mod2Gcc (lhs), m2convert_BuildConvert (location, tl, tr, true));
9364 : }
9365 51902 : }
9366 :
9367 :
9368 : /*
9369 : CodeCoerce - Coerce op3 to type op2 placing the result into
9370 : op1.
9371 : Coerce will NOT alter the machine representation
9372 : of op3 to comply with TYPE op2.
9373 : Therefore it _insists_ that under all circumstances that the
9374 : type sizes of op1 and op3 are the same.
9375 : CONVERT will perform machine manipulation to change variable
9376 : types, coerce does no such thing.
9377 : */
9378 :
9379 1428 : static void CodeCoerce (unsigned int quad, unsigned int op1, unsigned int op2, unsigned int op3)
9380 : {
9381 1428 : location_t location;
9382 :
9383 1428 : M2GCCDeclare_DeclareConstant (CurrentQuadToken, op3); /* checks to see whether it is a constant literal and declares it */
9384 1428 : M2GCCDeclare_DeclareConstructor (CurrentQuadToken, quad, op3); /* checks to see whether it is a constant literal and declares it */
9385 1428 : location = M2LexBuf_TokenToLocation (CurrentQuadToken);
9386 1428 : if (SymbolTable_IsProcedure (op3))
9387 : {
9388 0 : if (m2expr_AreConstantsEqual (FindSize (CurrentQuadToken, op1), FindSize (CurrentQuadToken, M2System_Address)))
9389 : {
9390 0 : if (SymbolTable_IsConst (op1))
9391 : {
9392 0 : M2GCCDeclare_ConstantKnownAndUsed (op1, CheckConstant (CurrentQuadToken, op1, op3));
9393 : }
9394 : else
9395 : {
9396 0 : m2statement_BuildAssignmentStatement (location, SymbolConversion_Mod2Gcc (op1), SymbolConversion_Mod2Gcc (op3));
9397 : }
9398 : }
9399 : else
9400 : {
9401 0 : M2MetaError_MetaErrorT0 (CurrentQuadToken, (const char *) "{%E}procedure address can only be stored in an address sized operand", 68);
9402 : }
9403 : }
9404 1428 : else if ((SymbolTable_IsConst (op3)) || (m2expr_AreConstantsEqual (FindSize (CurrentQuadToken, op1), FindSize (CurrentQuadToken, op3))))
9405 : {
9406 : /* avoid dangling else. */
9407 1428 : if (SymbolTable_IsConst (op1))
9408 : {
9409 0 : M2GCCDeclare_ConstantKnownAndUsed (op1, m2decl_DeclareKnownConstant (location, SymbolConversion_Mod2Gcc (SymbolTable_GetType (op1)), SymbolConversion_Mod2Gcc (op3)));
9410 : }
9411 : else
9412 : {
9413 1428 : M2Debug_Assert (SymbolConversion_GccKnowsAbout (op2));
9414 1428 : if (SymbolTable_IsConst (op3))
9415 : {
9416 0 : m2statement_BuildAssignmentStatement (location, SymbolConversion_Mod2Gcc (op1), SymbolConversion_Mod2Gcc (op3));
9417 : }
9418 : else
9419 : {
9420 : /* does not work t := BuildCoerce(Mod2Gcc(op1), Mod2Gcc(op2), Mod2Gcc(op3)) */
9421 1428 : checkDeclare (op1);
9422 1428 : m2type_AddStatement (location, MaybeDebugBuiltinMemcpy (location, m2expr_BuildAddr (location, SymbolConversion_Mod2Gcc (op1), false), m2expr_BuildAddr (location, SymbolConversion_Mod2Gcc (op3), false), FindSize (CurrentQuadToken, op2)));
9423 : }
9424 : }
9425 : }
9426 : else
9427 : {
9428 : /* avoid dangling else. */
9429 0 : M2MetaError_MetaErrorT0 (CurrentQuadToken, (const char *) "can only {%kCAST} objects of the same size", 42);
9430 : }
9431 1428 : }
9432 :
9433 :
9434 : /*
9435 : FoldCoerce -
9436 : */
9437 :
9438 12194 : static void FoldCoerce (unsigned int tokenno, M2GCCDeclare_WalkAction p, unsigned int quad, unsigned int op1, unsigned int op2, unsigned int op3)
9439 : {
9440 12194 : location_t location;
9441 :
9442 12194 : M2GCCDeclare_TryDeclareConstant (tokenno, op3); /* checks to see whether it is a constant literal and declares it */
9443 12194 : location = M2LexBuf_TokenToLocation (tokenno); /* checks to see whether it is a constant literal and declares it */
9444 12194 : if ((SymbolConversion_GccKnowsAbout (op2)) && (SymbolConversion_GccKnowsAbout (op3)))
9445 : {
9446 : /* avoid gcc warning by using compound statement even if not strictly necessary. */
9447 2214 : if (SymbolTable_IsProcedure (op3))
9448 : {
9449 0 : if (m2expr_AreConstantsEqual (FindSize (tokenno, op1), FindSize (tokenno, M2System_Address)))
9450 : {
9451 : /* avoid dangling else. */
9452 0 : if (SymbolTable_IsConst (op1))
9453 : {
9454 0 : SymbolConversion_AddModGcc (op1, m2decl_DeclareKnownConstant (location, SymbolConversion_Mod2Gcc (SymbolTable_GetType (op1)), SymbolConversion_Mod2Gcc (op3)));
9455 0 : (*p.proc) (op1);
9456 0 : NoChange = false;
9457 0 : M2Quads_SubQuad (quad);
9458 : }
9459 : }
9460 : else
9461 : {
9462 0 : M2MetaError_MetaErrorT0 (CurrentQuadToken, (const char *) "{%E}procedure address can only be stored in a address sized operand", 67);
9463 : }
9464 : }
9465 2214 : else if (SymbolTable_IsConst (op3))
9466 : {
9467 : /* avoid dangling else. */
9468 1248 : if (SymbolTable_IsConst (op1))
9469 : {
9470 1248 : SymbolConversion_AddModGcc (op1, m2decl_DeclareKnownConstant (location, SymbolConversion_Mod2Gcc (SymbolTable_GetType (op1)), SymbolConversion_Mod2Gcc (op3)));
9471 1248 : (*p.proc) (op1);
9472 1248 : NoChange = false;
9473 1248 : M2Quads_SubQuad (quad);
9474 : }
9475 : }
9476 : }
9477 12194 : }
9478 :
9479 :
9480 : /*
9481 : CanConvert - returns TRUE if we can convert variable, var, to a, type.
9482 : */
9483 :
9484 0 : static bool CanConvert (unsigned int type, unsigned int var)
9485 : {
9486 0 : unsigned int svar;
9487 0 : unsigned int stype;
9488 :
9489 0 : stype = SymbolTable_SkipType (type);
9490 0 : svar = SymbolTable_SkipType (SymbolTable_GetType (var));
9491 0 : return (((M2Base_IsBaseType (stype)) || (M2Base_IsOrdinalType (stype))) || (M2System_IsSystemType (stype))) && (((M2Base_IsBaseType (svar)) || (M2Base_IsOrdinalType (svar))) || (M2System_IsSystemType (stype)));
9492 : /* static analysis guarentees a RETURN statement will be used before here. */
9493 : __builtin_unreachable ();
9494 : }
9495 :
9496 :
9497 : /*
9498 : CodeCast - Cast op3 to type op2 placing the result into op1.
9499 : Cast will NOT alter the machine representation
9500 : of op3 to comply with TYPE op2 as long as SIZE(op3)=SIZE(op2).
9501 : If the sizes differ then Convert is called.
9502 : */
9503 :
9504 126 : static void CodeCast (unsigned int quad, unsigned int op1, unsigned int op2, unsigned int op3)
9505 : {
9506 126 : location_t location;
9507 :
9508 126 : M2GCCDeclare_DeclareConstant (CurrentQuadToken, op3); /* checks to see whether it is a constant literal and declares it */
9509 126 : M2GCCDeclare_DeclareConstructor (CurrentQuadToken, quad, op3); /* checks to see whether it is a constant literal and declares it */
9510 126 : location = M2LexBuf_TokenToLocation (CurrentQuadToken);
9511 126 : if (SymbolTable_IsProcedure (op3))
9512 : {
9513 0 : if (m2expr_AreConstantsEqual (FindSize (CurrentQuadToken, op1), FindSize (CurrentQuadToken, M2System_Address)))
9514 : {
9515 0 : if (SymbolTable_IsConst (op1))
9516 : {
9517 0 : M2GCCDeclare_ConstantKnownAndUsed (op1, CheckConstant (CurrentQuadToken, op1, op3));
9518 : }
9519 : else
9520 : {
9521 0 : m2statement_BuildAssignmentStatement (location, SymbolConversion_Mod2Gcc (op1), SymbolConversion_Mod2Gcc (op3));
9522 : }
9523 : }
9524 : else
9525 : {
9526 0 : M2MetaError_MetaErrorT0 (CurrentQuadToken, (const char *) "{%E}procedure address can only be stored in an address sized operand", 68);
9527 : }
9528 : }
9529 126 : else if ((SymbolTable_IsConst (op3)) || (m2expr_AreConstantsEqual (FindSize (CurrentQuadToken, op1), FindSize (CurrentQuadToken, op3))))
9530 : {
9531 : /* avoid dangling else. */
9532 108 : CodeCoerce (quad, op1, op2, op3);
9533 : }
9534 : else
9535 : {
9536 : /* avoid dangling else. */
9537 18 : if (M2Options_PedanticCast && (! (CanConvert (op2, op3))))
9538 : {
9539 0 : M2MetaError_MetaError2 ((const char *) "{%WkCAST} cannot copy a variable src {%2Dad} to a destination {%1Dad} as they are of different sizes and are not ordinal or real types", 134, op1, op3);
9540 : }
9541 18 : CodeConvert (quad, op1, op2, op3);
9542 : }
9543 126 : }
9544 :
9545 1500 : static void FoldCast (unsigned int tokenno, M2GCCDeclare_WalkAction p, unsigned int quad, unsigned int op1, unsigned int op2, unsigned int op3)
9546 : {
9547 : /*
9548 : FoldCoerce -
9549 : */
9550 1500 : M2GCCDeclare_TryDeclareConstant (tokenno, op3); /* checks to see whether it is a constant literal and declares it */
9551 1500 : if ((SymbolConversion_GccKnowsAbout (op2)) && (SymbolConversion_GccKnowsAbout (op3))) /* checks to see whether it is a constant literal and declares it */
9552 : {
9553 : /* avoid gcc warning by using compound statement even if not strictly necessary. */
9554 234 : if (SymbolTable_IsProcedure (op3))
9555 : {
9556 0 : if (m2expr_AreConstantsEqual (FindSize (tokenno, op1), FindSize (tokenno, M2System_Address)))
9557 : {
9558 0 : FoldCoerce (tokenno, p, quad, op1, op2, op3);
9559 : }
9560 : else
9561 : {
9562 0 : M2MetaError_MetaErrorT0 (tokenno, (const char *) "{%E}procedure address can only be stored in an address sized operand", 68);
9563 : }
9564 : }
9565 234 : else if (SymbolTable_IsConst (op3))
9566 : {
9567 : /* avoid dangling else. */
9568 0 : FoldCoerce (tokenno, p, quad, op1, op2, op3);
9569 : }
9570 : }
9571 1500 : }
9572 :
9573 :
9574 : /*
9575 : CreateLabelProcedureN - creates a label using procedure name and
9576 : an integer.
9577 : */
9578 :
9579 0 : static DynamicStrings_String CreateLabelProcedureN (unsigned int proc, const char *leader_, unsigned int _leader_high, unsigned int unboundedCount, unsigned int n)
9580 : {
9581 0 : DynamicStrings_String n1;
9582 0 : DynamicStrings_String n2;
9583 0 : char leader[_leader_high+1];
9584 :
9585 : /* make a local copy of each unbounded array. */
9586 0 : memcpy (leader, leader_, _leader_high+1);
9587 :
9588 0 : n1 = DynamicStrings_Mark (DynamicStrings_InitStringCharStar (NameKey_KeyToCharStar (SymbolTable_GetSymName (proc))));
9589 0 : n2 = DynamicStrings_Mark (DynamicStrings_InitString ((const char *) leader, _leader_high));
9590 : /* prefixed by .L unboundedCount and n to ensure that no Modula-2 identifiers clash */
9591 0 : return FormatStrings_Sprintf4 (DynamicStrings_Mark (DynamicStrings_InitString ((const char *) ".L%d.%d.unbounded.%s.%s", 23)), (const unsigned char *) &unboundedCount, (sizeof (unboundedCount)-1), (const unsigned char *) &n, (sizeof (n)-1), (const unsigned char *) &n1, (sizeof (n1)-1), (const unsigned char *) &n2, (sizeof (n2)-1));
9592 : /* static analysis guarentees a RETURN statement will be used before here. */
9593 : __builtin_unreachable ();
9594 0 : }
9595 :
9596 :
9597 : /*
9598 : CreateLabelName - creates a namekey from quadruple, q.
9599 : */
9600 :
9601 231916 : static DynamicStrings_String CreateLabelName (unsigned int q)
9602 : {
9603 : /* Prefixed by . to ensure that no Modula-2 identifiers clash */
9604 231916 : return FormatStrings_Sprintf1 (DynamicStrings_Mark (DynamicStrings_InitString ((const char *) ".L%d", 4)), (const unsigned char *) &q, (sizeof (q)-1));
9605 : /* static analysis guarentees a RETURN statement will be used before here. */
9606 : __builtin_unreachable ();
9607 : }
9608 :
9609 :
9610 : /*
9611 : CodeGoto - creates a jump to a labeled quadruple.
9612 : */
9613 :
9614 46253 : static void CodeGoto (unsigned int destquad)
9615 : {
9616 46253 : location_t location;
9617 :
9618 46253 : location = M2LexBuf_TokenToLocation (CurrentQuadToken);
9619 46253 : m2statement_BuildGoto (location, reinterpret_cast <char * > (DynamicStrings_string (CreateLabelName (destquad))));
9620 46253 : }
9621 :
9622 :
9623 : /*
9624 : CheckReferenced - checks to see whether this quadruple requires a label.
9625 : */
9626 :
9627 4311506 : static void CheckReferenced (unsigned int quad, M2Quads_QuadOperator op)
9628 : {
9629 4311506 : location_t location;
9630 :
9631 4311506 : location = M2LexBuf_TokenToLocation (CurrentQuadToken);
9632 : /* We do not create labels for procedure entries. */
9633 4311506 : if (((op != M2Quads_ProcedureScopeOp) && (op != M2Quads_NewLocalVarOp)) && (M2Quads_IsReferenced (quad)))
9634 : {
9635 105948 : m2statement_DeclareLabel (location, reinterpret_cast <char * > (DynamicStrings_string (CreateLabelName (quad))));
9636 : }
9637 4311506 : }
9638 :
9639 :
9640 : /*
9641 : CodeIfSetCondition - code IF left cond right then destquad for set types.
9642 : */
9643 :
9644 18 : static void CodeIfSetCondition (unsigned int tokenno, unsigned int left, unsigned int right, unsigned int destquad, M2GenGCC_BinaryFunction cond, NameKey_Name procedurename)
9645 : {
9646 18 : unsigned int settype;
9647 18 : location_t location;
9648 18 : tree expr;
9649 :
9650 18 : location = M2LexBuf_TokenToLocation (tokenno);
9651 18 : if ((SymbolTable_IsConst (left)) && (SymbolTable_IsConst (right)))
9652 : {
9653 0 : M2Error_InternalError ((const char *) "this should have been folded in the calling procedure", 53);
9654 : }
9655 18 : else if (SymbolTable_IsConst (left))
9656 : {
9657 : /* avoid dangling else. */
9658 0 : settype = SymbolTable_SkipType (SymbolTable_GetType (right));
9659 : }
9660 : else
9661 : {
9662 : /* avoid dangling else. */
9663 18 : settype = SymbolTable_SkipType (SymbolTable_GetType (left));
9664 : }
9665 18 : if (SymbolTable_GetSetInWord (settype))
9666 : {
9667 : /* WORD size sets. */
9668 0 : expr = (*cond.proc) (location, m2convert_BuildConvert (location, m2type_GetWordType (), SymbolConversion_Mod2Gcc (left), false), m2convert_BuildConvert (location, m2type_GetWordType (), SymbolConversion_Mod2Gcc (right), false));
9669 : }
9670 : else
9671 : {
9672 18 : expr = CallSetWideBoolFunction (location, tokenno, procedurename, settype, left, right);
9673 : }
9674 18 : m2statement_IfExprJump (location, expr, reinterpret_cast <char * > (DynamicStrings_string (CreateLabelName (destquad))));
9675 18 : }
9676 :
9677 :
9678 : /*
9679 : CodeIfSetLess - code IF left < right then destquad for set types.
9680 : */
9681 :
9682 6 : static void CodeIfSetLess (unsigned int tokenno, unsigned int left, unsigned int right, unsigned int destquad)
9683 : {
9684 6 : CodeIfSetCondition (tokenno, left, right, destquad, (M2GenGCC_BinaryFunction) {(M2GenGCC_BinaryFunction_t) m2expr_BuildIsSubset}, NameKey_MakeKey ((const char *) "Less", 4));
9685 6 : }
9686 :
9687 :
9688 : /*
9689 : CodeIfSetLessEqu - code IF left <= right then destquad for set types.
9690 : */
9691 :
9692 6 : static void CodeIfSetLessEqu (unsigned int tokenno, unsigned int left, unsigned int right, unsigned int destquad)
9693 : {
9694 6 : CodeIfSetCondition (tokenno, left, right, destquad, (M2GenGCC_BinaryFunction) {(M2GenGCC_BinaryFunction_t) m2expr_BuildIsSubset}, NameKey_MakeKey ((const char *) "LessEqu", 7));
9695 6 : }
9696 :
9697 :
9698 : /*
9699 : CodeIfSetGre - code IF left > right then destquad for set types.
9700 : */
9701 :
9702 0 : static void CodeIfSetGre (unsigned int tokenno, unsigned int left, unsigned int right, unsigned int destquad)
9703 : {
9704 0 : CodeIfSetCondition (tokenno, left, right, destquad, (M2GenGCC_BinaryFunction) {(M2GenGCC_BinaryFunction_t) m2expr_BuildIsNotSubset}, NameKey_MakeKey ((const char *) "Gre", 3));
9705 0 : }
9706 :
9707 :
9708 : /*
9709 : CodeIfSetGreEqu - code IF left >= right then destquad for set types.
9710 : */
9711 :
9712 6 : static void CodeIfSetGreEqu (unsigned int tokenno, unsigned int left, unsigned int right, unsigned int destquad)
9713 : {
9714 6 : CodeIfSetCondition (tokenno, left, right, destquad, (M2GenGCC_BinaryFunction) {(M2GenGCC_BinaryFunction_t) m2expr_BuildIsNotSubset}, NameKey_MakeKey ((const char *) "GreEqu", 6));
9715 6 : }
9716 :
9717 :
9718 : /*
9719 : PerformCodeIfLess - codes the quadruple if op1 < op2 then goto op3
9720 : */
9721 :
9722 3988 : static void PerformCodeIfLess (unsigned int quad)
9723 : {
9724 3988 : tree tl;
9725 3988 : tree tr;
9726 3988 : location_t location;
9727 3988 : unsigned int left;
9728 3988 : unsigned int right;
9729 3988 : unsigned int dest;
9730 3988 : unsigned int combined;
9731 3988 : unsigned int leftpos;
9732 3988 : unsigned int rightpos;
9733 3988 : unsigned int destpos;
9734 3988 : bool constExpr;
9735 3988 : bool overflow;
9736 3988 : M2Quads_QuadOperator op;
9737 :
9738 3988 : M2Quads_GetQuadOtok (quad, &combined, &op, &left, &right, &dest, &overflow, &constExpr, &leftpos, &rightpos, &destpos);
9739 3988 : location = M2LexBuf_TokenToLocation (combined);
9740 3988 : if ((SymbolTable_IsConst (left)) && (SymbolTable_IsConst (right)))
9741 : {
9742 0 : SymbolTable_PushValue (left);
9743 0 : SymbolTable_PushValue (right);
9744 0 : if (M2ALU_Less (CurrentQuadToken))
9745 : {
9746 0 : m2statement_BuildGoto (location, reinterpret_cast <char * > (DynamicStrings_string (CreateLabelName (dest))));
9747 : }
9748 : /* Fall through. */
9749 : }
9750 3988 : else if ((((SymbolTable_IsConstSet (left)) || ((SymbolTable_IsVar (left)) && (SymbolTable_IsSet (SymbolTable_SkipType (SymbolTable_GetType (left)))))) || (SymbolTable_IsConstSet (right))) || ((SymbolTable_IsVar (right)) && (SymbolTable_IsSet (SymbolTable_SkipType (SymbolTable_GetType (right))))))
9751 : {
9752 : /* avoid dangling else. */
9753 6 : CodeIfSetLess (combined, left, right, dest);
9754 : }
9755 : else
9756 : {
9757 : /* avoid dangling else. */
9758 3982 : if ((SymbolTable_IsComposite (SymbolTable_GetType (left))) || (SymbolTable_IsComposite (SymbolTable_GetType (right))))
9759 : {
9760 0 : M2MetaError_MetaErrorT2 (combined, (const char *) "comparison tests between composite types not allowed {%1Eatd} and {%2atd}", 73, left, right);
9761 : }
9762 : else
9763 : {
9764 3982 : ConvertBinaryOperands (location, &tl, &tr, ComparisonMixTypes (left, right, SymbolTable_SkipType (SymbolTable_GetType (left)), SymbolTable_SkipType (SymbolTable_GetType (right)), combined), left, right);
9765 3982 : m2statement_IfExprJump (location, m2expr_BuildLessThan (location, tl, tr), reinterpret_cast <char * > (DynamicStrings_string (CreateLabelName (dest))));
9766 : }
9767 : }
9768 3988 : }
9769 :
9770 :
9771 : /*
9772 : CodeIfLess - codes the quadruple if op1 < op2 then goto op3
9773 : */
9774 :
9775 3988 : static void CodeIfLess (unsigned int quad)
9776 : {
9777 3988 : if (IsValidExpressionRelOp (quad, false))
9778 : {
9779 3988 : PerformCodeIfLess (quad);
9780 : }
9781 3988 : }
9782 :
9783 :
9784 : /*
9785 : CodeIfSetEquNarrow -
9786 : */
9787 :
9788 738 : static void CodeIfSetEquNarrow (location_t location, bool invertCondition, unsigned int settype, tree left, tree right, unsigned int destQuad)
9789 : {
9790 738 : tree condition;
9791 738 : tree mask;
9792 :
9793 : /* The set type fits inside a word, so mask off any unused bits. */
9794 738 : mask = m2expr_BuildMask (location, CalcBitsInSet (location, settype), false);
9795 738 : left = m2expr_BuildLogicalAnd (location, left, mask);
9796 738 : right = m2expr_BuildLogicalAnd (location, right, mask);
9797 738 : if (invertCondition)
9798 : {
9799 372 : condition = m2expr_BuildNotEqualTo (location, left, right);
9800 : }
9801 : else
9802 : {
9803 366 : condition = m2expr_BuildEqualTo (location, left, right);
9804 : }
9805 738 : m2statement_IfExprJump (location, condition, reinterpret_cast <char * > (DynamicStrings_string (CreateLabelName (destQuad))));
9806 738 : }
9807 :
9808 :
9809 : /*
9810 : CallSetWideBoolFunction - return a tree containing a call to
9811 : M2WIDESET.widefuncname (left, right, HIGHBIT (settype)).
9812 : */
9813 :
9814 552 : static tree CallSetWideBoolFunction (location_t location, unsigned int tokenno, NameKey_Name widefuncname, unsigned int settype, unsigned int left, unsigned int right)
9815 : {
9816 552 : unsigned int function;
9817 552 : unsigned int param1;
9818 552 : unsigned int param2;
9819 552 : tree highbit;
9820 552 : tree array1;
9821 552 : tree array2;
9822 552 : tree call;
9823 :
9824 552 : function = FromM2WIDESETImport (tokenno, widefuncname);
9825 552 : checkDeclare (function);
9826 552 : location = M2LexBuf_TokenToLocation (tokenno);
9827 552 : param1 = SymbolTable_GetNthParamAnyClosest (function, 1, SymbolTable_GetMainModule ());
9828 552 : param2 = SymbolTable_GetNthParamAnyClosest (function, 2, SymbolTable_GetMainModule ());
9829 552 : array1 = CreateSetArrayParam (location, tokenno, left, param1);
9830 552 : array2 = CreateSetArrayParam (location, tokenno, right, param2);
9831 552 : highbit = m2convert_ToCardinal (location, CalcHighSetBit (location, settype));
9832 552 : m2statement_BuildParam (location, highbit); /* Parameter 3. */
9833 552 : m2statement_BuildParam (location, array2); /* Parameter 2. */
9834 552 : m2statement_BuildParam (location, array1); /* Parameter 1. */
9835 552 : call = m2statement_BuildProcedureCallTree (location, SymbolConversion_Mod2Gcc (function), SymbolConversion_Mod2Gcc (SymbolTable_GetType (function))); /* Parameter 1. */
9836 552 : m2statement_SetLastFunction (NULL);
9837 552 : return call;
9838 : /* static analysis guarentees a RETURN statement will be used before here. */
9839 : __builtin_unreachable ();
9840 : }
9841 :
9842 :
9843 : /*
9844 : CodeIfSetEquWide - creates a statement tree:
9845 : if left = right then goto destQuad. The boolean
9846 : invertCondition will check left # right.
9847 : */
9848 :
9849 534 : static void CodeIfSetEquWide (location_t location, unsigned int tokenno, bool invertCondition, unsigned int settype, unsigned int left, unsigned int right, unsigned int destQuad)
9850 : {
9851 534 : tree call;
9852 534 : tree expr;
9853 534 : tree label;
9854 :
9855 534 : call = CallSetWideBoolFunction (location, tokenno, NameKey_MakeKey ((const char *) "Equal", 5), settype, left, right);
9856 534 : label = static_cast<tree> (CreateLabelName (destQuad));
9857 534 : if (invertCondition)
9858 : {
9859 240 : expr = m2expr_BuildEqualTo (location, call, m2type_GetBooleanFalse ());
9860 : }
9861 : else
9862 : {
9863 294 : expr = m2expr_BuildNotEqualTo (location, call, m2type_GetBooleanFalse ());
9864 : }
9865 534 : m2statement_IfExprJump (location, expr, reinterpret_cast <char * > (DynamicStrings_string (static_cast<DynamicStrings_String> (label))));
9866 534 : }
9867 :
9868 :
9869 : /*
9870 : CodeIfSetEquLower code a comparison between left and right and if true
9871 : jump to destQuad. The invertCondition allows for the inverse test.
9872 : Note that if op1 and op2 are not both constants as this will have been
9873 : evaluated in CodeIfNotEqu.
9874 : */
9875 :
9876 1272 : static void CodeIfSetEquLower (unsigned int tokenno, bool invertCondition, unsigned int left, unsigned int right, unsigned int destQuad)
9877 : {
9878 1272 : unsigned int settype;
9879 1272 : location_t location;
9880 :
9881 1272 : location = M2LexBuf_TokenToLocation (tokenno);
9882 1272 : if ((SymbolTable_IsConst (left)) && (SymbolTable_IsConst (right)))
9883 : {
9884 0 : M2Error_InternalError ((const char *) "this should have been folded by CodeIfEqu or CodeIfNotEqu", 57);
9885 : }
9886 1272 : else if (SymbolTable_IsConst (left))
9887 : {
9888 : /* avoid dangling else. */
9889 0 : settype = SymbolTable_GetLType (right);
9890 : }
9891 : else
9892 : {
9893 : /* avoid dangling else. */
9894 1272 : settype = SymbolTable_GetLType (left);
9895 : }
9896 1272 : if ((SymbolTable_GetLType (left)) != (SymbolTable_GetLType (right)))
9897 : {
9898 : /* This test used to occur after the GetSetInWord (settype) condition. */
9899 0 : M2MetaError_MetaErrorT2 (tokenno, (const char *) "set comparison is only allowed between the same set type, the set types used by {%1Eatd} and {%2atd} are different", 114, left, right);
9900 : }
9901 1272 : if (SymbolTable_GetSetInWord (settype))
9902 : {
9903 : /* Allow sets to be compared against { } for bitset. */
9904 738 : CodeIfSetEquNarrow (location, invertCondition, settype, SymbolConversion_Mod2Gcc (left), SymbolConversion_Mod2Gcc (right), destQuad);
9905 : }
9906 : else
9907 : {
9908 534 : CodeIfSetEquWide (location, tokenno, invertCondition, settype, left, right, destQuad);
9909 : }
9910 1272 : }
9911 :
9912 :
9913 : /*
9914 : CodeIfSetNotEqu - codes if op1 # op2 then goto op3
9915 : */
9916 :
9917 612 : static void CodeIfSetNotEqu (unsigned int tokenno, unsigned int left, unsigned int right, unsigned int destQuad)
9918 : {
9919 0 : CodeIfSetEquLower (tokenno, true, left, right, destQuad);
9920 612 : }
9921 :
9922 :
9923 : /*
9924 : CodeIfSetEqu - codes if op1 = op2 then goto op3
9925 : */
9926 :
9927 660 : static void CodeIfSetEqu (unsigned int tokenno, unsigned int left, unsigned int right, unsigned int destQuad)
9928 : {
9929 0 : CodeIfSetEquLower (tokenno, false, left, right, destQuad);
9930 660 : }
9931 :
9932 :
9933 : /*
9934 : PerformCodeIfGre - codes the quadruple if op1 > op2 then goto op3
9935 : */
9936 :
9937 4832 : static void PerformCodeIfGre (unsigned int quad)
9938 : {
9939 4832 : tree tl;
9940 4832 : tree tr;
9941 4832 : tree condition;
9942 4832 : location_t location;
9943 4832 : unsigned int left;
9944 4832 : unsigned int right;
9945 4832 : unsigned int dest;
9946 4832 : unsigned int combined;
9947 4832 : unsigned int leftpos;
9948 4832 : unsigned int rightpos;
9949 4832 : unsigned int destpos;
9950 4832 : bool constExpr;
9951 4832 : bool overflow;
9952 4832 : M2Quads_QuadOperator op;
9953 :
9954 4832 : M2Quads_GetQuadOtok (quad, &combined, &op, &left, &right, &dest, &overflow, &constExpr, &leftpos, &rightpos, &destpos);
9955 4832 : location = M2LexBuf_TokenToLocation (combined);
9956 4832 : if ((SymbolTable_IsConst (left)) && (SymbolTable_IsConst (right)))
9957 : {
9958 0 : SymbolTable_PushValue (left);
9959 0 : SymbolTable_PushValue (right);
9960 0 : if (M2ALU_Gre (combined))
9961 : {
9962 0 : m2statement_BuildGoto (location, reinterpret_cast <char * > (DynamicStrings_string (CreateLabelName (dest))));
9963 : }
9964 : /* fall through */
9965 : }
9966 4832 : else if ((((SymbolTable_IsConstSet (left)) || ((SymbolTable_IsVar (left)) && (SymbolTable_IsSet (SymbolTable_SkipType (SymbolTable_GetType (left)))))) || (SymbolTable_IsConstSet (right))) || ((SymbolTable_IsVar (right)) && (SymbolTable_IsSet (SymbolTable_SkipType (SymbolTable_GetType (right))))))
9967 : {
9968 : /* avoid dangling else. */
9969 0 : CodeIfSetGre (combined, left, right, dest);
9970 : }
9971 : else
9972 : {
9973 : /* avoid dangling else. */
9974 4832 : if ((SymbolTable_IsComposite (SymbolTable_GetType (left))) || (SymbolTable_IsComposite (SymbolTable_GetType (right))))
9975 : {
9976 0 : M2MetaError_MetaErrorT2 (combined, (const char *) "comparison tests between composite types not allowed {%1Eatd} and {%2atd}", 73, left, right);
9977 : }
9978 : else
9979 : {
9980 4832 : ConvertBinaryOperands (location, &tl, &tr, ComparisonMixTypes (left, right, SymbolTable_SkipType (SymbolTable_GetType (left)), SymbolTable_SkipType (SymbolTable_GetType (right)), combined), left, right);
9981 4832 : condition = m2expr_BuildGreaterThan (location, tl, tr);
9982 4832 : m2statement_IfExprJump (location, condition, reinterpret_cast <char * > (DynamicStrings_string (CreateLabelName (dest))));
9983 : }
9984 : }
9985 4832 : }
9986 :
9987 :
9988 : /*
9989 : CodeIfGre - codes the quadruple if op1 > op2 then goto op3
9990 : */
9991 :
9992 4832 : static void CodeIfGre (unsigned int quad)
9993 : {
9994 4832 : if (IsValidExpressionRelOp (quad, false))
9995 : {
9996 4832 : PerformCodeIfGre (quad);
9997 : }
9998 4832 : }
9999 :
10000 :
10001 : /*
10002 : PerformCodeIfLessEqu - codes the quadruple if op1 <= op2 then goto op3
10003 : */
10004 :
10005 5972 : static void PerformCodeIfLessEqu (unsigned int quad)
10006 : {
10007 5972 : tree tl;
10008 5972 : tree tr;
10009 5972 : tree condition;
10010 5972 : location_t location;
10011 5972 : unsigned int left;
10012 5972 : unsigned int right;
10013 5972 : unsigned int dest;
10014 5972 : unsigned int combined;
10015 5972 : unsigned int leftpos;
10016 5972 : unsigned int rightpos;
10017 5972 : unsigned int destpos;
10018 5972 : bool constExpr;
10019 5972 : bool overflow;
10020 5972 : M2Quads_QuadOperator op;
10021 :
10022 5972 : M2Quads_GetQuadOtok (quad, &combined, &op, &left, &right, &dest, &overflow, &constExpr, &leftpos, &rightpos, &destpos);
10023 5972 : location = M2LexBuf_TokenToLocation (combined);
10024 5972 : if ((SymbolTable_IsConst (left)) && (SymbolTable_IsConst (right)))
10025 : {
10026 0 : SymbolTable_PushValue (left);
10027 0 : SymbolTable_PushValue (right);
10028 0 : if (M2ALU_LessEqu (combined))
10029 : {
10030 0 : m2statement_BuildGoto (location, reinterpret_cast <char * > (DynamicStrings_string (CreateLabelName (dest))));
10031 : }
10032 : /* fall through */
10033 : }
10034 5972 : else if ((((SymbolTable_IsConstSet (left)) || ((SymbolTable_IsVar (left)) && (SymbolTable_IsSet (SymbolTable_SkipType (SymbolTable_GetType (left)))))) || (SymbolTable_IsConstSet (right))) || ((SymbolTable_IsVar (right)) && (SymbolTable_IsSet (SymbolTable_SkipType (SymbolTable_GetType (right))))))
10035 : {
10036 : /* avoid dangling else. */
10037 6 : CodeIfSetLessEqu (combined, left, right, dest);
10038 : }
10039 : else
10040 : {
10041 : /* avoid dangling else. */
10042 5966 : if ((SymbolTable_IsComposite (SymbolTable_GetType (left))) || (SymbolTable_IsComposite (SymbolTable_GetType (right))))
10043 : {
10044 0 : M2MetaError_MetaErrorT2 (combined, (const char *) "comparison tests between composite types not allowed {%1Eatd} and {%2atd}", 73, left, right);
10045 : }
10046 : else
10047 : {
10048 5966 : ConvertBinaryOperands (location, &tl, &tr, ComparisonMixTypes (left, right, SymbolTable_SkipType (SymbolTable_GetType (left)), SymbolTable_SkipType (SymbolTable_GetType (right)), combined), left, right);
10049 5966 : condition = m2expr_BuildLessThanOrEqual (location, tl, tr);
10050 5966 : m2statement_IfExprJump (location, condition, reinterpret_cast <char * > (DynamicStrings_string (CreateLabelName (dest))));
10051 : }
10052 : }
10053 5972 : }
10054 :
10055 :
10056 : /*
10057 : CodeIfLessEqu - codes the quadruple if op1 <= op2 then goto op3
10058 : */
10059 :
10060 5984 : static void CodeIfLessEqu (unsigned int quad)
10061 : {
10062 5984 : if (IsValidExpressionRelOp (quad, false))
10063 : {
10064 5972 : PerformCodeIfLessEqu (quad);
10065 : }
10066 5984 : }
10067 :
10068 :
10069 : /*
10070 : PerformCodeIfGreEqu - codes the quadruple if op1 >= op2 then goto op3
10071 : */
10072 :
10073 7166 : static void PerformCodeIfGreEqu (unsigned int quad)
10074 : {
10075 7166 : tree tl;
10076 7166 : tree tr;
10077 7166 : tree condition;
10078 7166 : location_t location;
10079 7166 : unsigned int left;
10080 7166 : unsigned int right;
10081 7166 : unsigned int dest;
10082 7166 : unsigned int combined;
10083 7166 : unsigned int leftpos;
10084 7166 : unsigned int rightpos;
10085 7166 : unsigned int destpos;
10086 7166 : bool constExpr;
10087 7166 : bool overflow;
10088 7166 : M2Quads_QuadOperator op;
10089 :
10090 7166 : M2Quads_GetQuadOtok (quad, &combined, &op, &left, &right, &dest, &overflow, &constExpr, &leftpos, &rightpos, &destpos);
10091 7166 : location = M2LexBuf_TokenToLocation (combined);
10092 7166 : if ((SymbolTable_IsConst (left)) && (SymbolTable_IsConst (right)))
10093 : {
10094 0 : SymbolTable_PushValue (left);
10095 0 : SymbolTable_PushValue (right);
10096 0 : if (M2ALU_GreEqu (combined))
10097 : {
10098 0 : m2statement_BuildGoto (location, reinterpret_cast <char * > (DynamicStrings_string (CreateLabelName (dest))));
10099 : }
10100 : /* fall through */
10101 : }
10102 7166 : else if ((((SymbolTable_IsConstSet (left)) || ((SymbolTable_IsVar (left)) && (SymbolTable_IsSet (SymbolTable_SkipType (SymbolTable_GetType (left)))))) || (SymbolTable_IsConstSet (right))) || ((SymbolTable_IsVar (right)) && (SymbolTable_IsSet (SymbolTable_SkipType (SymbolTable_GetType (right))))))
10103 : {
10104 : /* avoid dangling else. */
10105 6 : CodeIfSetGreEqu (combined, left, right, dest);
10106 : }
10107 : else
10108 : {
10109 : /* avoid dangling else. */
10110 7160 : if ((SymbolTable_IsComposite (SymbolTable_GetType (left))) || (SymbolTable_IsComposite (SymbolTable_GetType (right))))
10111 : {
10112 0 : M2MetaError_MetaErrorT2 (combined, (const char *) "comparison tests between composite types not allowed {%1Eatd} and {%2atd}", 73, left, right);
10113 : }
10114 : else
10115 : {
10116 7160 : ConvertBinaryOperands (location, &tl, &tr, ComparisonMixTypes (left, right, SymbolTable_SkipType (SymbolTable_GetType (left)), SymbolTable_SkipType (SymbolTable_GetType (right)), combined), left, right);
10117 7160 : condition = m2expr_BuildGreaterThanOrEqual (location, tl, tr);
10118 7160 : m2statement_IfExprJump (location, condition, reinterpret_cast <char * > (DynamicStrings_string (CreateLabelName (dest))));
10119 : }
10120 : }
10121 7166 : }
10122 :
10123 :
10124 : /*
10125 : CodeIfGreEqu - codes the quadruple if op1 >= op2 then goto op3
10126 : */
10127 :
10128 7172 : static void CodeIfGreEqu (unsigned int quad)
10129 : {
10130 7172 : if (IsValidExpressionRelOp (quad, false))
10131 : {
10132 7166 : PerformCodeIfGreEqu (quad);
10133 : }
10134 7172 : }
10135 :
10136 :
10137 : /*
10138 : ComparisonMixTypes -
10139 : */
10140 :
10141 75811 : static unsigned int ComparisonMixTypes (unsigned int varleft, unsigned int varright, unsigned int left, unsigned int right, unsigned int tokpos)
10142 : {
10143 75811 : if (M2System_IsGenericSystemType (left))
10144 : {
10145 : return left;
10146 : }
10147 75497 : else if (M2System_IsGenericSystemType (right))
10148 : {
10149 : /* avoid dangling else. */
10150 : return right;
10151 : }
10152 : else
10153 : {
10154 : /* avoid dangling else. */
10155 75497 : return M2Base_MixTypesDecl (varleft, varright, left, right, tokpos);
10156 : }
10157 : /* static analysis guarentees a RETURN statement will be used before here. */
10158 : __builtin_unreachable ();
10159 : }
10160 :
10161 :
10162 : /*
10163 : PerformCodeIfEqu -
10164 : */
10165 :
10166 21860 : static void PerformCodeIfEqu (unsigned int quad)
10167 : {
10168 21860 : tree tl;
10169 21860 : tree tr;
10170 21860 : tree condition;
10171 21860 : location_t location;
10172 21860 : unsigned int left;
10173 21860 : unsigned int right;
10174 21860 : unsigned int dest;
10175 21860 : unsigned int combined;
10176 21860 : unsigned int leftpos;
10177 21860 : unsigned int rightpos;
10178 21860 : unsigned int destpos;
10179 21860 : bool constExpr;
10180 21860 : bool overflow;
10181 21860 : M2Quads_QuadOperator op;
10182 :
10183 21860 : M2Quads_GetQuadOtok (quad, &combined, &op, &left, &right, &dest, &overflow, &constExpr, &leftpos, &rightpos, &destpos);
10184 21860 : location = M2LexBuf_TokenToLocation (combined);
10185 21860 : if ((SymbolTable_IsConst (left)) && (SymbolTable_IsConst (right)))
10186 : {
10187 0 : SymbolTable_PushValue (left);
10188 0 : SymbolTable_PushValue (right);
10189 0 : if (M2ALU_Equ (combined))
10190 : {
10191 0 : m2statement_BuildGoto (location, reinterpret_cast <char * > (DynamicStrings_string (CreateLabelName (dest))));
10192 : }
10193 : /* Fall through. */
10194 : }
10195 21860 : else if ((((SymbolTable_IsConstSet (left)) || ((SymbolTable_IsVar (left)) && (SymbolTable_IsSet (SymbolTable_SkipType (SymbolTable_GetType (left)))))) || (SymbolTable_IsConstSet (right))) || ((SymbolTable_IsVar (right)) && (SymbolTable_IsSet (SymbolTable_SkipType (SymbolTable_GetType (right))))))
10196 : {
10197 : /* avoid dangling else. */
10198 660 : CodeIfSetEqu (quad, left, right, dest);
10199 : }
10200 : else
10201 : {
10202 : /* avoid dangling else. */
10203 21200 : if ((SymbolTable_IsComposite (SymbolTable_GetType (left))) || (SymbolTable_IsComposite (SymbolTable_GetType (right))))
10204 : {
10205 0 : M2MetaError_MetaErrorT2 (combined, (const char *) "equality tests between composite types not allowed {%1Eatd} and {%2atd}", 71, left, right);
10206 : }
10207 : else
10208 : {
10209 21200 : ConvertBinaryOperands (location, &tl, &tr, ComparisonMixTypes (left, right, SymbolTable_SkipType (SymbolTable_GetType (left)), SymbolTable_SkipType (SymbolTable_GetType (right)), combined), left, right);
10210 21200 : condition = m2expr_BuildEqualTo (location, tl, tr);
10211 21200 : m2statement_IfExprJump (location, condition, reinterpret_cast <char * > (DynamicStrings_string (CreateLabelName (dest))));
10212 : }
10213 : }
10214 21860 : }
10215 :
10216 :
10217 : /*
10218 : PerformCodeIfNotEqu -
10219 : */
10220 :
10221 33289 : static void PerformCodeIfNotEqu (unsigned int quad)
10222 : {
10223 33289 : tree tl;
10224 33289 : tree tr;
10225 33289 : tree condition;
10226 33289 : location_t location;
10227 33289 : unsigned int left;
10228 33289 : unsigned int right;
10229 33289 : unsigned int dest;
10230 33289 : unsigned int combined;
10231 33289 : unsigned int leftpos;
10232 33289 : unsigned int rightpos;
10233 33289 : unsigned int destpos;
10234 33289 : bool constExpr;
10235 33289 : bool overflow;
10236 33289 : M2Quads_QuadOperator op;
10237 :
10238 : /* Ensure that any remaining undeclared constant literal is declared. */
10239 33289 : M2Quads_GetQuadOtok (quad, &combined, &op, &left, &right, &dest, &constExpr, &overflow, &leftpos, &rightpos, &destpos);
10240 33289 : location = M2LexBuf_TokenToLocation (combined);
10241 33289 : if ((SymbolTable_IsConst (left)) && (SymbolTable_IsConst (right)))
10242 : {
10243 6 : SymbolTable_PushValue (left);
10244 6 : SymbolTable_PushValue (right);
10245 6 : if (M2ALU_NotEqu (combined))
10246 : {
10247 0 : m2statement_BuildGoto (location, reinterpret_cast <char * > (DynamicStrings_string (CreateLabelName (dest))));
10248 : }
10249 : /* Fall through. */
10250 : }
10251 33283 : else if ((((SymbolTable_IsConstSet (left)) || ((SymbolTable_IsVar (left)) && (SymbolTable_IsSet (SymbolTable_SkipType (SymbolTable_GetType (left)))))) || (SymbolTable_IsConstSet (right))) || ((SymbolTable_IsVar (right)) && (SymbolTable_IsSet (SymbolTable_SkipType (SymbolTable_GetType (right))))))
10252 : {
10253 : /* avoid dangling else. */
10254 612 : CodeIfSetNotEqu (combined, left, right, dest);
10255 : }
10256 : else
10257 : {
10258 : /* avoid dangling else. */
10259 32671 : if ((SymbolTable_IsComposite (SymbolTable_GetType (left))) || (SymbolTable_IsComposite (SymbolTable_GetType (right))))
10260 : {
10261 0 : M2MetaError_MetaErrorT2 (combined, (const char *) "inequality tests between composite types not allowed {%1Eatd} and {%2atd}", 73, left, right);
10262 : }
10263 : else
10264 : {
10265 32671 : ConvertBinaryOperands (location, &tl, &tr, ComparisonMixTypes (left, right, SymbolTable_SkipType (SymbolTable_GetType (left)), SymbolTable_SkipType (SymbolTable_GetType (right)), combined), left, right);
10266 32671 : condition = m2expr_BuildNotEqualTo (location, tl, tr);
10267 32671 : m2statement_IfExprJump (location, condition, reinterpret_cast <char * > (DynamicStrings_string (CreateLabelName (dest))));
10268 : }
10269 : }
10270 33289 : }
10271 :
10272 :
10273 : /*
10274 : IsValidExpressionRelOp - declare left and right constants (if they are not already declared).
10275 : Check whether left and right are expression compatible.
10276 : */
10277 :
10278 79637 : static bool IsValidExpressionRelOp (unsigned int quad, bool isin)
10279 : {
10280 79637 : unsigned int left;
10281 79637 : unsigned int right;
10282 79637 : unsigned int dest;
10283 79637 : unsigned int combined;
10284 79637 : unsigned int leftpos;
10285 79637 : unsigned int rightpos;
10286 79637 : unsigned int destpos;
10287 79637 : bool constExpr;
10288 79637 : bool overflow;
10289 79637 : M2Quads_QuadOperator op;
10290 :
10291 : /* Ensure that any remaining undeclared constant literal is declared. */
10292 79637 : M2Quads_GetQuadOtok (quad, &combined, &op, &left, &right, &dest, &constExpr, &overflow, &leftpos, &rightpos, &destpos);
10293 79637 : M2GCCDeclare_DeclareConstant (leftpos, left);
10294 79637 : M2GCCDeclare_DeclareConstant (rightpos, right);
10295 79637 : M2GCCDeclare_DeclareConstructor (leftpos, quad, left);
10296 79637 : M2GCCDeclare_DeclareConstructor (rightpos, quad, right);
10297 79637 : if (M2Check_ExpressionTypeCompatible (combined, (const char *) "", 0, left, right, M2Options_StrictTypeChecking, isin))
10298 : {
10299 : return true;
10300 : }
10301 : else
10302 : {
10303 : if (Verbose)
10304 : {
10305 : M2MetaError_MetaErrorT2 (combined, (const char *) "expression mismatch between {%1Etad} and {%2tad} seen during comparison", 71, left, right);
10306 : }
10307 : return false;
10308 : }
10309 : /* static analysis guarentees a RETURN statement will be used before here. */
10310 : __builtin_unreachable ();
10311 : }
10312 :
10313 :
10314 : /*
10315 : CodeIfEqu - codes the quadruple if op1 = op2 then goto op3
10316 : */
10317 :
10318 21878 : static void CodeIfEqu (unsigned int quad)
10319 : {
10320 21878 : if (IsValidExpressionRelOp (quad, false))
10321 : {
10322 21860 : PerformCodeIfEqu (quad);
10323 : }
10324 21878 : }
10325 :
10326 :
10327 : /*
10328 : CodeIfNotEqu - codes the quadruple if op1 # op2 then goto op3
10329 : */
10330 :
10331 33301 : static void CodeIfNotEqu (unsigned int quad)
10332 : {
10333 33301 : if (IsValidExpressionRelOp (quad, false))
10334 : {
10335 33289 : PerformCodeIfNotEqu (quad);
10336 : }
10337 33301 : }
10338 :
10339 :
10340 : /*
10341 : MixTypes3 - returns a type compatible from, low, high, var.
10342 : */
10343 :
10344 108 : static unsigned int MixTypes3 (unsigned int low, unsigned int high, unsigned int var, unsigned int tokenno)
10345 : {
10346 108 : unsigned int type;
10347 :
10348 108 : type = M2Base_MixTypes (SymbolTable_SkipType (SymbolTable_GetType (low)), SymbolTable_SkipType (SymbolTable_GetType (high)), tokenno);
10349 108 : type = M2Base_MixTypes (type, SymbolTable_SkipType (SymbolTable_GetType (var)), tokenno);
10350 108 : return type;
10351 : /* static analysis guarentees a RETURN statement will be used before here. */
10352 : __builtin_unreachable ();
10353 : }
10354 :
10355 :
10356 : /*
10357 : BuildIfVarInConstValue - if var in constsetvalue then goto trueexit
10358 : */
10359 :
10360 6 : static void BuildIfVarInConstValue (location_t location, unsigned int tokenno, M2ALU_PtrToValue constsetvalue, unsigned int var, unsigned int trueexit)
10361 : {
10362 6 : tree vt;
10363 6 : tree lt;
10364 6 : tree ht;
10365 6 : unsigned int type;
10366 6 : unsigned int low;
10367 6 : unsigned int high;
10368 6 : unsigned int n;
10369 6 : DynamicStrings_String truelabel;
10370 :
10371 6 : n = 1;
10372 6 : truelabel = static_cast<DynamicStrings_String> (DynamicStrings_string (CreateLabelName (trueexit)));
10373 24 : while (M2ALU_GetRange (constsetvalue, n, &low, &high))
10374 : {
10375 12 : type = MixTypes3 (low, high, var, tokenno);
10376 12 : ConvertBinaryOperands (location, &vt, <, type, var, low);
10377 12 : ConvertBinaryOperands (location, &ht, <, type, high, low);
10378 12 : m2expr_BuildIfInRangeGoto (location, vt, lt, ht, reinterpret_cast <char * > (truelabel));
10379 12 : n += 1;
10380 : }
10381 6 : }
10382 :
10383 :
10384 : /*
10385 : BuildIfNotVarInConstValue - if not (var in constsetvalue) then goto trueexit
10386 : */
10387 :
10388 60 : static void BuildIfNotVarInConstValue (location_t location, unsigned int tokenno, unsigned int quad, M2ALU_PtrToValue constsetvalue, unsigned int var, unsigned int trueexit)
10389 : {
10390 60 : tree vt;
10391 60 : tree lt;
10392 60 : tree ht;
10393 60 : unsigned int type;
10394 60 : unsigned int low;
10395 60 : unsigned int high;
10396 60 : unsigned int n;
10397 60 : DynamicStrings_String falselabel;
10398 60 : DynamicStrings_String truelabel;
10399 :
10400 60 : truelabel = static_cast<DynamicStrings_String> (DynamicStrings_string (CreateLabelName (trueexit)));
10401 60 : n = 1;
10402 216 : while (M2ALU_GetRange (constsetvalue, n, &low, &high))
10403 : {
10404 96 : n += 1;
10405 : }
10406 60 : if (n == 2)
10407 : {
10408 : /* Only one set range, so we invert it */
10409 28 : type = MixTypes3 (low, high, var, tokenno);
10410 28 : ConvertBinaryOperands (location, &vt, <, type, var, low);
10411 28 : ConvertBinaryOperands (location, &ht, <, type, high, low);
10412 28 : m2expr_BuildIfNotInRangeGoto (location, vt, lt, ht, reinterpret_cast <char * > (truelabel));
10413 : }
10414 : else
10415 : {
10416 32 : n = 1;
10417 32 : falselabel = static_cast<DynamicStrings_String> (DynamicStrings_string (FormatStrings_Sprintf1 (DynamicStrings_Mark (DynamicStrings_InitString ((const char *) ".Lset%d", 7)), (const unsigned char *) &quad, (sizeof (quad)-1))));
10418 132 : while (M2ALU_GetRange (constsetvalue, n, &low, &high))
10419 : {
10420 68 : type = MixTypes3 (low, high, var, tokenno);
10421 68 : ConvertBinaryOperands (location, &vt, <, type, var, low);
10422 68 : ConvertBinaryOperands (location, &ht, <, type, high, low);
10423 68 : m2expr_BuildIfInRangeGoto (location, vt, lt, ht, reinterpret_cast <char * > (falselabel));
10424 68 : n += 1;
10425 : }
10426 32 : m2statement_BuildGoto (location, reinterpret_cast <char * > (truelabel));
10427 32 : m2statement_DeclareLabel (location, reinterpret_cast <char * > (falselabel));
10428 : }
10429 60 : }
10430 :
10431 :
10432 : /*
10433 : SetWideIfIn - if M2WIDESET.In (set, element) then goto branch end.
10434 : */
10435 :
10436 850 : static void SetWideIfIn (location_t location, unsigned int tokenno, bool invertCondition, unsigned int settype, unsigned int element, unsigned int set, unsigned int branch)
10437 : {
10438 850 : DynamicStrings_String label;
10439 850 : tree bit;
10440 850 : tree call;
10441 850 : tree expr;
10442 850 : tree setarray;
10443 850 : unsigned int setparam;
10444 850 : unsigned int procedure;
10445 :
10446 850 : procedure = FromM2WIDESETImport (tokenno, NameKey_MakeKey ((const char *) "In", 2));
10447 850 : setparam = SymbolTable_GetNthParamAnyClosest (procedure, 1, SymbolTable_GetMainModule ());
10448 850 : setarray = CreateSetArrayParam (location, tokenno, set, setparam);
10449 850 : bit = SetElementToBit (location, settype, element);
10450 850 : m2statement_BuildParam (location, m2convert_ToCardinal (location, bit));
10451 850 : m2statement_BuildParam (location, setarray);
10452 850 : call = m2statement_BuildProcedureCallTree (location, SymbolConversion_Mod2Gcc (procedure), SymbolConversion_Mod2Gcc (SymbolTable_GetType (procedure)));
10453 850 : m2statement_SetLastFunction (NULL);
10454 850 : label = CreateLabelName (branch);
10455 850 : if (invertCondition)
10456 : {
10457 634 : expr = m2expr_BuildEqualTo (location, call, m2type_GetBooleanFalse ());
10458 : }
10459 : else
10460 : {
10461 216 : expr = m2expr_BuildNotEqualTo (location, call, m2type_GetBooleanFalse ());
10462 : }
10463 850 : m2statement_IfExprJump (location, expr, reinterpret_cast <char * > (DynamicStrings_string (label)));
10464 850 : }
10465 :
10466 :
10467 : /*
10468 : CodeNarrowIfIn -
10469 : */
10470 :
10471 1542 : static void CodeNarrowIfIn (location_t location, unsigned int settype, bool invertCondition, unsigned int element, unsigned int set, unsigned int branch)
10472 : {
10473 1542 : tree label;
10474 1542 : tree cond;
10475 1542 : tree bit;
10476 1542 : tree mask;
10477 1542 : tree bitset;
10478 :
10479 1542 : bit = m2convert_ToBitset (location, SetElementToBit (location, settype, element));
10480 1542 : mask = m2expr_BuildMask (location, CalcBitsInSet (location, settype), false);
10481 : /* Mask off only the bits we need. */
10482 1542 : bitset = m2convert_ToBitset (location, m2expr_BuildLogicalAnd (location, SymbolConversion_Mod2Gcc (set), mask));
10483 1542 : if (invertCondition)
10484 : {
10485 1234 : cond = m2expr_BuildIfNotInSet (location, bitset, bit);
10486 : }
10487 : else
10488 : {
10489 308 : cond = m2expr_BuildIfInSet (location, bitset, bit);
10490 : }
10491 1542 : label = static_cast<tree> (CreateLabelName (branch));
10492 1542 : m2statement_IfExprJump (location, cond, reinterpret_cast <char * > (DynamicStrings_string (static_cast<DynamicStrings_String> (label))));
10493 1542 : }
10494 :
10495 :
10496 : /*
10497 : CodeIfInLower - code the quadruple: if element in set then goto branch.
10498 : The invertCondition can be set to TRUE to handle CodeIfNotIn.
10499 : */
10500 :
10501 2476 : static void CodeIfInLower (unsigned int tokenno, unsigned int quad, bool invertCondition, unsigned int element, unsigned int set, unsigned int branch)
10502 : {
10503 2476 : unsigned int settype;
10504 2476 : location_t location;
10505 2476 : M2ALU_PtrToValue constsetvalue;
10506 :
10507 2476 : location = M2LexBuf_TokenToLocation (tokenno);
10508 : /* Firstly ensure that any constant literal is declared. */
10509 2476 : M2GCCDeclare_DeclareConstant (tokenno, set);
10510 2476 : M2GCCDeclare_DeclareConstant (tokenno, element);
10511 2476 : M2GCCDeclare_DeclareConstructor (tokenno, quad, set);
10512 2476 : M2GCCDeclare_DeclareConstructor (tokenno, quad, element);
10513 2476 : checkDeclare (set);
10514 2476 : checkDeclare (element);
10515 2476 : settype = SymbolTable_GetLType (set);
10516 2476 : if ((SymbolTable_IsConst (element)) && (SymbolTable_IsConst (set)))
10517 : {
10518 0 : M2Error_InternalError ((const char *) "should not get to here (if we do we should consider calling FoldIfIn)", 69);
10519 : }
10520 2476 : else if (CheckElementSetTypes (quad))
10521 : {
10522 : /* avoid dangling else. */
10523 2464 : if (SymbolTable_IsConst (set))
10524 : {
10525 66 : SymbolTable_PushValue (set);
10526 66 : constsetvalue = M2ALU_GetValue (tokenno);
10527 66 : if (invertCondition)
10528 : {
10529 : /* Builds a cascaded list of if statements. */
10530 60 : BuildIfNotVarInConstValue (location, tokenno, quad, constsetvalue, element, branch);
10531 : }
10532 : else
10533 : {
10534 : /* Builds a very different cascaded list of if statements. */
10535 6 : BuildIfVarInConstValue (location, tokenno, constsetvalue, element, branch);
10536 : }
10537 : }
10538 : else
10539 : {
10540 2398 : M2Debug_Assert (SymbolTable_IsVar (set));
10541 2398 : if (IsElementInRange (tokenno, settype, set, element))
10542 : {
10543 : /* avoid gcc warning by using compound statement even if not strictly necessary. */
10544 : /* Check for narrow and wide sets and call M2WIDESET if appropriate. */
10545 2392 : if (SymbolTable_GetSetInWord (settype))
10546 : {
10547 1542 : CodeNarrowIfIn (location, settype, invertCondition, element, set, branch);
10548 : }
10549 : else
10550 : {
10551 850 : SetWideIfIn (location, tokenno, invertCondition, settype, element, set, branch);
10552 : }
10553 : }
10554 : }
10555 : }
10556 2476 : }
10557 :
10558 :
10559 : /*
10560 : PerformCodeIfIn -
10561 : */
10562 :
10563 2476 : static void PerformCodeIfIn (unsigned int quad, bool invert)
10564 : {
10565 2476 : M2Quads_QuadOperator op;
10566 2476 : unsigned int element;
10567 2476 : unsigned int set;
10568 2476 : unsigned int branch;
10569 2476 : unsigned int combined;
10570 2476 : unsigned int elementpos;
10571 2476 : unsigned int setpos;
10572 2476 : unsigned int destpos;
10573 2476 : bool constExpr;
10574 2476 : bool overflow;
10575 :
10576 2476 : M2Quads_GetQuadOtok (quad, &combined, &op, &element, &set, &branch, &overflow, &constExpr, &elementpos, &setpos, &destpos);
10577 2476 : CodeIfInLower (combined, quad, invert, element, set, branch);
10578 2476 : }
10579 :
10580 :
10581 : /*
10582 : CodeIfIn - code the quadruple: if element in set then goto branch.
10583 : */
10584 :
10585 536 : static void CodeIfIn (unsigned int quad)
10586 : {
10587 536 : if (IsValidExpressionRelOp (quad, true))
10588 : {
10589 530 : PerformCodeIfIn (quad, false);
10590 : }
10591 536 : }
10592 :
10593 :
10594 : /*
10595 : CodeIfNotIn - code the quadruple: if not (element in set) then goto branch.
10596 : */
10597 :
10598 1946 : static void CodeIfNotIn (unsigned int quad)
10599 : {
10600 1946 : if (IsValidExpressionRelOp (quad, true))
10601 : {
10602 1946 : PerformCodeIfIn (quad, true);
10603 : }
10604 1946 : }
10605 :
10606 16981 : static void CodeIndrX (unsigned int quad)
10607 : {
10608 16981 : bool constExpr;
10609 16981 : bool overflowChecking;
10610 16981 : M2Quads_QuadOperator op;
10611 16981 : unsigned int tokenno;
10612 16981 : unsigned int left;
10613 16981 : unsigned int type;
10614 16981 : unsigned int right;
10615 16981 : unsigned int leftpos;
10616 16981 : unsigned int rightpos;
10617 16981 : unsigned int typepos;
10618 16981 : unsigned int indrxpos;
10619 16981 : location_t location;
10620 :
10621 : /*
10622 : ------------------------------------------------------------------------------
10623 : IndrX Operator a = *b
10624 : ------------------------------------------------------------------------------
10625 : Sym1<X> IndrX Sym2<I> Meaning Mem[Sym1<I>] := Mem[constant]
10626 : Sym1<X> IndrX Sym2<X> Meaning Mem[Sym1<I>] := Mem[Mem[Sym3<I>]]
10627 :
10628 : (op2 is the type of the data being indirectly copied)
10629 : */
10630 16981 : M2Quads_GetQuadOtok (quad, &indrxpos, &op, &left, &type, &right, &overflowChecking, &constExpr, &leftpos, &typepos, &rightpos);
10631 16981 : tokenno = M2LexBuf_MakeVirtualTok (indrxpos, leftpos, rightpos);
10632 16981 : location = M2LexBuf_TokenToLocation (tokenno);
10633 : /*
10634 : Follow the Quadruple rules:
10635 : */
10636 16981 : M2GCCDeclare_DeclareConstant (rightpos, right); /* Checks to see whether it is a constant
10637 : and if necessary declare it. */
10638 16981 : M2GCCDeclare_DeclareConstructor (rightpos, quad, right); /* Checks to see whether it is a constant
10639 : and if necessary declare it. */
10640 16981 : if (SymbolTable_IsConstString (right))
10641 : {
10642 0 : M2Error_InternalError ((const char *) "not expecting to index through a constant string", 48);
10643 : }
10644 16981 : else if (M2Options_StrictTypeChecking && (! (M2Check_AssignmentTypeCompatible (indrxpos, (const char *) "", 0, left, SymbolTable_GetType (right), true))))
10645 : {
10646 : /* avoid dangling else. */
10647 0 : M2MetaError_MetaErrorT2 (tokenno, (const char *) "assignment check caught mismatch between {%1Ead} and {%2ad}", 59, left, right);
10648 0 : M2Quads_SubQuad (quad);
10649 : }
10650 : else
10651 : {
10652 : /* avoid dangling else. */
10653 : /*
10654 : Mem[op1] := Mem[Mem[op3]]
10655 : */
10656 16981 : m2statement_BuildAssignmentStatement (location, SymbolConversion_Mod2Gcc (left), m2expr_BuildIndirect (location, SymbolConversion_Mod2Gcc (right), SymbolConversion_Mod2Gcc (type)));
10657 : }
10658 16981 : }
10659 :
10660 :
10661 : /*
10662 : CodeXIndr - operands for XIndrOp are: left type right.
10663 : *left = right. The second operand is the type of the data being
10664 : indirectly copied.
10665 : */
10666 :
10667 43588 : static void CodeXIndr (unsigned int quad)
10668 : {
10669 43588 : bool constExpr;
10670 43588 : bool overflowChecking;
10671 43588 : M2Quads_QuadOperator op;
10672 43588 : unsigned int tokenno;
10673 43588 : unsigned int left;
10674 43588 : unsigned int type;
10675 43588 : unsigned int right;
10676 43588 : unsigned int leftpos;
10677 43588 : unsigned int rightpos;
10678 43588 : unsigned int typepos;
10679 43588 : unsigned int xindrpos;
10680 43588 : tree length;
10681 43588 : tree newstr;
10682 43588 : location_t location;
10683 :
10684 43588 : M2Quads_GetQuadOtok (quad, &xindrpos, &op, &left, &type, &right, &overflowChecking, &constExpr, &leftpos, &typepos, &rightpos);
10685 43588 : tokenno = M2LexBuf_MakeVirtualTok (xindrpos, leftpos, rightpos);
10686 43588 : location = M2LexBuf_TokenToLocation (tokenno);
10687 43588 : type = SymbolTable_SkipType (type);
10688 43588 : M2GCCDeclare_DeclareConstant (rightpos, right);
10689 43588 : M2GCCDeclare_DeclareConstructor (rightpos, quad, right);
10690 43588 : if (M2Options_StrictTypeChecking && (! (M2Check_AssignmentTypeCompatible (xindrpos, (const char *) "", 0, SymbolTable_GetType (left), right, true))))
10691 : {
10692 0 : M2MetaError_MetaErrorT2 (tokenno, (const char *) "assignment check caught mismatch between {%1Ead} and {%2ad}", 59, left, right);
10693 0 : M2Quads_SubQuad (quad);
10694 : }
10695 43588 : if (SymbolTable_IsProcType (SymbolTable_SkipType (type)))
10696 : {
10697 31904 : m2statement_BuildAssignmentStatement (location, m2expr_BuildIndirect (location, SymbolConversion_Mod2Gcc (left), m2type_GetPointerType ()), SymbolConversion_Mod2Gcc (right));
10698 : }
10699 11684 : else if (((SymbolTable_IsConstString (right)) && ((SymbolTable_GetStringLength (rightpos, right)) == 0)) && ((SymbolTable_GetMode (left)) == SymbolTable_LeftValue))
10700 : {
10701 : /* avoid dangling else. */
10702 : /*
10703 : no need to check for type errors,
10704 : but we handle nul string as a special case as back end
10705 : complains if we pass through a "" and ask it to copy the
10706 : contents.
10707 : */
10708 12 : m2statement_BuildAssignmentStatement (location, m2expr_BuildIndirect (location, M2GenGCC_LValueToGenericPtr (location, left), SymbolConversion_Mod2Gcc (M2Base_Char)), M2GenGCC_StringToChar (SymbolConversion_Mod2Gcc (right), M2Base_Char, right));
10709 : }
10710 11672 : else if ((SymbolTable_IsConstString (right)) && ((SymbolTable_SkipTypeAndSubrange (SymbolTable_GetType (left))) != M2Base_Char))
10711 : {
10712 : /* avoid dangling else. */
10713 42 : if (! (M2GenGCC_PrepareCopyString (tokenno, &length, &newstr, right, type)))
10714 : {
10715 0 : M2MetaError_MetaErrorT2 (M2LexBuf_MakeVirtualTok (xindrpos, leftpos, rightpos), (const char *) "string constant {%1Ea} is too large to be assigned to the array {%2ad}", 70, right, left);
10716 : }
10717 42 : m2type_AddStatement (location, MaybeDebugBuiltinMemcpy (location, SymbolConversion_Mod2Gcc (left), m2expr_BuildAddr (location, newstr, false), length));
10718 : }
10719 : else
10720 : {
10721 : /* avoid dangling else. */
10722 11630 : m2statement_BuildAssignmentStatement (location, m2expr_BuildIndirect (location, SymbolConversion_Mod2Gcc (left), SymbolConversion_Mod2Gcc (type)), ConvertRHS (SymbolConversion_Mod2Gcc (right), type, right));
10723 : }
10724 43588 : }
10725 :
10726 :
10727 : /*
10728 : InitBuiltinSyms -
10729 : */
10730 :
10731 97594548 : static void InitBuiltinSyms (unsigned int tok)
10732 : {
10733 97594548 : if (Memset == SymbolTable_NulSym)
10734 : {
10735 14662 : Memset = SymbolTable_FromModuleGetSym (tok, NameKey_MakeKey ((const char *) "memset", 6), M2Batch_MakeDefinitionSource (tok, NameKey_MakeKey ((const char *) "Builtins", 8)));
10736 : }
10737 97594548 : if (Memcpy == SymbolTable_NulSym)
10738 : {
10739 14662 : Memcpy = SymbolTable_FromModuleGetSym (tok, NameKey_MakeKey ((const char *) "memcpy", 6), M2Batch_MakeDefinitionSource (tok, NameKey_MakeKey ((const char *) "Builtins", 8)));
10740 : }
10741 97594548 : }
10742 :
10743 :
10744 : /*
10745 : gdbhook - a debugger convenience hook.
10746 : */
10747 :
10748 0 : static void gdbhook (void)
10749 : {
10750 0 : }
10751 :
10752 :
10753 : /*
10754 : BreakWhenQuadTranslated - to be called interactively by gdb.
10755 : */
10756 :
10757 15674 : static void BreakWhenQuadTranslated (unsigned int quad)
10758 : {
10759 15674 : BreakQuad = quad;
10760 0 : }
10761 :
10762 :
10763 : /*
10764 : CheckBreak - if quad = BreakQuad then call gdbhook.
10765 : */
10766 :
10767 0 : static void CheckBreak (unsigned int quad)
10768 : {
10769 0 : if (quad == BreakQuad)
10770 : {
10771 0 : gdbhook ();
10772 : }
10773 0 : }
10774 :
10775 :
10776 : /*
10777 : Init -
10778 : */
10779 :
10780 15674 : static void Init (void)
10781 : {
10782 : /* You might want to add the option -fm2-debug-trace=quad to cc1gm2 if
10783 : contenplating interactively debugging cc1gm2 using the scheme below. */
10784 15674 : BreakWhenQuadTranslated (0); /* Disable the interactive quad watch. */
10785 : /* To examine when a quad is about to be converted into a gimple tree
10786 : run cc1gm2 from gdb and set a break point on gdbhook.
10787 : (gdb) break gdbhook
10788 : (gdb) run
10789 : Now below interactively call BreakWhenQuadTranslated with the quad
10790 : under investigation. */
10791 15674 : gdbhook ();
10792 : /* Now is the time to interactively call gdb, for example:
10793 : (gdb) print BreakWhenQuadTranslated (1234)
10794 : (gdb) cont
10795 : and you will arrive at gdbhook when this quad is about to be translated. */
10796 15674 : Memset = SymbolTable_NulSym;
10797 15674 : Memcpy = SymbolTable_NulSym;
10798 15674 : UnboundedLabelNo = 0;
10799 15674 : CurrentQuadToken = 0;
10800 15674 : SetTemporaryNo = 0;
10801 15674 : ScopeStack = M2StackWord_InitStackWord ();
10802 15674 : }
10803 :
10804 :
10805 : /*
10806 : ConvertQuadsToTree - runs through the quadruple list and converts it into
10807 : the GCC tree structure.
10808 : */
10809 :
10810 410599 : extern "C" void M2GenGCC_ConvertQuadsToTree (unsigned int Start, unsigned int End)
10811 : {
10812 4311506 : do {
10813 4311506 : CodeStatement (Start);
10814 4311494 : Start = M2Quads_GetNextQuad (Start);
10815 4311494 : } while (! ((Start > End) || (Start == 0)));
10816 410587 : }
10817 :
10818 :
10819 : /*
10820 : ResolveConstantExpressions - resolves constant expressions from the quadruple list.
10821 : It returns TRUE if one or more constants were folded.
10822 : When a constant symbol value is solved, the call back
10823 : p(sym) is invoked.
10824 : */
10825 :
10826 93215097 : extern "C" bool M2GenGCC_ResolveConstantExpressions (M2GCCDeclare_WalkAction p, M2BasicBlock_BasicBlock bb)
10827 : {
10828 93215097 : unsigned int tokenno;
10829 93215097 : unsigned int quad;
10830 93215097 : M2Quads_QuadOperator op;
10831 93215097 : unsigned int op1;
10832 93215097 : unsigned int op2;
10833 93215097 : unsigned int op3;
10834 93215097 : unsigned int op1pos;
10835 93215097 : unsigned int op2pos;
10836 93215097 : unsigned int op3pos;
10837 93215097 : bool Changed;
10838 93215097 : unsigned int start;
10839 93215097 : unsigned int end;
10840 :
10841 93215097 : InitBuiltinSyms (M2LexBuf_BuiltinTokenNo);
10842 93215097 : start = M2BasicBlock_GetBasicBlockStart (bb);
10843 93215097 : end = M2BasicBlock_GetBasicBlockEnd (bb);
10844 93215097 : Changed = false;
10845 93360408 : do {
10846 93360408 : NoChange = true;
10847 93360408 : quad = start;
10848 266633881 : while ((quad <= end) && (quad != 0))
10849 : {
10850 173273647 : tokenno = CurrentQuadToken;
10851 173273647 : if (tokenno == 0)
10852 : {
10853 3647374 : tokenno = M2Quads_QuadToTokenNo (quad);
10854 : }
10855 173273647 : if (M2Options_GetDebugTraceQuad ())
10856 : {
10857 0 : M2Printf_printf0 ((const char *) "examining fold: ", 16);
10858 0 : M2Quads_DisplayQuad (quad);
10859 : }
10860 173273647 : M2Quads_GetQuadtok (quad, &op, &op1, &op2, &op3, &op1pos, &op2pos, &op3pos);
10861 173273647 : switch (op)
10862 : {
10863 9564 : case M2Quads_StandardFunctionOp:
10864 9564 : FoldStandardFunction (tokenno, p, quad, op1, op2, op3);
10865 9564 : break;
10866 :
10867 28900 : case M2Quads_BuiltinConstOp:
10868 28900 : FoldBuiltinConst (tokenno, p, quad, op1, op3);
10869 28900 : break;
10870 :
10871 360 : case M2Quads_BuiltinTypeInfoOp:
10872 360 : FoldBuiltinTypeInfo (tokenno, p, quad, op1, op2, op3);
10873 360 : break;
10874 :
10875 14918 : case M2Quads_LogicalOrOp:
10876 14918 : FoldSetOr (tokenno, p, quad, op1, op2, op3);
10877 14918 : break;
10878 :
10879 3684 : case M2Quads_LogicalAndOp:
10880 3684 : FoldSetAnd (tokenno, p, quad, op1, op2, op3);
10881 3684 : break;
10882 :
10883 664 : case M2Quads_LogicalXorOp:
10884 664 : FoldSymmetricDifference (tokenno, p, quad, op1, op2, op3);
10885 664 : break;
10886 :
10887 5106768 : case M2Quads_BecomesOp:
10888 5106768 : FoldBecomes (p, bb, quad);
10889 5106768 : break;
10890 :
10891 0 : case M2Quads_ArithAddOp:
10892 0 : FoldArithAdd (op1pos, p, quad, op1, op2, op3);
10893 0 : break;
10894 :
10895 402082 : case M2Quads_AddOp:
10896 402082 : FoldAdd (op1pos, p, quad, op1, op2, op3);
10897 402082 : break;
10898 :
10899 166952 : case M2Quads_SubOp:
10900 166952 : FoldSub (op1pos, p, quad, op1, op2, op3);
10901 166952 : break;
10902 :
10903 110456 : case M2Quads_MultOp:
10904 110456 : FoldMult (op1pos, p, quad, op1, op2, op3);
10905 110456 : break;
10906 :
10907 15176 : case M2Quads_DivM2Op:
10908 15176 : FoldDivM2 (op1pos, p, quad, op1, op2, op3);
10909 15176 : break;
10910 :
10911 26130 : case M2Quads_ModM2Op:
10912 26130 : FoldModM2 (op1pos, p, quad, op1, op2, op3);
10913 26130 : break;
10914 :
10915 11100 : case M2Quads_DivTruncOp:
10916 11100 : FoldDivTrunc (op1pos, p, quad, op1, op2, op3);
10917 11100 : break;
10918 :
10919 96 : case M2Quads_ModTruncOp:
10920 96 : FoldModTrunc (op1pos, p, quad, op1, op2, op3);
10921 96 : break;
10922 :
10923 0 : case M2Quads_DivCeilOp:
10924 0 : FoldDivCeil (op1pos, p, quad, op1, op2, op3);
10925 0 : break;
10926 :
10927 0 : case M2Quads_ModCeilOp:
10928 0 : FoldModCeil (op1pos, p, quad, op1, op2, op3);
10929 0 : break;
10930 :
10931 0 : case M2Quads_DivFloorOp:
10932 0 : FoldDivFloor (op1pos, p, quad, op1, op2, op3);
10933 0 : break;
10934 :
10935 0 : case M2Quads_ModFloorOp:
10936 0 : FoldModFloor (op1pos, p, quad, op1, op2, op3);
10937 0 : break;
10938 :
10939 39843 : case M2Quads_NegateOp:
10940 39843 : FoldNegate (op1pos, p, quad, op1, op3);
10941 39843 : break;
10942 :
10943 7484 : case M2Quads_SizeOp:
10944 7484 : FoldSize (tokenno, p, quad, op1, op2, op3);
10945 7484 : break;
10946 :
10947 : case M2Quads_RecordFieldOp:
10948 : FoldRecordField (tokenno, p, quad, op1, op2, op3);
10949 : break;
10950 :
10951 1235639 : case M2Quads_HighOp:
10952 1235639 : FoldHigh (tokenno, p, quad, op1, op2, op3);
10953 1235639 : break;
10954 :
10955 10076 : case M2Quads_ElementSizeOp:
10956 10076 : FoldElementSize (tokenno, p, quad, op1, op2);
10957 10076 : break;
10958 :
10959 361350 : case M2Quads_ConvertOp:
10960 361350 : FoldConvert (tokenno, p, quad, op1, op2, op3);
10961 361350 : break;
10962 :
10963 12194 : case M2Quads_CoerceOp:
10964 12194 : FoldCoerce (tokenno, p, quad, op1, op2, op3);
10965 12194 : break;
10966 :
10967 1500 : case M2Quads_CastOp:
10968 1500 : FoldCast (tokenno, p, quad, op1, op2, op3);
10969 1500 : break;
10970 :
10971 27730 : case M2Quads_InclOp:
10972 27730 : FoldIncl (tokenno, p, quad, op1, op3);
10973 27730 : break;
10974 :
10975 15594 : case M2Quads_ExclOp:
10976 15594 : FoldExcl (tokenno, p, quad, op1, op3);
10977 15594 : break;
10978 :
10979 687321 : case M2Quads_IfEquOp:
10980 687321 : FoldIfEqu (tokenno, quad, op1, op2, op3);
10981 687321 : break;
10982 :
10983 343129 : case M2Quads_IfNotEquOp:
10984 343129 : FoldIfNotEqu (tokenno, quad, op1, op2, op3);
10985 343129 : break;
10986 :
10987 37942 : case M2Quads_IfLessOp:
10988 37942 : FoldIfLess (tokenno, quad, op1, op2, op3);
10989 37942 : break;
10990 :
10991 32162 : case M2Quads_IfLessEquOp:
10992 32162 : FoldIfLessEqu (tokenno, quad, op1, op2, op3);
10993 32162 : break;
10994 :
10995 29184 : case M2Quads_IfGreOp:
10996 29184 : FoldIfGre (tokenno, quad, op1, op2, op3);
10997 29184 : break;
10998 :
10999 47650 : case M2Quads_IfGreEquOp:
11000 47650 : FoldIfGreEqu (tokenno, quad, op1, op2, op3);
11001 47650 : break;
11002 :
11003 53420 : case M2Quads_IfInOp:
11004 53420 : FoldIfIn (tokenno, quad, op1, op2, op3);
11005 53420 : break;
11006 :
11007 9464 : case M2Quads_IfNotInOp:
11008 9464 : FoldIfNotIn (tokenno, quad, op1, op2, op3);
11009 9464 : break;
11010 :
11011 27654 : case M2Quads_LogicalShiftOp:
11012 27654 : FoldSetShift (tokenno, p, quad, op1, op2, op3);
11013 27654 : break;
11014 :
11015 23892 : case M2Quads_LogicalRotateOp:
11016 23892 : FoldSetRotate (tokenno, p, quad, op1, op2, op3);
11017 23892 : break;
11018 :
11019 7602937 : case M2Quads_ParamOp:
11020 7602937 : FoldBuiltinFunction (tokenno, p, quad, op1, op2, op3);
11021 7602937 : break;
11022 :
11023 14390657 : case M2Quads_RangeCheckOp:
11024 14390657 : FoldRange (tokenno, quad, op3);
11025 14390657 : break;
11026 :
11027 9988384 : case M2Quads_StatementNoteOp:
11028 9988384 : FoldStatementNote (op3);
11029 9988384 : break;
11030 :
11031 72 : case M2Quads_StringLengthOp:
11032 72 : FoldStringLength (quad, p);
11033 72 : break;
11034 :
11035 34913 : case M2Quads_StringConvertM2nulOp:
11036 34913 : FoldStringConvertM2nul (quad, p);
11037 34913 : break;
11038 :
11039 9733 : case M2Quads_StringConvertCnulOp:
11040 9733 : FoldStringConvertCnul (quad, p);
11041 9733 : break;
11042 :
11043 15326 : case M2Quads_LastForIteratorOp:
11044 15326 : FoldLastForIterator (quad, p);
11045 15326 : break;
11046 :
11047 :
11048 : default:
11049 : break;
11050 : }
11051 : /* Ignore quadruple as it is not associated with a constant expression. */
11052 173273473 : quad = M2Quads_GetNextQuad (quad);
11053 : }
11054 93360234 : if (! NoChange)
11055 : {
11056 145311 : Changed = true;
11057 : }
11058 93360234 : } while (! (NoChange));
11059 93214923 : return Changed;
11060 : /* static analysis guarentees a RETURN statement will be used before here. */
11061 : __builtin_unreachable ();
11062 : }
11063 :
11064 :
11065 : /*
11066 : GetHighFromUnbounded - returns a Tree containing the value of
11067 : param.HIGH.
11068 : */
11069 :
11070 21732 : extern "C" tree M2GenGCC_GetHighFromUnbounded (location_t location, unsigned int dim, unsigned int param)
11071 : {
11072 21732 : unsigned int UnboundedType;
11073 21732 : unsigned int ArrayType;
11074 21732 : unsigned int HighField;
11075 21732 : tree HighTree;
11076 21732 : unsigned int accessibleDim;
11077 :
11078 : /* remainingDim : CARDINAL ; */
11079 21732 : UnboundedType = SymbolTable_GetType (param);
11080 21732 : M2Debug_Assert (SymbolTable_IsUnbounded (UnboundedType));
11081 21732 : ArrayType = SymbolTable_GetType (UnboundedType);
11082 21732 : HighField = SymbolTable_GetUnboundedHighOffset (UnboundedType, dim);
11083 21732 : if (HighField == SymbolTable_NulSym)
11084 : {
11085 : /* It might be a dynamic array of static arrays,
11086 : so lets see if there is an earlier dimension available. */
11087 : accessibleDim = dim;
11088 0 : while ((HighField == SymbolTable_NulSym) && (accessibleDim > 1))
11089 : {
11090 0 : accessibleDim -= 1;
11091 0 : HighField = SymbolTable_GetUnboundedHighOffset (UnboundedType, accessibleDim);
11092 : }
11093 0 : if (HighField == SymbolTable_NulSym)
11094 : {
11095 0 : M2MetaError_MetaError1 ((const char *) "{%EkHIGH} dimension number {%1N} for array does not exist", 57, dim);
11096 0 : return m2expr_GetCardinalZero (location);
11097 : }
11098 : else
11099 : {
11100 0 : HighTree = BuildHighFromStaticArray (location, ArrayType); /* remainingDim, */
11101 0 : if (HighTree == NULL)
11102 : {
11103 0 : M2MetaError_MetaError1 ((const char *) "{%EkHIGH} dimension number {%1N} for array does not exist", 57, dim);
11104 0 : return m2expr_GetCardinalZero (location);
11105 : }
11106 : return HighTree;
11107 : }
11108 : }
11109 : else
11110 : {
11111 21732 : return m2expr_BuildComponentRef (location, SymbolConversion_Mod2Gcc (param), SymbolConversion_Mod2Gcc (HighField));
11112 : }
11113 : /* static analysis guarentees a RETURN statement will be used before here. */
11114 : __builtin_unreachable ();
11115 : }
11116 :
11117 :
11118 : /*
11119 : StringToChar - if type=Char and str is a string (of size <= 1)
11120 : then convert the string into a character constant.
11121 : */
11122 :
11123 1167759 : extern "C" tree M2GenGCC_StringToChar (tree t, unsigned int type, unsigned int str)
11124 : {
11125 1167759 : DynamicStrings_String s;
11126 1167759 : NameKey_Name n;
11127 1167759 : unsigned int tokenno;
11128 1167759 : location_t location;
11129 :
11130 1167759 : tokenno = SymbolTable_GetDeclaredMod (str);
11131 1167759 : location = M2LexBuf_TokenToLocation (tokenno);
11132 1167759 : type = SymbolTable_SkipType (type);
11133 1167759 : if ((type == M2Base_Char) && (SymbolTable_IsConstString (str)))
11134 : {
11135 12774 : M2Debug_Assert (SymbolTable_IsConstStringKnown (str));
11136 12774 : if ((SymbolTable_GetStringLength (tokenno, str)) == 0)
11137 : {
11138 108 : s = DynamicStrings_InitString ((const char *) "", 0);
11139 108 : t = m2type_BuildCharConstant (location, reinterpret_cast <const char * > (s));
11140 108 : s = DynamicStrings_KillString (s);
11141 : }
11142 12666 : else if ((SymbolTable_GetStringLength (tokenno, str)) > 1)
11143 : {
11144 : /* avoid dangling else. */
11145 0 : n = SymbolTable_GetSymName (str);
11146 0 : M2Error_WriteFormat1 ((const char *) "type incompatibility, attempting to use a string ('%a') when a CHAR is expected", 79, (const unsigned char *) &n, (sizeof (n)-1));
11147 0 : s = DynamicStrings_InitString ((const char *) "", 0); /* Do something safe. */
11148 0 : t = m2type_BuildCharConstant (location, reinterpret_cast <const char * > (s)); /* Do something safe. */
11149 : }
11150 12774 : s = DynamicStrings_InitStringCharStar (NameKey_KeyToCharStar (SymbolTable_GetString (str)));
11151 12774 : s = DynamicStrings_Slice (s, 0, 1);
11152 12774 : t = m2type_BuildCharConstant (location, const_cast <const char * > (static_cast <char * > (DynamicStrings_string (s))));
11153 12774 : s = DynamicStrings_KillString (s);
11154 : }
11155 1167759 : return t;
11156 : /* static analysis guarentees a RETURN statement will be used before here. */
11157 : __builtin_unreachable ();
11158 : }
11159 :
11160 :
11161 : /*
11162 : LValueToGenericPtr - returns a Tree representing symbol, sym.
11163 : It coerces a lvalue into an internal pointer type
11164 : */
11165 :
11166 544222 : extern "C" tree M2GenGCC_LValueToGenericPtr (location_t location, unsigned int sym)
11167 : {
11168 544222 : tree t;
11169 :
11170 544222 : t = SymbolConversion_Mod2Gcc (sym);
11171 544222 : if (t == NULL)
11172 : {
11173 0 : M2Error_InternalError ((const char *) "expecting symbol to be resolved", 31);
11174 : }
11175 544222 : if ((SymbolTable_GetMode (sym)) == SymbolTable_LeftValue)
11176 : {
11177 542 : t = m2convert_BuildConvert (location, m2type_GetPointerType (), t, false);
11178 : }
11179 544222 : return t;
11180 : /* static analysis guarentees a RETURN statement will be used before here. */
11181 : __builtin_unreachable ();
11182 : }
11183 :
11184 :
11185 : /*
11186 : ZConstToTypedConst - checks whether op1 and op2 are constants and
11187 : coerces, t, appropriately.
11188 : */
11189 :
11190 8690 : extern "C" tree M2GenGCC_ZConstToTypedConst (tree t, unsigned int op1, unsigned int op2)
11191 : {
11192 8690 : location_t location;
11193 :
11194 8690 : location = M2LexBuf_TokenToLocation (SymbolTable_GetDeclaredMod (op2));
11195 8690 : if ((SymbolTable_IsConst (op1)) && (SymbolTable_IsConst (op2)))
11196 : {
11197 : /* leave, Z type, alone */
11198 : return t;
11199 : }
11200 4110 : else if (SymbolTable_IsConst (op1))
11201 : {
11202 : /* avoid dangling else. */
11203 2830 : if ((SymbolTable_GetMode (op2)) == SymbolTable_LeftValue)
11204 : {
11205 : /* convert, Z type const into type of non constant operand */
11206 0 : return m2convert_BuildConvert (location, m2type_GetPointerType (), t, false);
11207 : }
11208 : else
11209 : {
11210 : /* convert, Z type const into type of non constant operand */
11211 2830 : return m2convert_BuildConvert (location, SymbolConversion_Mod2Gcc (FindType (op2)), t, false);
11212 : }
11213 : }
11214 1280 : else if (SymbolTable_IsConst (op2))
11215 : {
11216 : /* avoid dangling else. */
11217 0 : if ((SymbolTable_GetMode (op1)) == SymbolTable_LeftValue)
11218 : {
11219 : /* convert, Z type const into type of non constant operand */
11220 0 : return m2convert_BuildConvert (location, m2type_GetPointerType (), t, false);
11221 : }
11222 : else
11223 : {
11224 : /* convert, Z type const into type of non constant operand */
11225 0 : return m2convert_BuildConvert (location, SymbolConversion_Mod2Gcc (FindType (op1)), t, false);
11226 : }
11227 : }
11228 : else
11229 : {
11230 : /* avoid dangling else. */
11231 : /* neither operands are constants, leave alone */
11232 : return t;
11233 : }
11234 : /* static analysis guarentees a RETURN statement will be used before here. */
11235 : __builtin_unreachable ();
11236 : }
11237 :
11238 :
11239 : /*
11240 : PrepareCopyString - returns two trees:
11241 : length number of bytes to be copied (including the nul if room)
11242 : srcTreeType the new string type (with the extra nul character).
11243 :
11244 : Pre condition: destStrType the dest type string.
11245 : src is the original string (without a nul)
11246 : to be copied.
11247 : Post condition: TRUE or FALSE is returned.
11248 : if true length and srcTreeType will be assigned
11249 : else length is set to the maximum length to be
11250 : copied and srcTree is set to the max length
11251 : which fits in dest.
11252 : */
11253 :
11254 3312 : extern "C" bool M2GenGCC_PrepareCopyString (unsigned int tokenno, tree *length, tree *srcTree, unsigned int src, unsigned int destStrType)
11255 : {
11256 3312 : location_t location;
11257 3312 : int intLength;
11258 :
11259 3312 : location = M2LexBuf_TokenToLocation (tokenno);
11260 3312 : M2Debug_Assert (SymbolTable_IsArray (SymbolTable_SkipType (destStrType)));
11261 : /* Handle string assignments:
11262 : VAR
11263 : str: ARRAY [0..10] OF CHAR ;
11264 : ch : CHAR ;
11265 :
11266 : str := 'abcde' but not ch := 'a'
11267 : */
11268 3312 : if ((SymbolTable_GetType (src)) == M2Base_Char)
11269 : {
11270 : /* avoid dangling else. */
11271 : /*
11272 : * Create string from char and add nul to the end, nul is
11273 : * added by BuildStringConstant. In modula-2 an array must
11274 : * have at least one element.
11275 : */
11276 192 : (*length) = m2expr_GetIntegerOne (location);
11277 192 : M2ALU_PushIntegerTree (FindSize (tokenno, src));
11278 192 : M2ALU_PushIntegerTree (FindSize (tokenno, destStrType));
11279 192 : if (M2ALU_Less (tokenno))
11280 : {
11281 : /* There is room for the extra <nul> character. */
11282 156 : (*length) = m2expr_BuildAdd (location, (*length), m2expr_GetIntegerOne (location), false);
11283 : }
11284 : }
11285 : else
11286 : {
11287 3120 : M2ALU_PushIntegerTree (FindSize (tokenno, src));
11288 3120 : M2ALU_PushIntegerTree (FindSize (tokenno, destStrType));
11289 3120 : if (M2ALU_Less (tokenno))
11290 : {
11291 : /* There is room for the extra <nul> character. */
11292 2952 : (*length) = m2expr_BuildAdd (location, FindSize (tokenno, src), m2expr_GetIntegerOne (location), false);
11293 2952 : (*srcTree) = SymbolConversion_Mod2Gcc (src);
11294 : }
11295 : else
11296 : {
11297 : /* We need to truncate the <nul> at least. */
11298 168 : (*length) = FindSize (tokenno, destStrType);
11299 168 : M2ALU_PushIntegerTree (FindSize (tokenno, src));
11300 168 : M2ALU_PushIntegerTree ((*length));
11301 : /* Greater or Equal so return max characters in the array. */
11302 168 : if (M2ALU_Gre (tokenno))
11303 : {
11304 : /* Create a new string without non nul characters to be gimple safe.
11305 : But return FALSE indicating an overflow. */
11306 12 : intLength = m2expr_GetCstInteger ((*length));
11307 12 : (*srcTree) = m2decl_BuildStringConstant (const_cast <const char * > (static_cast <char * > (NameKey_KeyToCharStar (SymbolTable_GetString (src)))), intLength);
11308 12 : (*srcTree) = m2convert_ConvertString (SymbolConversion_Mod2Gcc (destStrType), (*srcTree));
11309 12 : return false;
11310 : }
11311 : }
11312 : }
11313 3300 : intLength = m2expr_GetCstInteger ((*length));
11314 3300 : (*srcTree) = m2decl_BuildStringConstant (const_cast <const char * > (static_cast <char * > (NameKey_KeyToCharStar (SymbolTable_GetString (src)))), intLength);
11315 3300 : (*srcTree) = m2convert_ConvertString (SymbolConversion_Mod2Gcc (destStrType), (*srcTree));
11316 3300 : return true;
11317 : /* static analysis guarentees a RETURN statement will be used before here. */
11318 : __builtin_unreachable ();
11319 : }
11320 :
11321 15674 : extern "C" void _M2_M2GenGCC_init (__attribute__((unused)) int argc, __attribute__((unused)) char *argv[], __attribute__((unused)) char *envp[])
11322 : {
11323 15674 : Init ();
11324 15674 : }
11325 :
11326 0 : extern "C" void _M2_M2GenGCC_fini (__attribute__((unused)) int argc, __attribute__((unused)) char *argv[], __attribute__((unused)) char *envp[])
11327 : {
11328 0 : }
|