1 /**
2  * Compiler implementation of the
3  * $(LINK2 https://www.dlang.org, D programming language).
4  *
5  * Copyright:   Copyright (C) 1985-1998 by Symantec
6  *              Copyright (C) 2000-2023 by The D Language Foundation, All Rights Reserved
7  * Authors:     $(LINK2 https://www.digitalmars.com, Walter Bright)
8  * License:     $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
9  * Source:      https://github.com/dlang/dmd/blob/master/src/dmd/backend/dtype.d
10  */
11 
12 module dmd.backend.dtype;
13 
14 version (SCPP)
15 {
16     version = COMPILE;
17     version = SCPP_HTOD;
18 }
19 version (HTOD)
20 {
21     version = COMPILE;
22     version = SCPP_HTOD;
23 }
24 version (MARS)
25     version = COMPILE;
26 
27 
28 version (COMPILE)
29 {
30 import core.stdc.stdio;
31 import core.stdc.stdlib;
32 import core.stdc.string;
33 
34 import dmd.backend.cdef;
35 import dmd.backend.cc;
36 import dmd.backend.dlist;
37 import dmd.backend.el;
38 import dmd.backend.global;
39 import dmd.backend.mem;
40 import dmd.backend.oper;
41 import dmd.backend.ty;
42 import dmd.backend.type;
43 
44 version (SCPP_HTOD)
45 {
46     import dtoken;
47     import msgs2;
48     import parser;
49     import precomp;
50 }
51 
52 extern (C++):
53 
54 nothrow:
55 @safe:
56 
57 alias MEM_PH_MALLOC = mem_malloc;
58 alias MEM_PH_CALLOC = mem_calloc;
59 alias MEM_PH_FREE = mem_free;
60 alias MEM_PH_STRDUP = mem_strdup;
61 alias MEM_PARF_MALLOC = mem_malloc;
62 alias MEM_PARF_CALLOC = mem_calloc;
63 alias MEM_PARF_REALLOC = mem_realloc;
64 alias MEM_PARF_FREE = mem_free;
65 alias MEM_PARF_STRDUP = mem_strdup;
66 
67 version (SCPP_HTOD)
68     @trusted
69     struct_t* struct_calloc();
70 else
71     @trusted
72     struct_t* struct_calloc() { return cast(struct_t*) mem_calloc(struct_t.sizeof); }
73 
74 int REGSIZE();
75 
76 private __gshared
77 {
78     type *type_list;          // free list of types
79     param_t *param_list;      // free list of params
80 
81     int type_num,type_max;   /* gather statistics on # of types      */
82 }
83 
84 __gshared
85 {
86     type*[TYMAX] tstypes;
87     type*[TYMAX] tsptr2types;
88 
89     type* tstrace,tsclib,tsjlib,tsdlib,
90             tslogical;
91     type* tspvoid,tspcvoid;
92     type* tsptrdiff, tssize;
93 }
94 
95 /*******************************
96  * Compute size of type in bytes.
97  * Mark size as known after error message if it is not known.
98  * Instantiate templates as needed to compute size.
99  * Params:
100  *      t = type
101  * Returns:
102  *      size
103  */
104 
105 version (SCPP_HTOD)
106 {
107 @trusted
108 targ_size_t type_size(type* t)
109 {
110     switch (tybasic(t.Tty))
111     {
112         case TYarray:
113             if (t.Tflags & TFsizeunknown)
114             {
115                 synerr(EM_unknown_size,"array".ptr);    /* size of array is unknown     */
116                 t.Tflags &= ~TFsizeunknown;
117             }
118             type_size(t.Tnext);
119             break;
120 
121         case TYstruct:
122             auto ts = t.Ttag.Stype;    // find main instance
123                                        // (for const struct X)
124             if (ts.Tflags & TFsizeunknown)
125             {
126                 template_instantiate_forward(ts.Ttag);
127                 if (ts.Tflags & TFsizeunknown)
128                     synerr(EM_unknown_size,ts.Tty & TYstruct ? prettyident(ts.Ttag) : "struct");
129                 ts.Tflags &= ~TFsizeunknown;
130             }
131             break;
132 
133         case TYenum:
134             if (t.Ttag.Senum.SEflags & SENforward)
135                 synerr(EM_unknown_size, prettyident(t.Ttag));
136             type_size(t.Tnext);
137             break;
138 
139         default:
140             break;
141     }
142     return type_size(cast(const)t);
143 }
144 }
145 
146 /***********************
147  * Compute size of type in bytes.
148  * Params:
149  *      t = type
150  * Returns:
151  *      size
152  */
153 @trusted
154 targ_size_t type_size(const type *t)
155 {   targ_size_t s;
156     tym_t tyb;
157 
158     type_debug(t);
159     tyb = tybasic(t.Tty);
160 
161     debug if (tyb >= TYMAX)
162         /*type_print(t),*/
163         printf("tyb = x%x\n", tyb);
164 
165     assert(tyb < TYMAX);
166     s = _tysize[tyb];
167     if (s == cast(targ_size_t) -1)
168     {
169         switch (tyb)
170         {
171             // in case program plays games with function pointers
172             case TYffunc:
173             case TYfpfunc:
174             case TYfsfunc:
175             case TYf16func:
176             case TYhfunc:
177             case TYnfunc:       /* in case program plays games with function pointers */
178             case TYnpfunc:
179             case TYnsfunc:
180             case TYifunc:
181             case TYjfunc:
182 version (SCPP_HTOD)
183 {
184             case TYmfunc:
185                 if (config.ansi_c)
186                     synerr(EM_unknown_size,"function".ptr); /* size of function is not known */
187 }
188                 s = 1;
189                 break;
190             case TYarray:
191             {
192                 if (t.Tflags & TFsizeunknown)
193                 {
194 version (SCPP_HTOD)
195 {
196                     synerr(EM_unknown_size,"array".ptr);    /* size of array is unknown     */
197 }
198                 }
199                 if (t.Tflags & TFvla)
200                 {
201                     s = _tysize[pointertype];
202                     break;
203                 }
204                 s = type_size(t.Tnext);
205                 uint u = cast(uint)t.Tdim * cast(uint) s;
206 version (SCPP_HTOD)
207 {
208                 type_chksize(u);
209 }
210 else version (MARS)
211 {
212                 if (t.Tdim && ((u / t.Tdim) != s || cast(int)u < 0))
213                     assert(0);          // overflow should have been detected in front end
214 }
215 else
216 {
217                 static assert(0);
218 }
219                 s = u;
220                 break;
221             }
222             case TYstruct:
223             {
224                 auto ts = t.Ttag.Stype;     // find main instance
225                                             // (for const struct X)
226                 assert(ts.Ttag);
227                 s = ts.Ttag.Sstruct.Sstructsize;
228                 break;
229             }
230 version (SCPP_HTOD)
231 {
232             case TYenum:
233                 if (t.Ttag.Senum.SEflags & SENforward)
234                     synerr(EM_unknown_size, prettyident(cast(Symbol*)t.Ttag));
235                 s = type_size(t.Tnext);
236                 break;
237 }
238             case TYvoid:
239 version (SCPP_HTOD) static if (TARGET_WINDOS)   // GNUC allows it, so we will, too
240 {
241                 synerr(EM_void_novalue);        // voids have no value
242 }
243                 s = 1;
244                 break;
245 
246             case TYref:
247 version (MARS)
248 {
249                 s = tysize(TYnptr);
250                 break;
251 }
252 version (SCPP_HTOD)
253 {
254             case TYmemptr:
255             case TYvtshape:
256                 s = tysize(tym_conv(t));
257                 break;
258 
259             case TYident:
260                 synerr(EM_unknown_size, t.Tident);
261                 s = 1;
262                 break;
263 }
264 
265             default:
266                 debug printf("%s\n", tym_str(t.Tty));
267                 assert(0);
268         }
269     }
270     return s;
271 }
272 
273 /********************************
274  * Return the size of a type for alignment purposes.
275  */
276 
277 @trusted
278 uint type_alignsize(type *t)
279 {   targ_size_t sz;
280 
281 L1:
282     type_debug(t);
283 
284     sz = tyalignsize(t.Tty);
285     if (sz == cast(targ_size_t)-1)
286     {
287         switch (tybasic(t.Tty))
288         {
289             case TYarray:
290                 if (t.Tflags & TFsizeunknown)
291                     goto err1;
292                 t = t.Tnext;
293                 goto L1;
294             case TYstruct:
295                 t = t.Ttag.Stype;         // find main instance
296                                             // (for const struct X)
297                 if (t.Tflags & TFsizeunknown)
298                     goto err1;
299                 sz = t.Ttag.Sstruct.Salignsize;
300                 if (sz > t.Ttag.Sstruct.Sstructalign + 1)
301                     sz = t.Ttag.Sstruct.Sstructalign + 1;
302                 break;
303 
304             case TYldouble:
305                 assert(0);
306 
307             case TYcdouble:
308                 sz = 8;         // not 16
309                 break;
310 
311             default:
312             err1:                   // let type_size() handle error messages
313                 sz = type_size(t);
314                 break;
315         }
316     }
317 
318     //printf("type_alignsize() = %d\n", sz);
319     return cast(uint)sz;
320 }
321 
322 /***********************************
323  * Compute special zero sized struct.
324  * Params:
325  *      t = type of parameter
326  *      tyf = function type
327  * Returns:
328  *      true if it is
329  */
330 @trusted
331 bool type_zeroSize(type *t, tym_t tyf)
332 {
333     if (tyf != TYjfunc && config.exe & (EX_FREEBSD | EX_OPENBSD | EX_OSX))
334     {
335         /* Use clang convention for 0 size structs
336          */
337         if (t && tybasic(t.Tty) == TYstruct)
338         {
339             type *ts = t.Ttag.Stype;     // find main instance
340                                            // (for const struct X)
341             if (ts.Tflags & TFsizeunknown)
342             {
343 version (SCPP_HTOD)
344 {
345                 template_instantiate_forward(ts.Ttag);
346                 if (ts.Tflags & TFsizeunknown)
347                     synerr(EM_unknown_size,ts.Tty & TYstruct ? prettyident(ts.Ttag) : "struct");
348                 ts.Tflags &= ~TFsizeunknown;
349 }
350             }
351             if (ts.Ttag.Sstruct.Sflags & STR0size)
352 //{ printf("0size\n"); type_print(t); *(char*)0=0;
353                 return true;
354 //}
355         }
356     }
357     return false;
358 }
359 
360 /*********************************
361  * Compute the size of a single parameter.
362  * Params:
363  *      t = type of parameter
364  *      tyf = function type
365  * Returns:
366  *      size in bytes
367  */
368 uint type_parameterSize(type *t, tym_t tyf)
369 {
370     if (type_zeroSize(t, tyf))
371         return 0;
372     return cast(uint)type_size(t);
373 }
374 
375 /*****************************
376  * Compute the total size of parameters for function call.
377  * Used for stdcall name mangling.
378  * Note that hidden parameters do not contribute to size.
379  * Params:
380  *   t = function type
381  * Returns:
382  *   total stack usage in bytes
383  */
384 
385 @trusted
386 uint type_paramsize(type *t)
387 {
388     targ_size_t sz = 0;
389     if (tyfunc(t.Tty))
390     {
391         for (param_t *p = t.Tparamtypes; p; p = p.Pnext)
392         {
393             const size_t n = type_parameterSize(p.Ptype, tybasic(t.Tty));
394             sz += _align(REGSIZE,n);       // align to REGSIZE boundary
395         }
396     }
397     return cast(uint)sz;
398 }
399 
400 /*****************************
401  * Create a type & initialize it.
402  * Input:
403  *      ty = TYxxxx
404  * Returns:
405  *      pointer to newly created type.
406  */
407 
408 @trusted
409 type *type_alloc(tym_t ty)
410 {   type *t;
411 
412     assert(tybasic(ty) != TYtemplate);
413     if (type_list)
414     {   t = type_list;
415         type_list = t.Tnext;
416     }
417     else
418         t = cast(type *) mem_fmalloc(type.sizeof);
419     *t = type();
420     t.Tty = ty;
421 version (SRCPOS_4TYPES)
422 {
423     if (PARSER && config.fulltypes)
424         t.Tsrcpos = getlinnum();
425 }
426 debug
427 {
428     t.id = type.IDtype;
429     type_num++;
430     if (type_num > type_max)
431         type_max = type_num;
432 }
433     //printf("type_alloc() = %p %s\n", t, tym_str(t.Tty));
434     //if (t == (type*)0xB6B744) *(char*)0=0;
435     return t;
436 }
437 
438 /*************************************
439  * Allocate a TYtemplate.
440  */
441 
442 version (SCPP_HTOD)
443 {
444 type *type_alloc_template(Symbol *s)
445 {   type *t;
446 
447     t = cast(type *) mem_fmalloc(typetemp_t.sizeof);
448     memset(t, 0, typetemp_t.sizeof);
449     t.Tty = TYtemplate;
450     if (s.Stemplate.TMprimary)
451         s = s.Stemplate.TMprimary;
452     (cast(typetemp_t *)t).Tsym = s;
453 version (SRCPOS_4TYPES)
454 {
455     if (PARSER && config.fulltypes)
456         t.Tsrcpos = getlinnum();
457 }
458 debug
459 {
460     t.id = type.IDtype;
461     type_num++;
462     if (type_num > type_max)
463         type_max = type_num;
464     //printf("Alloc'ing template type %p %s", t, tym_str(t.Tty));
465 }
466     return t;
467 }
468 }
469 
470 /*****************************
471  * Fake a type & initialize it.
472  * Input:
473  *      ty = TYxxxx
474  * Returns:
475  *      pointer to newly created type.
476  */
477 
478 type *type_fake(tym_t ty)
479 {   type *t;
480 
481 version (MARS)
482     assert(ty != TYstruct);
483 
484     t = type_alloc(ty);
485     if (typtr(ty) || tyfunc(ty))
486     {   t.Tnext = type_alloc(TYvoid);  /* fake with pointer to void    */
487         t.Tnext.Tcount = 1;
488     }
489     return t;
490 }
491 
492 /*****************************
493  * Allocate a type of ty with a Tnext of tn.
494  */
495 
496 type *type_allocn(tym_t ty,type *tn)
497 {   type *t;
498 
499     //printf("type_allocn(ty = x%x, tn = %p)\n", ty, tn);
500     assert(tn);
501     type_debug(tn);
502     t = type_alloc(ty);
503     t.Tnext = tn;
504     tn.Tcount++;
505     //printf("\tt = %p\n", t);
506     return t;
507 }
508 
509 /******************************
510  * Allocate a TYmemptr type.
511  */
512 
513 version (SCPP_HTOD)
514 {
515 type *type_allocmemptr(Classsym *stag,type *tn)
516 {   type *t;
517 
518     symbol_debug(stag);
519     assert(stag.Sclass == SC.struct_ || tybasic(stag.Stype.Tty) == TYident);
520     t = type_allocn(TYmemptr,tn);
521     t.Ttag = stag;
522     //printf("type_allocmemptr() = %p\n", t);
523     //type_print(t);
524     return t;
525 }
526 }
527 
528 /********************************
529  * Allocate a pointer type.
530  * Returns:
531  *      Tcount already incremented
532  */
533 
534 type *type_pointer(type *tnext)
535 {
536     type *t = type_allocn(TYnptr, tnext);
537     t.Tcount++;
538     return t;
539 }
540 
541 /********************************
542  * Allocate a dynamic array type.
543  * Returns:
544  *      Tcount already incremented
545  */
546 @trusted
547 type *type_dyn_array(type *tnext)
548 {
549     type *t = type_allocn(TYdarray, tnext);
550     t.Tcount++;
551     return t;
552 }
553 
554 /********************************
555  * Allocate a static array type.
556  * Returns:
557  *      Tcount already incremented
558  */
559 
560 extern (C) type *type_static_array(targ_size_t dim, type *tnext)
561 {
562     type *t = type_allocn(TYarray, tnext);
563     t.Tdim = dim;
564     t.Tcount++;
565     return t;
566 }
567 
568 /********************************
569  * Allocate an associative array type,
570  * which are key=value pairs
571  * Returns:
572  *      Tcount already incremented
573  */
574 
575 @trusted
576 type *type_assoc_array(type *tkey, type *tvalue)
577 {
578     type *t = type_allocn(TYaarray, tvalue);
579     t.Tkey = tkey;
580     tkey.Tcount++;
581     t.Tcount++;
582     return t;
583 }
584 
585 /********************************
586  * Allocate a delegate type.
587  * Returns:
588  *      Tcount already incremented
589  */
590 
591 @trusted
592 type *type_delegate(type *tnext)
593 {
594     type *t = type_allocn(TYdelegate, tnext);
595     t.Tcount++;
596     return t;
597 }
598 
599 /***********************************
600  * Allocation a function type.
601  * Params:
602  *      tyf      = function type
603  *      ptypes   = types of the function parameters
604  *      variadic = if ... function
605  *      tret     = return type
606  * Returns:
607  *      Tcount already incremented
608  */
609 @trusted
610 extern (C)
611 type *type_function(tym_t tyf, type*[] ptypes, bool variadic, type *tret)
612 {
613     param_t *paramtypes = null;
614     foreach (p; ptypes)
615     {
616         param_append_type(&paramtypes, p);
617     }
618     type *t = type_allocn(tyf, tret);
619     t.Tflags |= TFprototype;
620     if (!variadic)
621         t.Tflags |= TFfixed;
622     t.Tparamtypes = paramtypes;
623     t.Tcount++;
624     return t;
625 }
626 
627 /***************************************
628  * Create an enum type.
629  * Input:
630  *      name    name of enum
631  *      tbase   "base" type of enum
632  * Returns:
633  *      Tcount already incremented
634  */
635 @trusted
636 type *type_enum(const(char)* name, type *tbase)
637 {
638     Symbol *s = symbol_calloc(name[0 .. strlen(name)]);
639     s.Sclass = SC.enum_;
640     s.Senum = cast(enum_t *) MEM_PH_CALLOC(enum_t.sizeof);
641     s.Senum.SEflags |= SENforward;        // forward reference
642 
643     type *t = type_allocn(TYenum, tbase);
644     t.Ttag = cast(Classsym *)s;            // enum tag name
645     t.Tcount++;
646     s.Stype = t;
647     t.Tcount++;
648     return t;
649 }
650 
651 /**************************************
652  * Create a struct/union/class type.
653  * Params:
654  *      name = name of struct (this function makes its own copy of the string)
655  *      is0size = if struct has no fields (even if Sstructsize is 1)
656  * Returns:
657  *      Tcount already incremented
658  */
659 @trusted
660 type *type_struct_class(const(char)* name, uint alignsize, uint structsize,
661         type *arg1type, type *arg2type, bool isUnion, bool isClass, bool isPOD, bool is0size)
662 {
663     static if (0)
664     {
665         printf("type_struct_class(%s, %p, %p)\n", name, arg1type, arg2type);
666         if (arg1type)
667         {
668             printf("arg1type:\n");
669             type_print(arg1type);
670         }
671         if (arg2type)
672         {
673             printf("arg2type:\n");
674             type_print(arg2type);
675         }
676     }
677     Symbol *s = symbol_calloc(name[0 .. strlen(name)]);
678     s.Sclass = SC.struct_;
679     s.Sstruct = struct_calloc();
680     s.Sstruct.Salignsize = alignsize;
681     s.Sstruct.Sstructalign = cast(ubyte)alignsize;
682     s.Sstruct.Sstructsize = structsize;
683     s.Sstruct.Sarg1type = arg1type;
684     s.Sstruct.Sarg2type = arg2type;
685 
686     if (!isPOD)
687         s.Sstruct.Sflags |= STRnotpod;
688     if (isUnion)
689         s.Sstruct.Sflags |= STRunion;
690     if (isClass)
691     {   s.Sstruct.Sflags |= STRclass;
692         assert(!isUnion && isPOD);
693     }
694     if (is0size)
695         s.Sstruct.Sflags |= STR0size;
696 
697     type *t = type_alloc(TYstruct);
698     t.Ttag = cast(Classsym *)s;            // structure tag name
699     t.Tcount++;
700     s.Stype = t;
701     t.Tcount++;
702     return t;
703 }
704 
705 /*****************************
706  * Free up data type.
707  */
708 
709 @trusted
710 void type_free(type *t)
711 {   type *tn;
712     tym_t ty;
713 
714     while (t)
715     {
716         //printf("type_free(%p, Tcount = %d)\n", t, t.Tcount);
717         type_debug(t);
718         assert(cast(int)t.Tcount != -1);
719         if (--t.Tcount)                /* if usage count doesn't go to 0 */
720             break;
721         ty = tybasic(t.Tty);
722         if (tyfunc(ty))
723         {   param_free(&t.Tparamtypes);
724             list_free(&t.Texcspec, cast(list_free_fp)&type_free);
725             goto L1;
726         }
727 version (SCPP_HTOD)
728 {
729         if (ty == TYtemplate)
730         {
731             param_free(&t.Tparamtypes);
732             goto L1;
733         }
734         if (ty == TYident)
735         {
736             MEM_PH_FREE(t.Tident);
737             goto L1;
738         }
739 }
740         if (t.Tflags & TFvla && t.Tel)
741         {
742             el_free(t.Tel);
743             goto L1;
744         }
745 version (SCPP_HTOD)
746 {
747         if (t.Talternate && typtr(ty))
748         {
749             type_free(t.Talternate);
750             goto L1;
751         }
752 }
753 version (MARS)
754 {
755         if (t.Tkey && typtr(ty))
756             type_free(t.Tkey);
757 }
758       L1:
759 
760 debug
761 {
762         type_num--;
763         //printf("Free'ing type %p %s\n", t, tym_str(t.Tty));
764         t.id = 0;                      /* no longer a valid type       */
765 }
766 
767         tn = t.Tnext;
768         t.Tnext = type_list;
769         type_list = t;                  /* link into free list          */
770         t = tn;
771     }
772 }
773 
774 version (STATS)
775 {
776 /* count number of free types available on type list */
777 void type_count_free()
778     {
779     type *t;
780     int count;
781 
782     for(t=type_list;t;t=t.Tnext)
783         count++;
784     printf("types on free list %d with max of %d\n",count,type_max);
785     }
786 }
787 
788 /**********************************
789  * Initialize type package.
790  */
791 
792 private type * type_allocbasic(tym_t ty)
793 {   type *t;
794 
795     t = type_alloc(ty);
796     t.Tmangle = mTYman_c;
797     t.Tcount = 1;              /* so it is not inadvertently free'd    */
798     return t;
799 }
800 
801 @trusted
802 void type_init()
803 {
804     tstypes[TYbool]    = type_allocbasic(TYbool);
805     tstypes[TYwchar_t] = type_allocbasic(TYwchar_t);
806     tstypes[TYdchar]   = type_allocbasic(TYdchar);
807     tstypes[TYvoid]    = type_allocbasic(TYvoid);
808     tstypes[TYnullptr] = type_allocbasic(TYnullptr);
809     tstypes[TYchar16]  = type_allocbasic(TYchar16);
810     tstypes[TYuchar]   = type_allocbasic(TYuchar);
811     tstypes[TYschar]   = type_allocbasic(TYschar);
812     tstypes[TYchar]    = type_allocbasic(TYchar);
813     tstypes[TYshort]   = type_allocbasic(TYshort);
814     tstypes[TYushort]  = type_allocbasic(TYushort);
815     tstypes[TYint]     = type_allocbasic(TYint);
816     tstypes[TYuint]    = type_allocbasic(TYuint);
817     tstypes[TYlong]    = type_allocbasic(TYlong);
818     tstypes[TYulong]   = type_allocbasic(TYulong);
819     tstypes[TYllong]   = type_allocbasic(TYllong);
820     tstypes[TYullong]  = type_allocbasic(TYullong);
821     tstypes[TYfloat]   = type_allocbasic(TYfloat);
822     tstypes[TYdouble]  = type_allocbasic(TYdouble);
823     tstypes[TYdouble_alias]  = type_allocbasic(TYdouble_alias);
824     tstypes[TYldouble] = type_allocbasic(TYldouble);
825     tstypes[TYifloat]  = type_allocbasic(TYifloat);
826     tstypes[TYidouble] = type_allocbasic(TYidouble);
827     tstypes[TYildouble] = type_allocbasic(TYildouble);
828     tstypes[TYcfloat]   = type_allocbasic(TYcfloat);
829     tstypes[TYcdouble]  = type_allocbasic(TYcdouble);
830     tstypes[TYcldouble] = type_allocbasic(TYcldouble);
831 
832     if (I64)
833     {
834         TYptrdiff = TYllong;
835         TYsize = TYullong;
836         tsptrdiff = tstypes[TYllong];
837         tssize = tstypes[TYullong];
838     }
839     else
840     {
841         TYptrdiff = TYint;
842         TYsize = TYuint;
843         tsptrdiff = tstypes[TYint];
844         tssize = tstypes[TYuint];
845     }
846 
847     // Type of trace function
848     tstrace = type_fake(I16 ? TYffunc : TYnfunc);
849     tstrace.Tmangle = mTYman_c;
850     tstrace.Tcount++;
851 
852     chartype = (config.flags3 & CFG3ju) ? tstypes[TYuchar] : tstypes[TYchar];
853 
854     // Type of far library function
855     tsclib = type_fake(LARGECODE ? TYfpfunc : TYnpfunc);
856     tsclib.Tmangle = mTYman_c;
857     tsclib.Tcount++;
858 
859     tspvoid = type_allocn(pointertype,tstypes[TYvoid]);
860     tspvoid.Tmangle = mTYman_c;
861     tspvoid.Tcount++;
862 
863     // Type of far library function
864     tsjlib =    type_fake(TYjfunc);
865     tsjlib.Tmangle = mTYman_c;
866     tsjlib.Tcount++;
867 
868     tsdlib = tsjlib;
869 
870 version (SCPP_HTOD)
871 {
872     tspcvoid = type_alloc(mTYconst | TYvoid);
873     tspcvoid = newpointer(tspcvoid);
874     tspcvoid.Tmangle = mTYman_c;
875     tspcvoid.Tcount++;
876 }
877 
878     // Type of logical expression
879     tslogical = (config.flags4 & CFG4bool) ? tstypes[TYbool] : tstypes[TYint];
880 
881     for (int i = 0; i < TYMAX; i++)
882     {
883         if (tstypes[i])
884         {   tsptr2types[i] = type_allocn(pointertype,tstypes[i]);
885             tsptr2types[i].Tcount++;
886         }
887     }
888 }
889 
890 /**********************************
891  * Free type_list.
892  */
893 
894 void type_term()
895 {
896 static if (TERMCODE)
897 {
898     type *tn;
899     param_t *pn;
900     int i;
901 
902     for (i = 0; i < tstypes.length; i++)
903     {   type *t = tsptr2types[i];
904 
905         if (t)
906         {   assert(!(t.Tty & (mTYconst | mTYvolatile | mTYimmutable | mTYshared)));
907             assert(!(t.Tflags));
908             assert(!(t.Tmangle));
909             type_free(t);
910         }
911         type_free(tstypes[i]);
912     }
913 
914     type_free(tsclib);
915     type_free(tspvoid);
916     type_free(tspcvoid);
917     type_free(tsjlib);
918     type_free(tstrace);
919 
920     while (type_list)
921     {   tn = type_list.Tnext;
922         mem_ffree(type_list);
923         type_list = tn;
924     }
925 
926     while (param_list)
927     {   pn = param_list.Pnext;
928         mem_ffree(param_list);
929         param_list = pn;
930     }
931 
932 debug
933 {
934     printf("Max # of types = %d\n",type_max);
935     if (type_num != 0)
936         printf("type_num = %d\n",type_num);
937 /*    assert(type_num == 0);*/
938 }
939 
940 }
941 }
942 
943 /*******************************
944  * Type type information.
945  */
946 
947 /**************************
948  * Make copy of a type.
949  */
950 
951 @trusted
952 type *type_copy(type *t)
953 {   type *tn;
954     param_t *p;
955 
956     type_debug(t);
957 version (SCPP_HTOD)
958 {
959     if (tybasic(t.Tty) == TYtemplate)
960     {
961         tn = type_alloc_template((cast(typetemp_t *)t).Tsym);
962     }
963     else
964         tn = type_alloc(t.Tty);
965 }
966 else
967         tn = type_alloc(t.Tty);
968 
969     *tn = *t;
970     switch (tybasic(tn.Tty))
971     {
972 version (SCPP_HTOD)
973 {
974             case TYtemplate:
975                 (cast(typetemp_t *)tn).Tsym = (cast(typetemp_t *)t).Tsym;
976                 goto L1;
977 
978             case TYident:
979                 tn.Tident = cast(char *)MEM_PH_STRDUP(t.Tident);
980                 break;
981 }
982 
983             case TYarray:
984                 if (tn.Tflags & TFvla)
985                     tn.Tel = el_copytree(tn.Tel);
986                 break;
987 
988             default:
989                 if (tyfunc(tn.Tty))
990                 {
991                 L1:
992                     tn.Tparamtypes = null;
993                     for (p = t.Tparamtypes; p; p = p.Pnext)
994                     {   param_t *pn;
995 
996                         pn = param_append_type(&tn.Tparamtypes,p.Ptype);
997                         if (p.Pident)
998                         {
999                             pn.Pident = cast(char *)MEM_PH_STRDUP(p.Pident);
1000                         }
1001                         assert(!p.Pelem);
1002                     }
1003                 }
1004                 else
1005                 {
1006 version (SCPP_HTOD)
1007 {
1008                 if (tn.Talternate && typtr(tn.Tty))
1009                     tn.Talternate.Tcount++;
1010 }
1011 version (MARS)
1012 {
1013                 if (tn.Tkey && typtr(tn.Tty))
1014                     tn.Tkey.Tcount++;
1015 }
1016                 }
1017                 break;
1018     }
1019     if (tn.Tnext)
1020     {   type_debug(tn.Tnext);
1021         tn.Tnext.Tcount++;
1022     }
1023     tn.Tcount = 0;
1024     return tn;
1025 }
1026 
1027 /************************************
1028  */
1029 
1030 version (SCPP_HTOD)
1031 {
1032 
1033 elem *type_vla_fix(type **pt)
1034 {
1035     type *t;
1036     elem *e = null;
1037 
1038     for (t = *pt; t; t = t.Tnext)
1039     {
1040         type_debug(t);
1041         if (tybasic(t.Tty) == TYarray && t.Tflags & TFvla && t.Tel)
1042         {   Symbol *s;
1043             elem *ec;
1044 
1045             s = symbol_genauto(tstypes[TYuint]);
1046             ec = el_var(s);
1047             ec = el_bint(OPeq, tstypes[TYuint], ec, t.Tel);
1048             e = el_combine(e, ec);
1049             t.Tel = el_var(s);
1050         }
1051     }
1052     return e;
1053 }
1054 
1055 }
1056 
1057 /****************************
1058  * Modify the tym_t field of a type.
1059  */
1060 
1061 type *type_setty(type **pt,uint newty)
1062 {   type *t;
1063 
1064     t = *pt;
1065     type_debug(t);
1066     if (cast(tym_t)newty != t.Tty)
1067     {   if (t.Tcount > 1)              /* if other people pointing at t */
1068         {   type *tn;
1069 
1070             tn = type_copy(t);
1071             tn.Tcount++;
1072             type_free(t);
1073             t = tn;
1074             *pt = t;
1075         }
1076         t.Tty = newty;
1077     }
1078     return t;
1079 }
1080 
1081 /******************************
1082  * Set type field of some object to t.
1083  */
1084 
1085 type *type_settype(type **pt, type *t)
1086 {
1087     if (t)
1088     {   type_debug(t);
1089         t.Tcount++;
1090     }
1091     type_free(*pt);
1092     return *pt = t;
1093 }
1094 
1095 /****************************
1096  * Modify the Tmangle field of a type.
1097  */
1098 
1099 type *type_setmangle(type **pt,mangle_t mangle)
1100 {   type *t;
1101 
1102     t = *pt;
1103     type_debug(t);
1104     if (mangle != type_mangle(t))
1105     {
1106         if (t.Tcount > 1)              // if other people pointing at t
1107         {   type *tn;
1108 
1109             tn = type_copy(t);
1110             tn.Tcount++;
1111             type_free(t);
1112             t = tn;
1113             *pt = t;
1114         }
1115         t.Tmangle = mangle;
1116     }
1117     return t;
1118 }
1119 
1120 /******************************
1121  * Set/clear const and volatile bits in *pt according to the settings
1122  * in cv.
1123  */
1124 
1125 type *type_setcv(type **pt,tym_t cv)
1126 {   uint ty;
1127 
1128     type_debug(*pt);
1129     ty = (*pt).Tty & ~(mTYconst | mTYvolatile | mTYimmutable | mTYshared);
1130     return type_setty(pt,ty | (cv & (mTYconst | mTYvolatile | mTYimmutable | mTYshared)));
1131 }
1132 
1133 /*****************************
1134  * Set dimension of array.
1135  */
1136 
1137 type *type_setdim(type **pt,targ_size_t dim)
1138 {   type *t = *pt;
1139 
1140     type_debug(t);
1141     if (t.Tcount > 1)                  /* if other people pointing at t */
1142     {   type *tn;
1143 
1144         tn = type_copy(t);
1145         tn.Tcount++;
1146         type_free(t);
1147         t = tn;
1148     }
1149     t.Tflags &= ~TFsizeunknown; /* we have determined its size */
1150     t.Tdim = dim;              /* index of array               */
1151     return *pt = t;
1152 }
1153 
1154 
1155 /*****************************
1156  * Create a 'dependent' version of type t.
1157  */
1158 
1159 type *type_setdependent(type *t)
1160 {
1161     type_debug(t);
1162     if (t.Tcount > 0 &&                        /* if other people pointing at t */
1163         !(t.Tflags & TFdependent))
1164     {
1165         t = type_copy(t);
1166     }
1167     t.Tflags |= TFdependent;
1168     return t;
1169 }
1170 
1171 /************************************
1172  * Determine if type t is a dependent type.
1173  */
1174 
1175 @trusted
1176 int type_isdependent(type *t)
1177 {
1178     Symbol *stempl;
1179     type *tstart;
1180 
1181     //printf("type_isdependent(%p)\n", t);
1182     //type_print(t);
1183     for (tstart = t; t; t = t.Tnext)
1184     {
1185         type_debug(t);
1186         if (t.Tflags & TFdependent)
1187             goto Lisdependent;
1188         if (tyfunc(t.Tty)
1189                 || tybasic(t.Tty) == TYtemplate
1190                 )
1191         {
1192             for (param_t *p = t.Tparamtypes; p; p = p.Pnext)
1193             {
1194                 if (p.Ptype && type_isdependent(p.Ptype))
1195                     goto Lisdependent;
1196                 if (p.Pelem && el_isdependent(p.Pelem))
1197                     goto Lisdependent;
1198             }
1199         }
1200         else if (type_struct(t) &&
1201                  (stempl = t.Ttag.Sstruct.Stempsym) != null)
1202         {
1203             for (param_t *p = t.Ttag.Sstruct.Sarglist; p; p = p.Pnext)
1204             {
1205                 if (p.Ptype && type_isdependent(p.Ptype))
1206                     goto Lisdependent;
1207                 if (p.Pelem && el_isdependent(p.Pelem))
1208                     goto Lisdependent;
1209             }
1210         }
1211     }
1212     //printf("\tis not dependent\n");
1213     return 0;
1214 
1215 Lisdependent:
1216     //printf("\tis dependent\n");
1217     // Dependence on a dependent type makes this type dependent as well
1218     tstart.Tflags |= TFdependent;
1219     return 1;
1220 }
1221 
1222 
1223 /*******************************
1224  * Recursively check if type u is embedded in type t.
1225  * Returns:
1226  *      != 0 if embedded
1227  */
1228 
1229 @trusted
1230 int type_embed(type *t,type *u)
1231 {   param_t *p;
1232 
1233     for (; t; t = t.Tnext)
1234     {
1235         type_debug(t);
1236         if (t == u)
1237             return 1;
1238         if (tyfunc(t.Tty))
1239         {
1240             for (p = t.Tparamtypes; p; p = p.Pnext)
1241                 if (type_embed(p.Ptype,u))
1242                     return 1;
1243         }
1244     }
1245     return 0;
1246 }
1247 
1248 
1249 /***********************************
1250  * Determine if type is a VLA.
1251  */
1252 
1253 int type_isvla(type *t)
1254 {
1255     while (t)
1256     {
1257         if (tybasic(t.Tty) != TYarray)
1258             break;
1259         if (t.Tflags & TFvla)
1260             return 1;
1261         t = t.Tnext;
1262     }
1263     return 0;
1264 }
1265 
1266 
1267 /**********************************
1268  * Pretty-print a type.
1269  */
1270 
1271 @trusted
1272 void type_print(const type *t)
1273 {
1274   type_debug(t);
1275   printf("Tty=%s", tym_str(t.Tty));
1276   printf(" Tmangle=%d",t.Tmangle);
1277   printf(" Tflags=x%x",t.Tflags);
1278   printf(" Tcount=%d",t.Tcount);
1279   if (!(t.Tflags & TFsizeunknown) &&
1280         tybasic(t.Tty) != TYvoid &&
1281         tybasic(t.Tty) != TYident &&
1282         tybasic(t.Tty) != TYtemplate &&
1283         tybasic(t.Tty) != TYmfunc &&
1284         tybasic(t.Tty) != TYarray)
1285       printf(" Tsize=%lld", cast(long)type_size(t));
1286   printf(" Tnext=%p",t.Tnext);
1287   switch (tybasic(t.Tty))
1288   {     case TYstruct:
1289         case TYmemptr:
1290             printf(" Ttag=%p,'%s'",t.Ttag,t.Ttag.Sident.ptr);
1291             //printf(" Sfldlst=%p",t.Ttag.Sstruct.Sfldlst);
1292             break;
1293 
1294         case TYarray:
1295             printf(" Tdim=%lld", cast(long)t.Tdim);
1296             break;
1297 
1298         case TYident:
1299             printf(" Tident='%s'",t.Tident);
1300             break;
1301         case TYtemplate:
1302             printf(" Tsym='%s'",(cast(typetemp_t *)t).Tsym.Sident.ptr);
1303             {
1304                 int i;
1305 
1306                 i = 1;
1307                 for (const(param_t)* p = t.Tparamtypes; p; p = p.Pnext)
1308                 {   printf("\nTP%d (%p): ",i++,p);
1309                     fflush(stdout);
1310 
1311 printf("Pident=%p,Ptype=%p,Pelem=%p,Pnext=%p ",p.Pident,p.Ptype,p.Pelem,p.Pnext);
1312                     param_debug(p);
1313                     if (p.Pident)
1314                         printf("'%s' ", p.Pident);
1315                     if (p.Ptype)
1316                         type_print(p.Ptype);
1317                     if (p.Pelem)
1318                         elem_print(p.Pelem);
1319                 }
1320             }
1321             break;
1322 
1323         default:
1324             if (tyfunc(t.Tty))
1325             {
1326                 int i;
1327 
1328                 i = 1;
1329                 for (const(param_t)* p = t.Tparamtypes; p; p = p.Pnext)
1330                 {   printf("\nP%d (%p): ",i++,p);
1331                     fflush(stdout);
1332 
1333 printf("Pident=%p,Ptype=%p,Pelem=%p,Pnext=%p ",p.Pident,p.Ptype,p.Pelem,p.Pnext);
1334                     param_debug(p);
1335                     if (p.Pident)
1336                         printf("'%s' ", p.Pident);
1337                     type_print(p.Ptype);
1338                 }
1339             }
1340             break;
1341   }
1342   printf("\n");
1343   if (t.Tnext) type_print(t.Tnext);
1344 }
1345 
1346 /*******************************
1347  * Pretty-print a param_t
1348  */
1349 
1350 @trusted
1351 void param_t_print(const scope param_t* p)
1352 {
1353     printf("Pident=%p,Ptype=%p,Pelem=%p,Psym=%p,Pnext=%p\n",p.Pident,p.Ptype,p.Pelem,p.Psym,p.Pnext);
1354     if (p.Pident)
1355         printf("\tPident = '%s'\n", p.Pident);
1356     if (p.Ptype)
1357     {   printf("\tPtype =\n");
1358         type_print(p.Ptype);
1359     }
1360     if (p.Pelem)
1361     {   printf("\tPelem =\n");
1362         elem_print(p.Pelem);
1363     }
1364     if (p.Pdeftype)
1365     {   printf("\tPdeftype =\n");
1366         type_print(p.Pdeftype);
1367     }
1368     if (p.Psym)
1369     {   printf("\tPsym = '%s'\n", p.Psym.Sident.ptr);
1370     }
1371     if (p.Pptpl)
1372     {   printf("\tPptpl = %p\n", p.Pptpl);
1373     }
1374 }
1375 
1376 void param_t_print_list(scope param_t* p)
1377 {
1378     for (; p; p = p.Pnext)
1379         p.print();
1380 }
1381 
1382 
1383 /**********************************
1384  * Hydrate a type.
1385  */
1386 
1387 version (SCPP_HTOD)
1388 {
1389 
1390 static if (HYDRATE)
1391 {
1392 void type_hydrate(type **pt)
1393 {
1394     type *t;
1395 
1396     assert(pt);
1397     while (isdehydrated(*pt))
1398     {
1399         t = cast(type *) ph_hydrate(cast(void**)pt);
1400         type_debug(t);
1401         switch (tybasic(t.Tty))
1402         {
1403             case TYstruct:
1404             case TYenum:
1405             case TYmemptr:
1406             case TYvtshape:
1407                 // Cannot assume symbol is hydrated, because entire HX file
1408                 // may not have been hydrated.
1409                 Classsym_hydrate(&t.Ttag);
1410                 symbol_debug(t.Ttag);
1411                 break;
1412             case TYident:
1413                 ph_hydrate(cast(void**)&t.Tident);
1414                 break;
1415             case TYtemplate:
1416                 symbol_hydrate(&(cast(typetemp_t *)t).Tsym);
1417                 param_hydrate(&t.Tparamtypes);
1418                 break;
1419             case TYarray:
1420                 if (t.Tflags & TFvla)
1421                     el_hydrate(&t.Tel);
1422                 break;
1423             default:
1424                 if (tyfunc(t.Tty))
1425                 {   param_hydrate(&t.Tparamtypes);
1426                     list_hydrate(&t.Texcspec, cast(list_free_fp)&type_hydrate);
1427                 }
1428                 else if (t.Talternate && typtr(t.Tty))
1429                     type_hydrate(&t.Talternate);
1430                 else if (t.Tkey && typtr(t.Tty))
1431                     type_hydrate(&t.Tkey);
1432                 break;
1433         }
1434         pt = &t.Tnext;
1435     }
1436 }
1437 }
1438 
1439 /**********************************
1440  * Dehydrate a type.
1441  */
1442 
1443 static if (DEHYDRATE)
1444 {
1445 void type_dehydrate(type **pt)
1446 {
1447     type *t;
1448 
1449     while ((t = *pt) != null && !isdehydrated(t))
1450     {
1451         ph_dehydrate(pt);
1452 version (DEBUG_XSYMGEN)
1453 {
1454         /* don't dehydrate types in HEAD when creating XSYM */
1455         if (xsym_gen && (t.Tflags & TFhydrated))
1456             return;
1457 }
1458         type_debug(t);
1459         switch (tybasic(t.Tty))
1460         {
1461             case TYstruct:
1462             case TYenum:
1463             case TYmemptr:
1464             case TYvtshape:
1465                 Classsym_dehydrate(&t.Ttag);
1466                 break;
1467             case TYident:
1468                 ph_dehydrate(&t.Tident);
1469                 break;
1470             case TYtemplate:
1471                 symbol_dehydrate(&(cast(typetemp_t *)t).Tsym);
1472                 param_dehydrate(&t.Tparamtypes);
1473                 break;
1474             case TYarray:
1475                 if (t.Tflags & TFvla)
1476                     el_dehydrate(&t.Tel);
1477                 break;
1478             default:
1479                 if (tyfunc(t.Tty))
1480                 {   param_dehydrate(&t.Tparamtypes);
1481                     list_dehydrate(&t.Texcspec, cast(list_free_fp)&type_dehydrate);
1482                 }
1483                 else if (t.Talternate && typtr(t.Tty))
1484                     type_dehydrate(&t.Talternate);
1485                 else if (t.Tkey && typtr(t.Tty))
1486                     type_dehydrate(&t.Tkey);
1487                 break;
1488         }
1489         pt = &t.Tnext;
1490     }
1491 }
1492 }
1493 
1494 }
1495 
1496 /****************************
1497  * Allocate a param_t.
1498  */
1499 
1500 @trusted
1501 param_t *param_calloc()
1502 {
1503     static param_t pzero;
1504     param_t *p;
1505 
1506     if (param_list)
1507     {
1508         p = param_list;
1509         param_list = p.Pnext;
1510     }
1511     else
1512     {
1513         p = cast(param_t *) mem_fmalloc(param_t.sizeof);
1514     }
1515     *p = pzero;
1516 
1517     debug p.id = param_t.IDparam;
1518 
1519     return p;
1520 }
1521 
1522 /***************************
1523  * Allocate a param_t of type t, and append it to parameter list.
1524  */
1525 
1526 param_t *param_append_type(param_t **pp,type *t)
1527 {   param_t *p;
1528 
1529     p = param_calloc();
1530     while (*pp)
1531     {   param_debug(*pp);
1532         pp = &((*pp).Pnext);   /* find end of list     */
1533     }
1534     *pp = p;                    /* append p to list     */
1535     type_debug(t);
1536     p.Ptype = t;
1537     t.Tcount++;
1538     return p;
1539 }
1540 
1541 /************************
1542  * Version of param_free() suitable for list_free().
1543  */
1544 
1545 @trusted
1546 void param_free_l(param_t *p)
1547 {
1548     param_free(&p);
1549 }
1550 
1551 /***********************
1552  * Free parameter list.
1553  * Output:
1554  *      paramlst = null
1555  */
1556 
1557 @trusted
1558 void param_free(param_t **pparamlst)
1559 {   param_t* p,pn;
1560 
1561     //debug_assert(PARSER);
1562     for (p = *pparamlst; p; p = pn)
1563     {   param_debug(p);
1564         pn = p.Pnext;
1565         type_free(p.Ptype);
1566         mem_free(p.Pident);
1567         el_free(p.Pelem);
1568         type_free(p.Pdeftype);
1569         if (p.Pptpl)
1570             param_free(&p.Pptpl);
1571 
1572         debug p.id = 0;
1573 
1574         p.Pnext = param_list;
1575         param_list = p;
1576     }
1577     *pparamlst = null;
1578 }
1579 
1580 /***********************************
1581  * Compute number of parameters
1582  */
1583 
1584 uint param_t_length(scope param_t* p)
1585 {
1586     uint nparams = 0;
1587 
1588     for (; p; p = p.Pnext)
1589         nparams++;
1590     return nparams;
1591 }
1592 
1593 /*************************************
1594  * Create template-argument-list blank from
1595  * template-parameter-list
1596  * Input:
1597  *      ptali   initial template-argument-list
1598  */
1599 
1600 @trusted
1601 param_t* param_t_createTal(scope param_t* p, param_t *ptali)
1602 {
1603 version (SCPP_HTOD)
1604 {
1605     param_t *ptalistart = ptali;
1606     param_t *pstart = p;
1607 }
1608     param_t *ptal = null;
1609     param_t **pp = &ptal;
1610 
1611     for (; p; p = p.Pnext)
1612     {
1613         *pp = param_calloc();
1614         if (p.Pident)
1615         {
1616             // Should find a way to just point rather than dup
1617             (*pp).Pident = cast(char *)MEM_PH_STRDUP(p.Pident);
1618         }
1619         if (ptali)
1620         {
1621             if (ptali.Ptype)
1622             {   (*pp).Ptype = ptali.Ptype;
1623                 (*pp).Ptype.Tcount++;
1624             }
1625             if (ptali.Pelem)
1626             {
1627                 elem *e = el_copytree(ptali.Pelem);
1628 version (SCPP_HTOD)
1629 {
1630                 if (p.Ptype)
1631                 {   type *t = p.Ptype;
1632                     t = template_tyident(t, ptalistart, pstart, 1);
1633                     e = poptelem3(typechk(e, t));
1634                     type_free(t);
1635                 }
1636 }
1637                 (*pp).Pelem = e;
1638             }
1639             (*pp).Psym = ptali.Psym;
1640             (*pp).Pflags = ptali.Pflags;
1641             assert(!ptali.Pptpl);
1642             ptali = ptali.Pnext;
1643         }
1644         pp = &(*pp).Pnext;
1645     }
1646     return ptal;
1647 }
1648 
1649 /**********************************
1650  * Look for Pident matching id
1651  */
1652 
1653 @trusted
1654 param_t* param_t_search(return scope param_t* p, const(char)* id)
1655 {
1656     for (; p; p = p.Pnext)
1657     {
1658         if (p.Pident && strcmp(p.Pident, id) == 0)
1659             break;
1660     }
1661     return p;
1662 }
1663 
1664 /**********************************
1665  * Look for Pident matching id
1666  */
1667 
1668 @trusted
1669 int param_t_searchn(param_t* p, char *id)
1670 {
1671     int n = 0;
1672 
1673     for (; p; p = p.Pnext)
1674     {
1675         if (p.Pident && strcmp(p.Pident, id) == 0)
1676             return n;
1677         n++;
1678     }
1679     return -1;
1680 }
1681 
1682 /*************************************
1683  * Search for member, create symbol as needed.
1684  * Used for symbol tables for VLA's such as:
1685  *      void func(int n, int a[n]);
1686  */
1687 
1688 @trusted
1689 Symbol *param_search(const(char)* name, param_t **pp)
1690 {   Symbol *s = null;
1691     param_t *p;
1692 
1693     p = (*pp).search(cast(char *)name);
1694     if (p)
1695     {
1696         s = p.Psym;
1697         if (!s)
1698         {
1699             s = symbol_calloc(p.Pident[0 .. strlen(p.Pident)]);
1700             s.Sclass = SC.parameter;
1701             s.Stype = p.Ptype;
1702             s.Stype.Tcount++;
1703             p.Psym = s;
1704         }
1705     }
1706     return s;
1707 }
1708 
1709 /**********************************
1710  * Hydrate/dehydrate a type.
1711  */
1712 
1713 version (SCPP_HTOD)
1714 {
1715 static if (HYDRATE)
1716 {
1717 void param_hydrate(param_t **pp)
1718 {
1719     param_t *p;
1720 
1721     assert(pp);
1722     if (isdehydrated(*pp))
1723     {   while (*pp)
1724         {   assert(isdehydrated(*pp));
1725             p = cast(param_t *) ph_hydrate(cast(void**)pp);
1726             param_debug(p);
1727 
1728             type_hydrate(&p.Ptype);
1729             if (p.Ptype)
1730                 type_debug(p.Ptype);
1731             ph_hydrate(cast(void**)&p.Pident);
1732             if (CPP)
1733             {
1734                 el_hydrate(&p.Pelem);
1735                 if (p.Pelem)
1736                     elem_debug(p.Pelem);
1737                 type_hydrate(&p.Pdeftype);
1738                 if (p.Pptpl)
1739                     param_hydrate(&p.Pptpl);
1740                 if (p.Psym)
1741                     symbol_hydrate(&p.Psym);
1742                 if (p.PelemToken)
1743                     token_hydrate(&p.PelemToken);
1744             }
1745 
1746             pp = &p.Pnext;
1747         }
1748     }
1749 }
1750 }
1751 
1752 static if (DEHYDRATE)
1753 {
1754 void param_dehydrate(param_t **pp)
1755 {
1756     param_t *p;
1757 
1758     assert(pp);
1759     while ((p = *pp) != null && !isdehydrated(p))
1760     {   param_debug(p);
1761 
1762         ph_dehydrate(pp);
1763         if (p.Ptype && !isdehydrated(p.Ptype))
1764             type_debug(p.Ptype);
1765         type_dehydrate(&p.Ptype);
1766         ph_dehydrate(&p.Pident);
1767         if (CPP)
1768         {
1769             el_dehydrate(&p.Pelem);
1770             type_dehydrate(&p.Pdeftype);
1771             if (p.Pptpl)
1772                 param_dehydrate(&p.Pptpl);
1773             if (p.Psym)
1774                 symbol_dehydrate(&p.Psym);
1775             if (p.PelemToken)
1776                 token_dehydrate(&p.PelemToken);
1777         }
1778         pp = &p.Pnext;
1779     }
1780 }
1781 }
1782 }
1783 
1784 version (MARS)
1785 {
1786 
1787 // Return TRUE if type lists match.
1788 private int paramlstmatch(param_t *p1,param_t *p2)
1789 {
1790         return p1 == p2 ||
1791             p1 && p2 && typematch(p1.Ptype,p2.Ptype,0) &&
1792             paramlstmatch(p1.Pnext,p2.Pnext)
1793             ;
1794 }
1795 
1796 /*************************************************
1797  * A cheap version of exp2.typematch() and exp2.paramlstmatch(),
1798  * so that we can get cpp_mangle() to work for MARS.
1799  * It's less complex because it doesn't do templates and
1800  * can rely on strict typechecking.
1801  * Returns:
1802  *      !=0 if types match.
1803  */
1804 
1805 @trusted
1806 int typematch(type *t1,type *t2,int relax)
1807 { tym_t t1ty, t2ty;
1808   tym_t tym;
1809 
1810   tym = ~(mTYimport | mTYnaked);
1811 
1812   return t1 == t2 ||
1813             t1 && t2 &&
1814 
1815             (
1816                 /* ignore name mangling */
1817                 (t1ty = (t1.Tty & tym)) == (t2ty = (t2.Tty & tym))
1818             )
1819                  &&
1820 
1821             (tybasic(t1ty) != TYarray || t1.Tdim == t2.Tdim ||
1822              t1.Tflags & TFsizeunknown || t2.Tflags & TFsizeunknown)
1823                  &&
1824 
1825             (tybasic(t1ty) != TYstruct
1826                 && tybasic(t1ty) != TYenum
1827                 && tybasic(t1ty) != TYmemptr
1828              || t1.Ttag == t2.Ttag)
1829                  &&
1830 
1831             typematch(t1.Tnext,t2.Tnext, 0)
1832                  &&
1833 
1834             (!tyfunc(t1ty) ||
1835              ((t1.Tflags & TFfixed) == (t2.Tflags & TFfixed) &&
1836                  paramlstmatch(t1.Tparamtypes,t2.Tparamtypes) ))
1837          ;
1838 }
1839 
1840 }
1841 
1842 }