Rune - Fix array passing, optimize constant array indices
[rune.git] / librune / type.c
1 /*
2  * TYPE.C
3  *
4  * (c)Copyright 1993-2014, Matthew Dillon, All Rights Reserved.  See the  
5  *    COPYRIGHT file at the base of the distribution.
6  */
7
8 #include "defs.h"
9
10 Type DynamicLValueType;
11 Type DynamicRValueType;
12
13 Type NumericType;       /* generic numeric placeholder */
14 Type IntegralType;      /* generic integral placeholder */
15 Type SIntegerType;      /* generic signed integer placeholder */
16 Type UIntegerType;      /* generic unsigned integer placeholder */
17
18 Type VoidType;
19 Type BoolType;
20 Type Int8Type;
21 Type UInt8Type;
22 Type Int16Type;
23 Type UInt16Type;
24 Type Int32Type;
25 Type UInt32Type;
26 Type Int64Type;
27 Type UInt64Type;
28 Type Int128Type;
29 Type UInt128Type;
30
31 Type IntPtrType;
32 Type UIntPtrType;
33 Type OffType;
34 Type SizeType;
35
36 Type FloatType;         /* generic float placeholder */
37 Type Float32Type;
38 Type Float64Type;
39 Type Float128Type;
40
41 Type PointerType;       /* generic pointer placeholder */
42 Type CCharType;         /* const char           */
43 Type StrType;           /* const char *         */
44 Type CharPtrType;       /* char *               */
45 Type CharPtrPtrType;    /* char **              */
46 Type VoidPtrType;       /* void *               */
47 Type VoidRefType;       /* void @               */
48 Type CVoidPtrType;      /* const void *         */
49 Type LVoidPtrType;      /* lvalue void *        */
50
51 Type LexRefType;        /* run-time access class tie-ins */
52 Type ScopeType;
53 Type DeclarationType;
54 Type SemGroupType;
55 Type TypeType;
56 Type FILLERTypeType;
57 Type FILLERDeclType;
58
59 typelist_t DynamicTypeList = RUNE_HEAD_INITIALIZER(DynamicTypeList);
60 typelist_t CompoundTypeList = RUNE_HEAD_INITIALIZER(CompoundTypeList);
61 typelist_t ArgsTypeList = RUNE_HEAD_INITIALIZER(ArgsTypeList);
62 typelist_t StorageTypeList = RUNE_HEAD_INITIALIZER(StorageTypeList);
63
64 static void initInternalClassType(Type *type, Declaration *d);
65
66 Type *BaseTypeAry[] = {
67                 &DynamicLValueType, &DynamicRValueType, &NumericType,
68                 &IntegralType, &SIntegerType, &UIntegerType,
69                 &VoidType, &BoolType, &Int8Type, &UInt8Type,
70                 &Int16Type, &UInt16Type, &Int32Type, &UInt32Type,
71                 &Int64Type, &UInt64Type, &Int128Type, &UInt128Type,
72
73                 &IntPtrType, &UIntPtrType, &OffType, &SizeType,
74
75                 &FloatType, &Float32Type, &Float64Type, &Float128Type,
76
77                 &PointerType, &CCharType, &StrType, &CharPtrType,
78                 &CharPtrPtrType, &VoidPtrType, &VoidRefType, &CVoidPtrType,
79                 &LVoidPtrType,
80
81                 &LexRefType, &ScopeType, &DeclarationType, &SemGroupType,
82                 &TypeType, &FILLERTypeType, &FILLERDeclType,
83                 NULL
84 };
85
86 void
87 initType(Type *type, typelist_t *list, int op)
88 {
89         type->ty_Op = op;
90         RUNE_INIT(&type->ty_QList);
91         if (list)
92                 RUNE_INSERT_TAIL(list, type, ty_Node);
93         type->ty_SQList = list;
94 }
95
96 void
97 initQualType(Type *type, typelist_t *list, int op, int sqflags)
98 {
99         initType(type, list, op);
100         type->ty_SQFlags = sqflags;
101 }
102
103 void
104 initPtrType(Type *type, Type *ptrto, int sqflags)
105 {
106         initQualType(type, &ptrto->ty_QList, TY_PTRTO, sqflags);
107         type->ty_PtrType.et_Type = ptrto;
108         /*type->ty_Bytes = sizeof(PointerStor);*/
109         type->ty_AlignMask = sizeof(void *) - 1;
110 }
111
112 void
113 initCPtrType(Type *type, Type *ptrto, int sqflags)
114 {
115         initQualType(type, &ptrto->ty_QList, TY_CPTRTO, sqflags);
116         type->ty_PtrType.et_Type = ptrto;
117         /*type->ty_Bytes = sizeof(void *);*/
118         type->ty_AlignMask = sizeof(void *) - 1;
119 }
120
121 static void
122 initRefType(Type *type, Type *refto, int sqflags)
123 {
124         initQualType(type, &refto->ty_QList, TY_REFTO, sqflags);
125         type->ty_RefType.et_Type = refto;
126         type->ty_AlignMask = sizeof(void *) - 1;
127         /*type->ty_Bytes = sizeof(PointerStor);*/
128 }
129
130 void
131 TypeInit(void)
132 {
133         int i;
134
135         initQualType(&DynamicLValueType, &DynamicTypeList,
136                      TY_DYNAMIC, SF_LVALUE);
137         initType(&DynamicRValueType, &DynamicTypeList, TY_DYNAMIC);
138         initType(&NumericType, NULL, TY_UNRESOLVED);
139         initType(&IntegralType, NULL, TY_UNRESOLVED);
140         initType(&SIntegerType, NULL, TY_UNRESOLVED);
141         initType(&UIntegerType, NULL, TY_UNRESOLVED);
142         initType(&FloatType, NULL, TY_UNRESOLVED);
143         initType(&PointerType, NULL, TY_UNRESOLVED);
144         PointerType.ty_AlignMask = sizeof(void *) - 1;
145
146         initType(&VoidType, NULL, TY_UNRESOLVED);
147         initType(&BoolType, NULL, TY_UNRESOLVED);
148         initType(&Int8Type, NULL, TY_UNRESOLVED);
149         initType(&UInt8Type, NULL, TY_UNRESOLVED);
150         initType(&Int16Type, NULL, TY_UNRESOLVED);
151         initType(&UInt16Type, NULL, TY_UNRESOLVED);
152         initType(&Int32Type, NULL, TY_UNRESOLVED);
153         initType(&UInt32Type, NULL, TY_UNRESOLVED);
154         initType(&Int64Type, NULL, TY_UNRESOLVED);
155         initType(&UInt64Type, NULL, TY_UNRESOLVED);
156
157         initType(&IntPtrType, NULL, TY_UNRESOLVED);
158         initType(&UIntPtrType, NULL, TY_UNRESOLVED);
159         initType(&OffType, NULL, TY_UNRESOLVED);
160         initType(&SizeType, NULL, TY_UNRESOLVED);
161
162         initType(&Float32Type, NULL, TY_UNRESOLVED);
163         initType(&Float64Type, NULL, TY_UNRESOLVED);
164         initType(&Float128Type, NULL, TY_UNRESOLVED);
165
166         initQualType(&CCharType, NULL, TY_UNRESOLVED, SF_CONST);
167         initPtrType(&StrType, &CCharType, 0);
168         initPtrType(&CharPtrType, &UInt8Type, 0);
169         initPtrType(&CharPtrPtrType, &CharPtrType, 0);
170         initPtrType(&VoidPtrType, &VoidType, 0);
171         initRefType(&VoidRefType, &VoidType, 0);
172         initCPtrType(&CVoidPtrType, &VoidType, SF_CONST);
173         initPtrType(&LVoidPtrType, &VoidType, SF_LVALUE);
174
175         /*
176          * Mark internal types (not all are bound to classes so it is
177          * easiest to just do it here).  This will prevent the collapse
178          * code from trying to collapse our base types.
179          */
180         for (i = 0; BaseTypeAry[i]; ++i)
181                 BaseTypeAry[i]->ty_Flags |= TF_ISINTERNAL;
182
183         StrTableAlloc("void", 4, SPECIAL_INTERNAL_VOID);
184         StrTableAlloc("bool", 4, SPECIAL_INTERNAL_BOOL);
185         StrTableAlloc("int8_t", 6, SPECIAL_INTERNAL_INT8);
186         StrTableAlloc("uint8_t", 7, SPECIAL_INTERNAL_UINT8);
187         StrTableAlloc("int16_t", 7, SPECIAL_INTERNAL_INT16);
188         StrTableAlloc("uint16_t", 8, SPECIAL_INTERNAL_UINT16);
189         StrTableAlloc("int32_t", 7, SPECIAL_INTERNAL_INT32);
190         StrTableAlloc("uint32_t", 8, SPECIAL_INTERNAL_UINT32);
191         StrTableAlloc("int64_t", 7, SPECIAL_INTERNAL_INT64);
192         StrTableAlloc("uint64_t", 8, SPECIAL_INTERNAL_UINT64);
193         StrTableAlloc("int128_t", 8, SPECIAL_INTERNAL_INT128);
194         StrTableAlloc("uint128_t", 9, SPECIAL_INTERNAL_UINT128);
195
196         StrTableAlloc("float32_t", 9, SPECIAL_INTERNAL_FLOAT32);
197         StrTableAlloc("float64_t", 9, SPECIAL_INTERNAL_FLOAT64);
198         StrTableAlloc("float128_t", 10, SPECIAL_INTERNAL_FLOAT128);
199
200         StrTableAlloc("intptr_t", 8, SPECIAL_INTERNAL_INTPTR);
201         StrTableAlloc("uintptr_t", 9, SPECIAL_INTERNAL_UINTPTR);
202         StrTableAlloc("size_t", 6, SPECIAL_INTERNAL_SIZE);
203         StrTableAlloc("off_t", 5, SPECIAL_INTERNAL_OFF);
204
205         StrTableAlloc("Float", 5, SPECIAL_INTERNAL_FLOAT);
206         StrTableAlloc("Pointer", 7, SPECIAL_INTERNAL_POINTER);
207         StrTableAlloc("Numeric", 7, SPECIAL_INTERNAL_NUMERIC);
208         StrTableAlloc("Integral", 8, SPECIAL_INTERNAL_INTEGRAL);
209         StrTableAlloc("SInteger", 8, SPECIAL_INTERNAL_SINTEGER);
210         StrTableAlloc("UInteger", 8, SPECIAL_INTERNAL_UINTEGER);
211
212         StrTableAlloc("LexRef", 6, SPECIAL_INTERNAL_LEXREF);
213         StrTableAlloc("Scope", 5, SPECIAL_INTERNAL_SCOPE);
214         StrTableAlloc("Declaration", 11, SPECIAL_INTERNAL_DECLARATION);
215         StrTableAlloc("SemGroup", 8, SPECIAL_INTERNAL_SEMGROUP);
216         StrTableAlloc("Type", 4, SPECIAL_INTERNAL_TYPE);
217         StrTableAlloc("FILLERType", 10, SPECIAL_INTERNAL_FILLERTYPE);
218         StrTableAlloc("FILLERDecl", 10, SPECIAL_INTERNAL_FILLERDECL);
219
220         StrTableAlloc("__count",        7,      SPECIAL_COUNT);
221         StrTableAlloc("__data",         6,      SPECIAL_DATA);
222         StrTableAlloc("__varcount",     10,     SPECIAL_VAR_COUNT);
223         StrTableAlloc("__vardata",      9,      SPECIAL_VAR_DATA);
224         StrTableAlloc("__typeid",       8,      SPECIAL_TYPEID);
225         StrTableAlloc("__typestr",      9,      SPECIAL_TYPESTR);
226         StrTableAlloc("NULL",           4,      SPECIAL_NULL);
227 }
228
229 /*
230  * Attach an internal class, creating a global summary type for it that
231  * allows our interpreter and code generator to make various assumptions.
232  */
233 int
234 InternalClassAttach(Parse *p __unused, int t, Declaration *d)
235 {
236         Type *itype = NULL;
237         int s;
238
239         dassert_decl(d, d->d_Op == DOP_CLASS);
240
241         if ((s = StrTableSpecial(d->d_Id)) & SPECIALF_INTERNAL) {
242                 switch(s) {
243                 case SPECIAL_INTERNAL_VOID:
244                         itype = &VoidType;
245                         break;
246                 case SPECIAL_INTERNAL_BOOL:
247                         /*
248                          * Special flag helper (resolver sets TF_ISBOOL in
249                          * in the type)
250                          */
251                         itype = &BoolType;
252                         d->d_ClassDecl.ed_SemGroup->sg_Flags |= SGF_ISBOOL;
253                         break;
254                 case SPECIAL_INTERNAL_INT8:
255                         itype = &Int8Type;
256                         break;
257                 case SPECIAL_INTERNAL_UINT8:
258                         itype = &UInt8Type;
259                         break;
260                 case SPECIAL_INTERNAL_INT16:
261                         itype = &Int16Type;
262                         break;
263                 case SPECIAL_INTERNAL_UINT16:
264                         itype = &UInt16Type;
265                         break;
266                 case SPECIAL_INTERNAL_INT32:
267                         itype = &Int32Type;
268                         break;
269                 case SPECIAL_INTERNAL_UINT32:
270                         itype = &UInt32Type;
271                         break;
272                 case SPECIAL_INTERNAL_INT64:
273                         itype = &Int64Type;
274                         break;
275                 case SPECIAL_INTERNAL_UINT64:
276                         itype = &UInt64Type;
277                         break;
278                 case SPECIAL_INTERNAL_INT128:
279                         itype = &Int128Type;
280                         break;
281                 case SPECIAL_INTERNAL_UINT128:
282                         itype = &UInt128Type;
283                         break;
284
285                 case SPECIAL_INTERNAL_FLOAT:
286                         /*
287                          * Special flag helper (resolver sets TF_ISFLOATING in
288                          * in the type)
289                          */
290                         itype = &FloatType;
291                         d->d_ClassDecl.ed_SemGroup->sg_Flags |= SGF_ISFLOATING;
292                         break;
293                 case SPECIAL_INTERNAL_FLOAT32:
294                         itype = &Float32Type;
295                         break;
296                 case SPECIAL_INTERNAL_FLOAT64:
297                         itype = &Float64Type;
298                         break;
299                 case SPECIAL_INTERNAL_FLOAT128:
300                         itype = &Float128Type;
301                         break;
302
303                 case SPECIAL_INTERNAL_INTPTR:
304                         itype = &IntPtrType;
305                         break;
306                 case SPECIAL_INTERNAL_UINTPTR:
307                         itype = &UIntPtrType;
308                         break;
309                 case SPECIAL_INTERNAL_OFF:
310                         itype = &OffType;
311                         break;
312                 case SPECIAL_INTERNAL_SIZE:
313                         itype = &SizeType;
314                         break;
315                 /* NOTE: There is no ssize_t in rune. size_t is signed */
316
317                 case SPECIAL_INTERNAL_POINTER:
318                         itype = &PointerType;
319                         break;
320                 case SPECIAL_INTERNAL_NUMERIC:
321                         itype = &NumericType;
322                         break;
323                 case SPECIAL_INTERNAL_INTEGRAL:
324                         itype = &IntegralType;
325                         break;
326                 case SPECIAL_INTERNAL_SINTEGER:
327                         /*
328                          * Special flag helper (resolver sets TF_ISINTEGER in
329                          * in the type)
330                          */
331                         itype = &SIntegerType;
332                         d->d_ClassDecl.ed_SemGroup->sg_Flags |= SGF_ISINTEGER;
333                         break;
334                 case SPECIAL_INTERNAL_UINTEGER:
335                         /*
336                          * Special flag helper (resolver sets TF_ISINTEGER
337                          * and TF_ISUNSIGNED in the type)
338                          */
339                         itype = &UIntegerType;
340                         d->d_ClassDecl.ed_SemGroup->sg_Flags |= SGF_ISUNSIGNED;
341                         d->d_ClassDecl.ed_SemGroup->sg_Flags |= SGF_ISINTEGER;
342                         break;
343
344                 case SPECIAL_INTERNAL_LEXREF:
345                         itype = &LexRefType;
346                         break;
347                 case SPECIAL_INTERNAL_SCOPE:
348                         itype = &ScopeType;
349                         break;
350                 case SPECIAL_INTERNAL_DECLARATION:
351                         itype = &DeclarationType;
352                         break;
353                 case SPECIAL_INTERNAL_SEMGROUP:
354                         itype = &SemGroupType;
355                         break;
356                 case SPECIAL_INTERNAL_TYPE:
357                         itype = &TypeType;
358                         break;
359                 case SPECIAL_INTERNAL_FILLERTYPE:
360                         itype = &FILLERTypeType;
361                         break;
362                 case SPECIAL_INTERNAL_FILLERDECL:
363                         itype = &FILLERDeclType;
364                         break;
365                 default:
366                         dpanic("Unknown internal class: %s", d->d_Id);
367                         break;
368                 }
369         }
370         initInternalClassType(itype, d);
371
372         /*
373          * Fixup for const int8 pointers... we did not have
374          * a QList to put CCharType on until now.  It will
375          * wind up on the SemGroup's sg_ClassList.
376          */
377         if (itype == &UInt8Type) {
378                 TypeToQualType(itype, &CCharType,
379                                itype->ty_SQFlags | SF_CONST, NULL);
380         } 
381
382         return(t);
383 }
384
385 /*
386  * This is mostly deprecated except for official type aliases such as
387  * intptr_t.
388  */
389 int
390 InternalTypeAttach(Parse *p, int t, Declaration *d)
391 {
392         Type *itype = NULL;
393         int s;
394
395         dassert_decl(d, d->d_Op == DOP_TYPEDEF);
396
397         if ((s = StrTableSpecial(d->d_Id)) & SPECIALF_INTERNAL) {
398                 switch(s) {
399                 case SPECIAL_INTERNAL_VOID:
400                         itype = &VoidType;
401                         break;
402                 case SPECIAL_INTERNAL_BOOL:
403                         itype = &BoolType;
404                         break;
405                 case SPECIAL_INTERNAL_INT8:
406                         itype = &Int8Type;
407                         break;
408                 case SPECIAL_INTERNAL_UINT8:
409                         itype = &UInt8Type;
410                         break;
411                 case SPECIAL_INTERNAL_INT16:
412                         itype = &Int16Type;
413                         break;
414                 case SPECIAL_INTERNAL_UINT16:
415                         itype = &UInt16Type;
416                         break;
417                 case SPECIAL_INTERNAL_INT32:
418                         itype = &Int32Type;
419                         break;
420                 case SPECIAL_INTERNAL_UINT32:
421                         itype = &UInt32Type;
422                         break;
423                 case SPECIAL_INTERNAL_INT64:
424                         itype = &Int64Type;
425                         break;
426                 case SPECIAL_INTERNAL_UINT64:
427                         itype = &UInt64Type;
428                         break;
429
430                 case SPECIAL_INTERNAL_FLOAT32:
431                         itype = &Float32Type;
432                         break;
433                 case SPECIAL_INTERNAL_FLOAT64:
434                         itype = &Float64Type;
435                         break;
436                 case SPECIAL_INTERNAL_FLOAT128:
437                         itype = &Float128Type;
438                         break;
439
440                 case SPECIAL_INTERNAL_INTPTR:
441                         itype = &IntPtrType;
442                         break;
443                 case SPECIAL_INTERNAL_UINTPTR:
444                         itype = &UIntPtrType;
445                         break;
446                 case SPECIAL_INTERNAL_OFF:
447                         itype = &OffType;
448                         break;
449                 case SPECIAL_INTERNAL_SIZE:
450                         itype = &SizeType;
451                         break;
452                 /* NOTE: There is no ssize_t in rune. size_t is signed */
453
454                 case SPECIAL_INTERNAL_POINTER:
455                         itype = &PointerType;
456                         break;
457                 case SPECIAL_INTERNAL_NUMERIC:
458                         itype = &NumericType;
459                         break;
460                 case SPECIAL_INTERNAL_INTEGRAL:
461                         itype = &IntegralType;
462                         break;
463                 case SPECIAL_INTERNAL_SINTEGER:
464                         itype = &SIntegerType;
465                         break;
466                 case SPECIAL_INTERNAL_UINTEGER:
467                         itype = &UIntegerType;
468                         break;
469                 default:
470                         itype = InternalRegisteredTypeLookup(d->d_Id);
471                         if (itype == NULL)
472                                 dpanic("Unknown internal type: %s", d->d_Id);
473                         break;
474                 }
475         }
476         if (itype) {
477                 if (itype->ty_Op != TY_UNRESOLVED) {
478                         t = LexError(&p->p_Token, TOK_ERR_DUPLICATE_ATTACH);
479                 } else {
480                         Type *ntype = d->d_TypedefDecl.ed_Type;
481
482                         TypeToQualType(ntype, itype, ntype->ty_SQFlags, NULL);
483                 }
484         } else {
485                 t = LexError(&p->p_Token, TOK_ERR_UNRECOGNIZED_ATTACH);
486         }
487         return(t);
488 }
489
490 Type *
491 AllocType(typelist_t *list, int op)
492 {
493         Type *type = zalloc(sizeof(Type));
494
495         initType(type, list, op);
496         return(type);
497 }
498
499 /*
500  * May be used to generate a varargs compound type, in which case the
501  * semgroup may already be resolved.
502  *
503  * We do no matching/caching at this time and callers assume that (for
504  * making adjustments) to the underlying sg at parse-time via
505  * TypeToProcType()
506  */
507 Type *
508 AllocCompoundType(SemGroup *sg)
509 {
510         Type *type;
511
512         type = AllocType(&CompoundTypeList, TY_COMPOUND);
513         type->ty_CompType.et_SemGroup = sg;
514         dassert((sg->sg_Flags & SGF_RESOLVED) == 0);
515         return(type);
516 }
517
518 /*
519  * XXX match the compound type(s)
520  */
521 Type *
522 AllocArgsType(SemGroup *sg)
523 {
524         Type *type;
525
526         type = AllocType(&ArgsTypeList, TY_ARGS);
527         type->ty_ArgsType.et_SemGroup = sg;
528         return(type);
529 }
530
531 Type *
532 AllocStorageType(runesize_t bytes)
533 {
534         Type *type;
535
536         RUNE_FOREACH(type, &StorageTypeList, ty_Node) {
537                 if (type->ty_Op == TY_STORAGE &&
538                         type->ty_StorType.et_Bytes == bytes
539                 ) {
540                         return(type);
541                 }
542         }
543         type = AllocType(&StorageTypeList, TY_STORAGE);
544         type->ty_StorType.et_Bytes = bytes;
545         return(type);
546 }
547
548 Type *
549 AllocUnresolvedType(SemGroup *isg, SemGroup *sg, string_t *ary, int eatAry)
550 {
551         Type *type = NULL;
552
553         dassert_semgrp(sg, ary != NULL);
554
555         RUNE_FOREACH(type, &sg->sg_ClassList, ty_Node) {
556                 int i;
557
558                 if (type->ty_Op != TY_UNRESOLVED)
559                         continue;
560                 if (type->ty_UnresType.et_ImportSemGroup != isg)
561                         continue;
562
563                 for (i = 0; ary[i]; ++i) {
564                         if (ary[i] != type->ty_UnresType.et_DottedId[i])
565                                 break;
566                 }
567                 if (ary[i] == NULL &&
568                     type->ty_UnresType.et_DottedId[i] == NULL) {
569                         if (eatAry)
570                                 FreeDotIdAry(ary);
571                         return(type);
572                 }
573         }
574         type = AllocType((sg ? &sg->sg_ClassList : NULL), TY_UNRESOLVED);
575         type->ty_UnresType.et_DottedId = ary;
576         type->ty_UnresType.et_SemGroup = sg;            /* may be NULL */
577         type->ty_UnresType.et_ImportSemGroup = isg;     /* may be NULL */
578         return(type);
579 }
580
581 /*
582  * AllocClassType() - allocate a type representing a the semgroup which
583  *                      in turn represents (typically) a class.
584  */
585 Type *
586 AllocClassType(typelist_t *list, Type *super, SemGroup *sg, int visibility)
587 {
588         Type *type;
589
590         dassert(sg != NULL);
591         list = &sg->sg_ClassList;
592
593         RUNE_FOREACH(type, list, ty_Node) {
594                 if (type->ty_Op == TY_CLASS &&
595                     type->ty_ClassType.et_SemGroup == sg &&
596                     type->ty_ClassType.et_Super == super &&
597                     type->ty_Visibility == visibility
598                 ) {
599                         return(type);
600                 }
601         }
602         if (sg)
603                 dassert(&sg->sg_ClassList == list);
604         type = AllocType(list, TY_CLASS);
605         type->ty_ClassType.et_SemGroup = sg;
606         type->ty_ClassType.et_Super = super;
607         type->ty_Visibility = visibility;
608         return(type);
609 }
610
611 static
612 void
613 initInternalClassType(Type *type, Declaration *d)
614 {
615         SemGroup *sg = d->d_ClassDecl.ed_SemGroup;
616
617         initType(type, &sg->sg_ClassList, TY_CLASS);
618         RUNE_REMOVE(&sg->sg_ClassList, type, ty_Node);
619         RUNE_INSERT_HEAD(&sg->sg_ClassList, type, ty_Node);
620         type->ty_ClassType.et_SemGroup = d->d_ClassDecl.ed_SemGroup;
621         type->ty_ClassType.et_Super = d->d_ClassDecl.ed_Super;
622         type->ty_Visibility = d->d_ScopeFlags & SCOPE_ALL_VISIBLE;
623         type->ty_Flags |= TF_ISINTERNAL;
624 }
625
626 Type *
627 AllocImportType(typelist_t *list, SemGroup *sg, int visibility)
628 {
629         Type *type = AllocType(list, TY_IMPORT);
630
631         type->ty_ImportType.et_SemGroup = sg;
632         type->ty_Visibility = visibility;
633         return(type);
634 }
635
636 /*
637  * adjtype must be moved to type's QList because type is being modified
638  * such that that is where it is expected to be.
639  */
640 Type *
641 TypeAdjustQList(Type *type, Type *adjtype)
642 {
643         if (adjtype) {
644                 if (adjtype->ty_SQList)
645                         RUNE_REMOVE(adjtype->ty_SQList, adjtype, ty_Node);
646                 adjtype->ty_SQList = &type->ty_QList;
647                 RUNE_INSERT_TAIL(adjtype->ty_SQList, adjtype, ty_Node);
648         }
649         return type;
650 }
651
652 /*
653  * Adjust the type to be locked storage.  Assumes that compound types
654  * have not been cached/collapsed (parse-time only).
655  */
656 Type *
657 TypeAdjustLockedStorage(Type *type)
658 {
659         SemGroup *sg;
660         Declaration *d;
661
662         if (type->ty_Op != TY_COMPOUND)
663                 return type;
664
665         /*
666          * Assume no matching collapse yet
667          */
668         sg = type->ty_CompType.et_SemGroup;
669         RUNE_FOREACH(d, &sg->sg_DeclList, d_Node) {
670                 if (d->d_Op != DOP_GROUP_STORAGE)
671                         continue;
672                 d->d_ScopeFlags &= ~SCOPE_UNLOCKED;
673         }
674         return type;
675 }
676
677 Type *
678 TypeToQualType(Type *otype, Type *ntype, int sqFlags, Exp *exp)
679 {
680         SemGroup *sg;
681
682         /*
683          * Combine with existing qualifiers, Shortcut if no changes made.
684          */
685         if (ntype == NULL && 
686             sqFlags == otype->ty_SQFlags &&
687             (exp == NULL || exp == otype->ty_AssExp)
688         ) {
689                 return(otype);
690         }
691
692         /*
693          * See if we already have a matching qualified type (only if storage
694          * for the new type is not being provided).  Note: the provided storage
695          * has already been initType()d
696          */
697         if (ntype == NULL) {
698                 RUNE_FOREACH(ntype, otype->ty_SQList, ty_Node) {
699                         if (ntype->ty_Op == otype->ty_Op && 
700                             ntype->ty_SQFlags == sqFlags &&
701                             (exp == NULL || ntype->ty_AssExp == exp)
702                         ) {
703                                 if (SameType(ntype, otype, sqFlags))
704                                         return(ntype);
705                         }
706                 }
707         }
708
709         /*
710          * Build a new qualified type and set its qualifiers, then duplicate
711          * appropriate sections of the old type.
712          *
713          * Default to the same SQList as otype.
714          */
715         if (ntype == NULL) {
716                 ntype = AllocType(otype->ty_SQList, otype->ty_Op);
717         } else {
718                 if (ntype->ty_SQList)
719                         RUNE_REMOVE(ntype->ty_SQList, ntype, ty_Node);
720                 ntype->ty_SQList = otype->ty_SQList;
721                 RUNE_INSERT_TAIL(ntype->ty_SQList, ntype, ty_Node);
722         }
723
724         /*
725          * Set the op and the expression.  Unlike SQFlags, if exp is passed as
726          * NULL we inherit the old type's default.
727          *
728          * The DupExp() call here is special, see DupExp()'s handling of
729          * ex_Decl.
730          *
731          * Normally DupExp() is called during resolution prior to ex_Decl
732          * being set.  This is the one case where it may be called with
733          * ex_Decl already set.
734          *
735          * WARNING! We do not try to resolve the type here.  Various resolve
736          *          related flags in ty_Flags will be resolved later.  This
737          *          includes TF_ISUNSIGNED and other TF_* flags.
738          */
739         ntype->ty_Op = otype->ty_Op;
740         if (exp)
741                 ntype->ty_AssExp = exp;
742         else if (otype->ty_AssExp)
743                 ntype->ty_AssExp = SetDupExp(NULL, otype->ty_AssExp);
744         ntype->ty_SQFlags = sqFlags;
745         ntype->ty_Visibility = otype->ty_Visibility;
746
747         switch(otype->ty_Op) {
748         case TY_CLASS:
749                 /*
750                  * When updating the class, alternative forms are collapsed
751                  * into it's SemGroup->sg_ClassList and not into some
752                  * potentially long recursive chain based on ty_QList.
753                  */
754                 sg = otype->ty_ClassType.et_SemGroup;
755
756                 dassert(ntype->ty_SQList == &sg->sg_ClassList);
757                 if (ntype->ty_ClassType.et_SemGroup != sg) {
758                         ntype->ty_ClassType.et_SemGroup = sg;
759                 }
760                 ntype->ty_ClassType.et_Super = otype->ty_ClassType.et_Super;
761                 break;
762         case TY_IMPORT:
763                 ntype->ty_Visibility = otype->ty_Visibility;
764                 ntype->ty_ImportType.et_SemGroup = otype->ty_ImportType.et_SemGroup;
765                 break;
766         case TY_CPTRTO:
767                 ntype->ty_CPtrType.et_Type = otype->ty_CPtrType.et_Type;
768                 break;
769         case TY_PTRTO:
770                 ntype->ty_PtrType.et_Type = otype->ty_PtrType.et_Type;
771                 break;
772         case TY_REFTO:
773                 ntype->ty_RefType.et_Type = otype->ty_RefType.et_Type;
774                 break;
775         case TY_ARYOF:
776                 /*
777                  * note: multiple type structures may share the same array size
778                  * expression in simple qualified-type cases.  YYY XXX bad bad.
779                  */
780                 ntype->ty_AryType.et_Type = otype->ty_AryType.et_Type;
781                 ntype->ty_AryType.et_ArySize = otype->ty_AryType.et_ArySize;
782                 ntype->ty_AryType.et_SemGroup = otype->ty_AryType.et_SemGroup;
783                 ntype->ty_AryType.et_Count = otype->ty_AryType.et_Count;
784                 break;
785         case TY_COMPOUND:
786                 ntype->ty_CompType.et_SemGroup = otype->ty_CompType.et_SemGroup;
787                 break;
788         case TY_VAR:
789                 ntype->ty_VarType.et_Type = otype->ty_VarType.et_Type;
790                 ntype->ty_VarType.et_SemGroup = otype->ty_VarType.et_SemGroup;
791                 break;
792         case TY_ARGS:
793                 ntype->ty_ArgsType.et_SemGroup = otype->ty_ArgsType.et_SemGroup;
794                 break;
795         case TY_PROC:
796                 ntype->ty_ProcType.et_ArgsType = otype->ty_ProcType.et_ArgsType;
797                 ntype->ty_ProcType.et_RetType = otype->ty_ProcType.et_RetType;
798                 ntype->ty_ProcType.et_ArgCount = otype->ty_ProcType.et_ArgCount;
799                 dassert(ntype->ty_SQList ==
800                         &otype->ty_ProcType.et_RetType->ty_QList);
801                 break;
802         case TY_STORAGE:
803                 ntype->ty_StorType.et_Bytes = otype->ty_StorType.et_Bytes;
804                 break;
805         case TY_DYNAMIC:
806                 /*
807                  * It is not legal to qualify a dynamic type other then to
808                  * add or remove SF_LVALUE.
809                  */
810                 dpanic("Dynamic type cannot be qualified");
811                 break;
812         case TY_UNRESOLVED:
813                 ntype->ty_UnresType.et_DottedId =
814                         otype->ty_UnresType.et_DottedId;
815                 ntype->ty_UnresType.et_SemGroup =
816                         otype->ty_UnresType.et_SemGroup;
817                 ntype->ty_UnresType.et_ImportSemGroup =
818                         otype->ty_UnresType.et_ImportSemGroup;
819                 break;
820         default:
821                 dassert_type(otype, 0);
822         }
823         return(ntype);
824 }
825
826 /*
827  * Convert a return-type + argument-type into a procedure type.  If
828  * adjret is non-zero the return-type is converted to locked storage
829  * (which is generally what we want).
830  *
831  * Match the procedure type(s) (after adjustment?)
832  */
833 Type *
834 TypeToProcType(Type *rtype, Type *atype, int adjret)
835 {
836         Type *type;
837         runesize_t count = 0;
838         Declaration *d;
839         SemGroup *sg;
840
841         dassert_type(atype, atype->ty_Op == TY_ARGS);
842
843         if (adjret)
844                 rtype = TypeAdjustLockedStorage(rtype);
845
846         sg = atype->ty_CompType.et_SemGroup;
847
848         RUNE_FOREACH(d, &sg->sg_DeclList, d_Node) {
849                 ++count;
850         }
851         RUNE_FOREACH(type, &rtype->ty_QList, ty_Node) {
852                 if (type->ty_Op == TY_PROC) {
853                         if (type->ty_ProcType.et_ArgsType == atype &&
854                             type->ty_ProcType.et_RetType == rtype &&
855                             type->ty_ProcType.et_ArgCount == count
856                         ) {
857                                 return(type);
858                         }
859                 }
860         }
861         type = AllocType(&rtype->ty_QList, TY_PROC);
862         type->ty_ProcType.et_ArgsType = AllocArgsType(sg);
863         type->ty_ProcType.et_RetType = rtype;
864         type->ty_ProcType.et_ArgCount = count;
865         return(type);
866 }
867
868 /*
869  * Convert type to pointer-to-type
870  */
871 Type *
872 TypeToPtrType(Type *otype)
873 {
874         Type *type;
875
876         RUNE_FOREACH(type, &otype->ty_QList, ty_Node) {
877                 if (type->ty_Op == TY_PTRTO)
878                         return(type);
879         }
880         type = AllocType(&otype->ty_QList, TY_PTRTO);
881         type->ty_PtrType.et_Type = otype;
882         return(type);
883 }
884
885 /*
886  * Convert type to pointer-to-type
887  */
888 Type *
889 TypeToCPtrType(Type *otype)
890 {
891         Type *type;
892
893         RUNE_FOREACH(type, &otype->ty_QList, ty_Node) {
894                 if (type->ty_Op == TY_CPTRTO)
895                         return(type);
896         }
897         type = AllocType(&otype->ty_QList, TY_CPTRTO);
898         type->ty_CPtrType.et_Type = otype;
899         return(type);
900 }
901
902 /*
903  * Convert type to ref-to-type
904  *
905  *      A reference type is similar to a pointer type except that the
906  *      resolver is not able to entirely know what it is pointing to.
907  *      The reference type is a superclass, but the actual type is 
908  *      stored in the run-time structure.
909  */
910 Type *
911 TypeToRefType(Type *otype)
912 {
913         Type *type;
914
915         RUNE_FOREACH(type, &otype->ty_QList, ty_Node) {
916                 if (type->ty_Op == TY_REFTO)
917                         return(type);
918         }
919         type = AllocType(&otype->ty_QList, TY_REFTO);
920         type->ty_RefType.et_Type = otype;
921         return(type);
922 }
923
924 Type *
925 TypeToAryType(Type *otype, Exp *exp, SemGroup *sg)
926 {
927         Type *type;
928
929         /*
930          * XXX handle constant expression optimization for QList
931          * XXX handle qualifiers
932          */
933         type = AllocType(&otype->ty_QList, TY_ARYOF);
934         type->ty_AryType.et_ArySize = exp;
935         type->ty_AryType.et_Type = DelTypeQual(otype, SF_MASK_ARY_INHERIT);
936         type->ty_AryType.et_SemGroup = sg;
937         type->ty_SQFlags |= otype->ty_SQFlags & SF_MASK_ARY_INHERIT;
938         return(type);
939 }
940
941 #if 0
942
943 Type *
944 TypeToRunTimeAryType(Type *otype, int count)
945 {
946         Type *type;
947         Type *t2 = DelTypeQual(otype, SF_MASK_ARY_INHERIT);
948
949         RUNE_FOREACH(type, &otype->ty_QList, ty_Node) {
950                 if (type->ty_Op == TY_ARYOF &&
951                         type->ty_AryType.et_Type == t2 &&
952                         type->ty_AryType.et_Count == count &&
953                         type->ty_SQFlags ==
954                          (otype->ty_SQFlags & SF_MASK_ARY_INHERIT)
955                 ) {
956                         return(type);
957                 }
958         }
959         type = AllocType(&otype->ty_QList, TY_ARYOF);
960         type->ty_AryType.et_Count = count;
961         type->ty_AryType.et_Type = t2;
962         type->ty_SQFlags |= otype->ty_SQFlags & SF_MASK_ARY_INHERIT;
963         return(type);
964 }
965
966 #endif
967
968 Type *
969 TypeToVarType(Type *otype, SemGroup *sg)
970 {
971         Type *type;
972
973         /*dassert(sg->sg_Flags & SGF_RESOLVED);*/
974         /*dassert(otype->ty_Flags & TF_RESOLVED);*/
975
976         RUNE_FOREACH(type, &otype->ty_QList, ty_Node) {
977                 if (type->ty_Op == TY_VAR &&
978                     type->ty_VarType.et_Type == otype &&
979                     type->ty_VarType.et_SemGroup == sg
980                 ) {
981                         puts("SG2"); /* YYY */
982                         return(type);
983                 }
984         }
985         type = AllocType(&otype->ty_QList, TY_VAR);
986         type->ty_VarType.et_Type = otype;
987         type->ty_VarType.et_SemGroup = sg;
988 #if 0
989         /* XXX doesn't work for var-args */
990         if (sg->sg_Flags & SGF_RESOLVED) {
991                 type->ty_Flags |= TF_RESOLVED;
992                 type->ty_Bytes = sg->sg_Bytes;
993                 type->ty_AlignMask = sg->sg_AlignMask;
994         }
995 #endif
996         return(type);
997 }
998
999 /*
1000  * ChangeType() - given pointer, C pointer, or array of something,
1001  *                return 'op' of something instead.
1002  */
1003 Type *
1004 ChangeType(Type *type, int op)
1005 {
1006         switch(type->ty_Op) {
1007         case TY_PTRTO:
1008                 switch(op) {
1009                 case TY_CPTRTO:
1010                         type = TypeToCPtrType(type->ty_PtrType.et_Type);
1011                         break;
1012                 case TY_ARYOF:
1013                         type = TypeToAryType(type->ty_PtrType.et_Type,
1014                                              NULL, NULL);
1015                         break;
1016                 default:
1017                         dpanic("Illegal type convesion (A)");
1018                 }
1019                 break;
1020         case TY_CPTRTO:
1021                 switch(op) {
1022                 case TY_PTRTO:
1023                         type = TypeToPtrType(type->ty_CPtrType.et_Type);
1024                         break;
1025                 case TY_ARYOF:
1026                         type = TypeToAryType(type->ty_CPtrType.et_Type,
1027                                              NULL, NULL);
1028                         break;
1029                 default:
1030                         dpanic("Illegal type convesion (B)");
1031                 }
1032                 break;
1033         case TY_ARYOF:
1034                 switch(op) {
1035                 case TY_PTRTO:
1036                         type = TypeToPtrType(type->ty_AryType.et_Type);
1037                         break;
1038                 case TY_CPTRTO:
1039                         type = TypeToCPtrType(type->ty_AryType.et_Type);
1040                         break;
1041                 default:
1042                         dpanic("Illegal type convesion (C)");
1043                 }
1044                 break;
1045         default:
1046                 dpanic("Illegal type convesion (D)");
1047         }
1048         return(type);
1049 }
1050
1051 /*
1052  * BaseType() - return base type
1053  *
1054  *      Traverse the type to locate the base type.  Store the base type
1055  *      in *ptype and return the SemGroup, or return NULL if the base type
1056  *      does not have a SemGroup.
1057  */
1058 SemGroup *
1059 BaseType(Type **ptype)
1060 {
1061         Type *type = *ptype;
1062
1063         for (;;) {
1064                 switch(type->ty_Op) {
1065                 case TY_CPTRTO:
1066                         type = type->ty_CPtrType.et_Type;
1067                         continue;
1068                 case TY_PTRTO:
1069                         type = type->ty_PtrType.et_Type;
1070                         continue;
1071                 case TY_REFTO:
1072                         type = type->ty_RefType.et_Type;
1073                         continue;
1074                 case TY_ARYOF:
1075                         type = type->ty_AryType.et_Type;
1076                         continue;
1077                 }
1078                 break;
1079         }
1080
1081         *ptype = type;
1082
1083         switch(type->ty_Op) {
1084         case TY_CLASS:
1085                 return(type->ty_ClassType.et_SemGroup);
1086         case TY_COMPOUND:
1087                 return(type->ty_CompType.et_SemGroup);
1088         case TY_ARGS:
1089                 return(type->ty_ArgsType.et_SemGroup);
1090         case TY_PROC:
1091         case TY_VAR:
1092         case TY_DYNAMIC:
1093         case TY_STORAGE:
1094                 return(NULL);
1095         case TY_UNRESOLVED:
1096         default:
1097                 dassert_type(type, 0);
1098                 return(NULL);   /* avoid compiler complaints */
1099         }
1100 }
1101
1102 /*
1103  * DupType()     - create a duplicate of a type, possibly in a new SemGroup.
1104  *
1105  *      This code is used when duplicating procedures and other elements
1106  *      when merging a superclass into a subclass.
1107  *
1108  *      If sg is NULL, stype is simply returned.  The case is used when we
1109  *      try to duplciate an expression with DupExp()... in that case we
1110  *      want to dup the expression tree but use the same types.
1111  */
1112 Type *
1113 DupType(SemGroup *sg, Type *stype)
1114 {
1115         Type *type = NULL;
1116
1117         if (sg == NULL)
1118                 return(stype);
1119
1120         /*
1121          * XXX type may be resolved if it is part of a varargs dup
1122          */
1123 #if 0
1124         dassert_type(stype,
1125                      (stype->ty_Flags & (TF_RESOLVED|TF_RESOLVING)) == 0);
1126 #endif
1127
1128         switch(stype->ty_Op) {
1129         case TY_CLASS:
1130                 /*
1131                  * This only occurs because the resolver has resolved an
1132                  * unresolved type on the original SemGroup.  We duplicate
1133                  * that on the new SemGroup.
1134                  */
1135                 type = AllocClassType(&sg->sg_ClassList,
1136                                       stype->ty_ClassType.et_Super,
1137                                       stype->ty_ClassType.et_SemGroup,
1138                                       stype->ty_Visibility);
1139                 break;
1140         case TY_IMPORT:
1141         case TY_DYNAMIC:
1142                 type = stype;
1143                 break;
1144         case TY_CPTRTO:
1145                 type = TypeToCPtrType(DupType(sg, stype->ty_CPtrType.et_Type));
1146                 break;
1147         case TY_PTRTO:
1148                 type = TypeToPtrType(DupType(sg, stype->ty_PtrType.et_Type));
1149                 break;
1150         case TY_REFTO:
1151                 type = TypeToRefType(DupType(sg, stype->ty_RefType.et_Type));
1152                 break;
1153         case TY_ARYOF:
1154                 type = TypeToAryType(DupType(sg, stype->ty_AryType.et_Type),
1155                                 SetDupExp(sg, stype->ty_AryType.et_ArySize),
1156                                 stype->ty_AryType.et_SemGroup);
1157                 type->ty_AryType.et_Count = stype->ty_AryType.et_Count;
1158                 break;
1159         case TY_VAR:
1160                 type = TypeToVarType(DupType(sg, stype->ty_VarType.et_Type),
1161                                 DupSemGroup(sg, NULL,
1162                                             stype->ty_VarType.et_SemGroup, 1));
1163                 break;
1164         case TY_COMPOUND:
1165                 type = AllocCompoundType(
1166                                 DupSemGroup(sg, NULL,
1167                                             stype->ty_CompType.et_SemGroup, 1));
1168                 break;
1169         case TY_ARGS:
1170                 /*
1171                  * At the moment we always formally duplicate the arguments
1172                  * so we can modify them for methods below.
1173                  */
1174                 type = AllocArgsType(
1175                                 DupSemGroup(sg, NULL,
1176                                             stype->ty_CompType.et_SemGroup, 1));
1177                 break;
1178         case TY_PROC:
1179                 type = DupType(sg, stype->ty_ProcType.et_RetType);
1180                 type = TypeToProcType(type,
1181                                   DupType(sg, stype->ty_ProcType.et_ArgsType),
1182                                       1);
1183
1184                 /*
1185                  * If this is a method procedure, we have to change the
1186                  * first argument to point at our new subclass.  It was
1187                  * previously pointing at our superclass.   XXX the
1188                  * programmer can override the argument.  If it isn't a
1189                  * reference we have to assert.
1190                  */
1191                 if (sg->sg_Stmt->st_Op != ST_Class) {
1192                         /*
1193                          * XXX probably an inlined procedure, the type is
1194                          *     already correct.  Need an assertrion here.
1195                          */
1196                 } else if (stype->ty_SQFlags & SF_METHOD) {
1197                         SemGroup *asg = type->ty_ProcType.et_ArgsType->ty_ArgsType.et_SemGroup;
1198                         Declaration *d = RUNE_FIRST(&asg->sg_DeclList);
1199                         Type *thisType = d->d_StorDecl.ed_Type;
1200
1201                         dassert_decl(d, d->d_Id == String_This &&
1202                                         d->d_Op == DOP_ARGS_STORAGE);
1203                         dassert_decl(d, sg->sg_Stmt->st_Op == ST_Class);
1204                         if (thisType->ty_Op == TY_CLASS) {
1205                                 /* XXX sg_ClassList? right sg? */
1206                                 /* XXX correct visibility? */
1207                                 if (d->d_Search == NULL) {
1208                                         d->d_Search = d->d_StorDecl.ed_Type->
1209                                                       ty_ClassType.et_SemGroup;
1210                                 }
1211                                 d->d_StorDecl.ed_Type =
1212                                         AllocClassType(&sg->sg_ClassList,
1213                                                        sg->sg_Stmt->st_ClassStmt.es_Super,
1214                                                        sg->sg_Stmt->st_MyGroup,
1215                                                        SCOPE_ALL_VISIBLE);
1216                         } else {
1217                                 dassert_decl(d, thisType->ty_Op == TY_REFTO);
1218                         }
1219                 } else if (stype->ty_SQFlags & SF_GMETHOD) {
1220                         SemGroup *asg;
1221                         Declaration *d;
1222
1223                         asg = type->ty_ProcType.et_ArgsType->
1224                                 ty_ArgsType.et_SemGroup;
1225                         d = RUNE_FIRST(&asg->sg_DeclList);
1226
1227                         dassert_decl(d, d->d_Id == String_This &&
1228                                      d->d_Op == DOP_TYPEDEF);
1229                         dassert_decl(d, sg->sg_Stmt->st_Op == ST_Class);
1230                         dassert_decl(d, d->d_TypedefDecl.ed_Type->ty_Op ==
1231                                         TY_CLASS);
1232                         /* XXX sg_ClassList? right sg? */
1233                         /* XXX correct visibility? */
1234                         if (d->d_Search == NULL) {
1235                                 d->d_Search = d->d_TypedefDecl.ed_Type->
1236                                                ty_ClassType.et_SemGroup;
1237                         }
1238                         d->d_TypedefDecl.ed_Type =
1239                                 AllocClassType(&sg->sg_ClassList,
1240                                                sg->sg_Stmt->st_ClassStmt.es_Super,
1241                                                sg->sg_Stmt->st_MyGroup,
1242                                                SCOPE_ALL_VISIBLE);
1243                 }
1244                 break;
1245         case TY_STORAGE:
1246                 type = stype;
1247                 break;
1248         case TY_UNRESOLVED:
1249                 /*
1250                  * e.g. so elements in a superclass will see refined elements
1251                  * in the subclass.  Note that the original import semgroup
1252                  * is left intact so the semantic search mechanism uses it
1253                  * when the base sg (typically a subclass) fails.
1254                  */
1255                 type = AllocUnresolvedType(
1256                                 stype->ty_UnresType.et_ImportSemGroup,
1257                                 sg,
1258                                 stype->ty_UnresType.et_DottedId,
1259                                 0);
1260                 break;
1261         default:
1262                 dassert_type(stype, 0);
1263         }
1264
1265         if (type != stype) {
1266                 type->ty_Flags = stype->ty_Flags &
1267                                  ~(TF_ISINTERNAL | TF_RESOLVING | TF_RESOLVED |
1268                                    TF_ALIGNRESOLVED | TF_TMPRESOLVED);
1269                 type->ty_Bytes = stype->ty_Bytes;
1270                 type->ty_AlignMask = stype->ty_AlignMask;
1271                 type->ty_Visibility = stype->ty_Visibility;
1272                 type->ty_DynamicVector = stype->ty_DynamicVector;
1273         }
1274         if (stype->ty_AssExp || stype->ty_SQFlags != type->ty_SQFlags) {
1275                 type = TypeToQualType(type, NULL,
1276                                       stype->ty_SQFlags,
1277                                       SetDupExp(sg, stype->ty_AssExp));
1278         }
1279
1280         return(type);
1281 }
1282
1283 typereglist_t TypeRegList = RUNE_HEAD_INITIALIZER(TypeRegList);
1284
1285 void
1286 InternalRegisterType(const char *str, const char *linkname, Type *type)
1287 {
1288         static int Special = SPECIALF_REGISTERED|SPECIALF_INTERNAL|1;
1289         TypeRegNode *tr;
1290
1291         dassert(Special & SPECIALF_MASK);
1292         tr = zalloc(sizeof(TypeRegNode));
1293         tr->tr_Id = StrTableAlloc(str, strlen(str), Special++);
1294         tr->tr_Type = type;
1295         tr->tr_LinkName = linkname;
1296         RUNE_INSERT_TAIL(&TypeRegList, tr, tr_Node);
1297 }
1298
1299 Type *
1300 InternalRegisteredTypeLookup(string_t id)
1301 {
1302         TypeRegNode *tr;
1303
1304         RUNE_FOREACH(tr, &TypeRegList, tr_Node) {
1305                 if (tr->tr_Id == id)
1306                         return(tr->tr_Type);
1307         }
1308         return(NULL);
1309 }