2 * COLLAPSE.C - Collapse Declarations and Types
4 * (c)Copyright 1993-2014, Matthew Dillon, All Rights Reserved. See the
5 * COPYRIGHT file at the base of the distribution.
7 * This module is essentially optional but if we do not collapse duplicates
8 * the generated output will be massive to say the least.
10 * We can reach the entire tree by resolving the top-level import
11 * statement's DeclBlock.
18 static void CollapseClasses(Stmt *st);
21 static void collapseStmt(Stmt *st);
22 static void collapseDecl(Declaration *d, int dynamic);
23 static void collapseExp(Exp *exp);
24 static void collapseSemGroup(SemGroup *sg);
25 static void collapseType(Type **typep, Type *adjtype);
28 CollapseProject(Stmt *st)
33 dassert_stmt(st, st->st_Op == ST_Import);
36 * All of our base types should collapse to themselves. Easiest
37 * to just call it so the proper flags get set, otherwise they
38 * might not get generated.
40 for (i = 0; BaseTypeAry[i]; ++i) {
41 type = BaseTypeAry[i];
42 collapseType(&type, NULL);
43 dassert(type == BaseTypeAry[i]);
49 /*CollapseClasses(st);*/
59 CollapseClasses(Stmt *st)
66 if (st->st_Flags & (STF_COLLAPSING | STF_COLLAPSED))
69 if (st->st_Op == ST_Class && st->st_ClassStmt.es_Super) {
70 collapseType(&st->st_ClassStmt.es_Super, NULL);
71 collapseDecl(st->st_ClassStmt.es_Decl, 0);
75 * If this is an ST_Import we must recurse through it. The only
76 * statements under an Import should be Modules. Well, really just
77 * one module. And under that module we only care about ST_Import
78 * and ST_Class statements.
80 * If this is a shared import the statement list will be empty (later
81 * it may be used for import refinement, I dunno). This is what we
82 * want since we should only resolve a shared import once.
84 if (st->st_Op == ST_Import) {
87 st->st_Flags |= STF_COLLAPSING;
88 RUNE_FOREACH(scan, &st->st_List, st_Node) {
91 dassert_stmt(scan, scan->st_Op == ST_Module);
92 RUNE_FOREACH(scan2, &scan->st_List, st_Node) {
93 if (scan2->st_Op == ST_Import ||
94 scan2->st_Op == ST_Class) {
95 CollapseClasses(scan2);
100 if (st->st_ImportStmt.es_DLL) {
101 void (*func)(void) = dlsym(st->st_ImportStmt.es_DLL,
107 st->st_Flags &= ~STF_COLLAPSING;
108 st->st_Flags |= STF_COLLAPSED;
114 * collapseStmt() - Collapse all types, declarations, and semantic refs
116 * Collapses all types, declarations, and identifiers. Additionally
117 * this function collapses intermediate types for expressions.
121 collapseStmt(Stmt *st)
127 if (st->st_Flags & (STF_COLLAPSING | STF_COLLAPSED))
129 st->st_Flags |= STF_COLLAPSING;
131 if (st->st_Flags & STF_SEMANTIC) {
132 collapseSemGroup(st->st_MyGroup);
134 SemGroup *sg = st->st_MyGroup;
137 RUNE_FOREACH(type, &sg->sg_ClassList, ty_Node) {
138 if (type->ty_Op == TY_UNRESOLVED) {
139 if (resolveSuperClass(type) == NULL) {
141 type->ty_UnresType.et_DottedId,
142 "Unable to resolve class");
151 * Collapse statements.
156 * This will just flag the import declaration as resolved
157 * so the code generator dives it for generation.
159 if (st->st_ImportStmt.es_Decl)
160 collapseDecl(st->st_ImportStmt.es_Decl, 0);
164 * Recursively resolve contents
166 RUNE_FOREACH(scan, &st->st_List, st_Node) {
171 collapseType(&st->st_ClassStmt.es_Super, NULL);
172 collapseDecl(st->st_ClassStmt.es_Decl, 0);
175 collapseDecl(st->st_TypedefStmt.es_Decl, 0);
179 * Resolve declarations, skipping any whos context was
180 * moved to a class (e.g. a declaration at the top level
181 * of a file like Fd.setfd(...) also exists in the Fd class).
184 Declaration *d = st->st_DeclStmt.es_Decl;
187 for (i = 0; i < st->st_DeclStmt.es_DeclCount; ++i) {
188 if (st->st_MyGroup != d->d_MyGroup)
189 /*printf("SKIPA %s\n", d->d_Id)*/;
192 d = RUNE_NEXT(d, d_Node);
197 RUNE_FOREACH(scan, &st->st_List, st_Node) {
204 collapseStmt(st->st_LoopStmt.es_Init);
205 collapseExp(st->st_LoopStmt.es_BCond);
206 collapseExp(st->st_LoopStmt.es_ACond);
207 collapseExp(st->st_LoopStmt.es_AExp);
208 collapseStmt(st->st_LoopStmt.es_Body);
216 * NOTE: BoolType global implies an rvalue.
218 collapseExp(st->st_IfStmt.es_Exp);
219 collapseStmt(st->st_IfStmt.es_TrueStmt);
220 collapseStmt(st->st_IfStmt.es_FalseStmt);
223 collapseType(&st->st_RetStmt.es_ProcRetType, NULL);
224 collapseExp(st->st_RetStmt.es_Exp);
227 collapseType(&st->st_ResStmt.es_ProcRetType, NULL);
228 collapseExp(st->st_ResStmt.es_Exp);
232 * NOTE: Switch type must be an rvalue.
234 * NOTE: It is possible to switch on a type. See ST_Case
235 * below for more detail.
237 collapseExp(st->st_SwStmt.es_Exp);
238 RUNE_FOREACH(scan, &st->st_List, st_Node) {
244 * Handle a case/default. Note that when switching on a type,
245 * each case expression must return a type.
247 * NOTE: Case type must be an rvalue. We use the switch type
248 * to cast, so it will be.
251 dassert_stmt(st, st->st_Parent->st_Op == ST_Switch);
254 * Elements of the case/default
256 collapseExp(st->st_CaseStmt.es_Exp);
257 RUNE_FOREACH(scan, &st->st_List, st_Node) {
264 * NOTE: VoidType global implies an rvalue.
266 * NOTE: If resolveExp() doesn't cast to void for
267 * us, we will do it here.
269 collapseExp(st->st_ExpStmt.es_Exp);
272 RUNE_FOREACH(scan, &st->st_List, st_Node) {
282 st->st_Flags &= ~STF_COLLAPSING;
283 st->st_Flags |= STF_COLLAPSED;
287 * collapseDecl() - collapse a declaration
291 collapseDecl(Declaration *d, int dynamic)
297 if (d->d_Flags & (DF_COLLAPSING | DF_COLLAPSED))
299 if ((d->d_Flags & DF_RESOLVED) == 0)
301 d->d_Flags |= DF_COLLAPSING;
302 if (d->d_Flags & DF_ADDRUSED)
303 d->d_InfoIndex = d->d_MyGroup->sg_InfoCount++;
307 collapseType(&d->d_ClassDecl.ed_Super, NULL);
308 sg = d->d_ClassDecl.ed_SemGroup;
309 collapseSemGroup(sg);
310 d->d_MyGroup->sg_InfoCount += sg->sg_InfoCount;
314 * Alias access is a barrier and always returns an rvalue.
316 collapseType(&d->d_AliasDecl.ed_Type, NULL);
317 collapseExp(d->d_AliasDecl.ed_AssExp);
320 collapseType(&d->d_TypedefDecl.ed_Type, NULL);
324 * This only occurs when resolving an import's semantic group.
325 * Since we are scanning statements in that context we do not
326 * have to recurse here, collapseStmt() will do it for us.
331 * XXX global procedure, later on, make the argument a
332 * type instead of storage?
334 collapseType(&d->d_ProcDecl.ed_Type, NULL);
335 collapseStmt(d->d_ProcDecl.ed_ProcBody); /* XXX */
336 collapseStmt(d->d_ProcDecl.ed_OrigBody); /* XXX */
338 case DOP_ARGS_STORAGE:
339 case DOP_STACK_STORAGE:
340 case DOP_GLOBAL_STORAGE:
341 case DOP_GROUP_STORAGE:
342 collapseType(&d->d_StorDecl.ed_Type, NULL);
343 collapseExp(d->d_StorDecl.ed_AssExp);
348 d->d_Flags &= ~DF_COLLAPSING;
349 d->d_Flags |= DF_COLLAPSED | DF_LAYOUT;
354 for (scan = d->d_SubBase; scan; scan = scan->d_SubNext)
355 collapseDecl(scan, 1);
364 collapseExp(Exp *exp)
370 if (exp->ex_Flags & (EXF_COLLAPSING | EXF_COLLAPSED))
372 exp->ex_Flags |= EXF_COLLAPSING;
374 collapseType(&exp->ex_Type, NULL);
375 collapseDecl(exp->ex_Decl, 0);
377 switch(exp->ex_Token) {
381 collapseExp(exp->ex_Lhs);
382 collapseExp(exp->ex_Rhs);
388 collapseExp(exp->ex_Lhs);
391 * Resolver might have turned RHS into a SEMGRP_ID, only
392 * collapse if it hasn't. XXX
394 if (exp->ex_Rhs->ex_Token != TOK_SEMGRP_ID)
395 collapseExp(exp->ex_Rhs);
400 collapseExp(exp->ex_Lhs);
401 collapseExp(exp->ex_Rhs);
404 collapseExp(exp->ex_Lhs);
407 collapseExp(exp->ex_Lhs);
410 collapseExp(exp->ex_Lhs);
411 collapseExp(exp->ex_Rhs);
414 dassert_exp(exp, 0); /* XXX */
429 collapseExp(exp->ex_Lhs);
434 collapseExp(exp->ex_Lhs);
435 /* RHS was converted to type */
437 case TOK_INLINE_CALL:
438 collapseExp(exp->ex_Lhs);
439 collapseExp(exp->ex_Rhs);
440 collapseStmt(exp->ex_AuxStmt);
441 if (exp->ex_Lhs->ex_Token == TOK_STRIND &&
442 exp->ex_Lhs->ex_Lhs->ex_Type &&
443 exp->ex_Lhs->ex_Lhs->ex_Type->ty_Op == TY_REFTO) {
444 collapseDecl(exp->ex_Lhs->ex_Decl, 1);
448 collapseExp(exp->ex_Lhs);
449 collapseExp(exp->ex_Rhs);
450 if (exp->ex_Lhs->ex_Token == TOK_STRIND &&
451 exp->ex_Lhs->ex_Lhs->ex_Type &&
452 exp->ex_Lhs->ex_Lhs->ex_Type->ty_Op == TY_REFTO) {
453 collapseDecl(exp->ex_Lhs->ex_Decl, 1);
458 for (scan = exp->ex_Lhs; scan; scan = scan->ex_Next)
465 collapseExp(exp->ex_Lhs);
467 case TOK_ERR_EXP_REMOVED:
470 fprintf(stderr, "BADEXP %p %08x\n", exp, exp->ex_Token);
471 /* dassert_exp(exp, 0); */
475 exp->ex_Flags &= ~EXF_COLLAPSING;
476 exp->ex_Flags |= EXF_COLLAPSED;
480 * Collapse a SemGroup. The SemGroup may be used even if not resolved
481 * if individual functions were picked out of it without instantiating
486 collapseSemGroup(SemGroup *sg)
492 if (sg->sg_Flags & (SGF_COLLAPSING | SGF_COLLAPSED))
494 if ((sg->sg_Flags & (SGF_RESOLVED | SGF_ALIGNRESOLVED)) == 0)
496 sg->sg_Flags |= SGF_COLLAPSING;
498 RUNE_FOREACH(d, &sg->sg_DeclList, d_Node) {
499 if (d->d_Flags & DF_RESOLVED)
502 sg->sg_Flags &= ~SGF_COLLAPSING;
503 sg->sg_Flags |= SGF_COLLAPSED | SGF_LAYOUT;
507 * Match basic type fields. Note that the TF_RESOLVE* flags must also match.
508 * (that is, we do not match a resolved against an unresolved type).
512 matchbasicfields(Type *type, Type *scan)
514 if (type->ty_Op == scan->ty_Op &&
515 (type->ty_Flags & ~(TF_COLLAPSED | TF_LAYOUT)) ==
516 (scan->ty_Flags & ~(TF_COLLAPSED | TF_LAYOUT)) &&
517 type->ty_AssExp == scan->ty_AssExp &&
518 type->ty_Bytes == scan->ty_Bytes &&
519 type->ty_AlignMask == scan->ty_AlignMask &&
520 type->ty_SQFlags == scan->ty_SQFlags &&
521 type->ty_Visibility == scan->ty_Visibility &&
522 type->ty_TmpBytes == scan->ty_TmpBytes &&
523 type->ty_TmpAlignMask == scan->ty_TmpAlignMask) {
531 * Resolve a type and attempt to remove duplicates that were present as
536 collapseType(Type **typep, Type *adjtype)
546 if ((type->ty_Flags & TF_RESOLVED) == 0)
548 if (type->ty_Flags & TF_COLLAPSED) {
549 if (type->ty_Flags & TF_LAYOUT)
551 /* re-execute (XXX cache in type->ty_CollapsedType) */
553 type->ty_Flags |= TF_COLLAPSED;
556 * Otherwise try to collapse
561 printf("; CHECKTYPE l=%p %s\n", type->ty_SQList, TypeToStr(type, NULL));
564 switch(type->ty_Op) {
566 dassert(type->ty_SQList ==
567 &type->ty_ClassType.et_SemGroup->sg_ClassList);
568 collapseType(&type->ty_ClassType.et_Super, NULL);
569 collapseSemGroup(type->ty_ClassType.et_SemGroup);
570 if (type->ty_ClassType.et_Super) {
571 dassert((type->ty_ClassType.et_Super->ty_Flags &
574 if (type->ty_Flags & TF_ISINTERNAL) {
579 sg = type->ty_ClassType.et_SemGroup;
580 dassert(type->ty_SQList == &sg->sg_ClassList);
581 RUNE_FOREACH(scan, &sg->sg_ClassList, ty_Node) {
583 printf("; TEST %s\t", TypeToStr(scan, NULL));
585 if (matchbasicfields(type, scan) &&
586 type->ty_ClassType.et_SemGroup ==
587 scan->ty_ClassType.et_SemGroup &&
588 type->ty_ClassType.et_Super ==
589 scan->ty_ClassType.et_Super) {
594 if (type->ty_Op != scan->ty_Op)
596 if ((type->ty_Flags & ~TF_COLLAPSED) !=
597 (scan->ty_Flags & ~TF_COLLAPSED))
599 if (type->ty_AssExp != scan->ty_AssExp)
601 if (type->ty_Bytes != scan->ty_Bytes)
603 if (type->ty_AlignMask != scan->ty_AlignMask)
605 if (type->ty_SQFlags != scan->ty_SQFlags)
607 if (type->ty_Visibility != scan->ty_Visibility)
608 printf(" vis[%d,%d]",
610 scan->ty_Visibility);
611 if (type->ty_TmpBytes != scan->ty_TmpBytes)
613 if (type->ty_TmpAlignMask != scan->ty_TmpAlignMask)
615 if (type->ty_ClassType.et_SemGroup !=
616 scan->ty_ClassType.et_SemGroup)
618 if (type->ty_ClassType.et_Super !=
619 scan->ty_ClassType.et_Super)
631 dassert(type->ty_SQList ==
632 &type->ty_PtrType.et_Type->ty_QList);
633 collapseType(&type->ty_PtrType.et_Type, type);
634 if (type->ty_Flags & TF_ISINTERNAL) {
638 RUNE_FOREACH(scan, &type->ty_PtrType.et_Type->ty_QList, ty_Node) {
640 printf("; TEST %s\n", TypeToStr(scan, NULL));
642 if (matchbasicfields(type, scan) &&
643 type->ty_PtrType.et_Type ==
644 scan->ty_PtrType.et_Type) {
652 dassert(type->ty_SQList ==
653 &type->ty_AryType.et_Type->ty_QList);
655 collapseType(&type->ty_AryType.et_Type, type);
656 if (type->ty_Flags & TF_ISINTERNAL) {
660 RUNE_FOREACH(scan, &type->ty_AryType.et_Type->ty_QList, ty_Node) {
662 printf("; TEST %s\n", TypeToStr(scan, NULL));
664 if (matchbasicfields(type, scan) &&
665 type->ty_AryType.et_SemGroup ==
666 scan->ty_AryType.et_SemGroup &&
667 type->ty_AryType.et_Type ==
668 scan->ty_AryType.et_Type &&
669 type->ty_AryType.et_Count ==
670 scan->ty_AryType.et_Count) {
677 collapseSemGroup(type->ty_CompType.et_SemGroup);
678 dassert(type->ty_SQList == &CompoundTypeList);
679 if (type->ty_Flags & TF_ISINTERNAL) {
683 RUNE_FOREACH(scan, &CompoundTypeList, ty_Node) {
685 printf("; TEST %s\n", TypeToStr(scan, NULL));
687 if (matchbasicfields(type, scan) &&
688 type->ty_CompType.et_SemGroup ==
689 scan->ty_CompType.et_SemGroup) {
696 collapseSemGroup(type->ty_CompType.et_SemGroup);
697 dassert(type->ty_SQList == &ArgsTypeList);
698 if (type->ty_Flags & TF_ISINTERNAL) {
702 RUNE_FOREACH(scan, &ArgsTypeList, ty_Node) {
704 printf("; TEST %s\n", TypeToStr(scan, NULL));
706 if (matchbasicfields(type, scan) &&
707 type->ty_CompType.et_SemGroup ==
708 scan->ty_CompType.et_SemGroup) {
715 collapseSemGroup(type->ty_VarType.et_SemGroup);
716 scan = type; /* XXX */
720 * NOTE: Storage not tracked.
723 dassert(type->ty_SQList ==
724 &type->ty_ProcType.et_RetType->ty_QList);
726 collapseType(&type->ty_ProcType.et_ArgsType, NULL);
727 collapseType(&type->ty_ProcType.et_RetType, type);
728 if (type->ty_Flags & TF_ISINTERNAL) {
733 RUNE_FOREACH(scan, &type->ty_ProcType.et_RetType->ty_QList, ty_Node) {
735 printf("; TEST %s\n", TypeToStr(scan, NULL));
737 if (matchbasicfields(type, scan) &&
738 type->ty_ProcType.et_ArgsType ==
739 scan->ty_ProcType.et_ArgsType &&
740 type->ty_ProcType.et_RetType ==
741 scan->ty_ProcType.et_RetType &&
742 type->ty_ProcType.et_ArgCount ==
743 scan->ty_ProcType.et_ArgCount) {
750 dassert(type->ty_SQList == &StorageTypeList);
751 if (type->ty_Flags & TF_ISINTERNAL) {
755 RUNE_FOREACH(scan, &StorageTypeList, ty_Node) {
757 printf("; TEST %s\n", TypeToStr(scan, NULL));
759 if (matchbasicfields(type, scan) &&
760 type->ty_StorType.et_Bytes ==
761 scan->ty_StorType.et_Bytes) {
768 scan = type; /* XXX */
771 dassert(type->ty_SQList == &DynamicTypeList);
772 if (type->ty_Flags & TF_ISINTERNAL) {
776 RUNE_FOREACH(scan, &DynamicTypeList, ty_Node) {
778 printf("; TEST %s\n", TypeToStr(scan, NULL));
780 if (matchbasicfields(type, scan)) {
787 scan = type; /* XXX */
791 dpanic("Unknown type %d (type=%p)", type->ty_Op, type);
794 dassert(scan != NULL); /* we should find at least ourselves */
797 collapseType(&type, NULL);
799 RUNE_REMOVE(adjtype->ty_SQList, adjtype, ty_Node);
800 adjtype->ty_SQList = &type->ty_QList;
801 RUNE_INSERT_TAIL(adjtype->ty_SQList, adjtype, ty_Node);
804 printf("; COLLAPSE %s <- %s\n",
805 TypeToStr(type, NULL), TypeToStr(otype, NULL));
806 if (type->ty_Op == TY_CLASS && type->ty_ClassType.et_Super &&
807 type->ty_ClassType.et_Super != otype->ty_ClassType.et_Super)
808 printf("; SUPERCLASS %s <- %s\n",
809 TypeToStr(type->ty_ClassType.et_Super, NULL), TypeToStr(otype->ty_ClassType.et_Super, NULL));
815 printf("; MATCHEDSAME\n");
818 type->ty_Flags |= TF_LAYOUT;