2 * RESOLVE.C - Resolve parser tree
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 responsible for resolving unresolved types and
8 * classes, generating offsets for DeclBlock's and declarations, and
9 * resolving type-rules for expressions in the expression tree.
11 * We can reach the entire tree by resolving the top-level import
12 * statement's DeclBlock.
18 static void ResolveClasses(Stmt *st);
19 static void ResolveTypes(SemGroup *isg, Stmt *st);
20 static void ResolveStorage(Stmt *st);
21 static void errorDottedId(string_t *ary, const char *ctl, ...);
23 static Type *resolveReturnType(SemGroup *sg);
24 static Type *resolveArgsType(SemGroup *sg);
25 static void resolveDecl(Declaration *d);
26 static Exp *resolveExp(SemGroup *isg, SemGroup *sg,
27 Exp *exp, Type *itype, int autocast);
28 static Exp *resolveConstExp(SemGroup *isg, SemGroup *sg, Exp *exp);
29 static Exp *resolveCompoundExp(SemGroup *isg, SemGroup *sg,
30 Exp *exp, Type *itype);
31 static Exp *resolveExpCast(SemGroup *isg, SemGroup *sg,
32 Exp *exp, Type *ltype);
33 static Exp *resolveExpOper(SemGroup *isg, SemGroup *sg,
34 Exp *exp, Type *itype);
35 static int resolveSemGroup1(SemGroup *sg);
36 static void resolveSemGroup2(SemGroup *sg);
37 static Type *resolveSuperClass(Type *super);
38 static void resolveStorageDeclExp(Declaration *d,
39 runesize_t *offset, runesize_t *goffset);
40 static runesize_t resolveStorageExpOnly(Exp *exp, runesize_t *offset);
41 static void resolveStorageExpSub(Exp *exp, runesize_t *offset);
42 static void resolveStorageExp(Exp *exp, runesize_t *offset);
44 static Declaration *findOper(Type *btype, string_t id,
45 Type *ltype, Type *rtype);
46 static Declaration *findExpOper(Exp *exp);
47 static Declaration *findCast(Type *btype, Type *ltype, Type *rtype);
48 static void loadExpCopy(Exp *copy, Exp *exp);
49 static void saveExpCopy(Exp *copy, Exp *exp);
50 static Exp *dupExpCopy(Exp *copy, Exp *exp);
51 static void resolveStorageType(Type *type);
52 static void resolveStorageSemGroup(SemGroup *sg,
53 runesize_t noffset, runesize_t ngoffset);
55 #define exLhs copy.ex_Lhs
56 #define exRhs copy.ex_Rhs
57 #define exFlags copy.ex_Flags
58 #define exType copy.ex_Type
59 #define exToken copy.ex_Token
60 #define exDecl copy.ex_Decl
61 #define exVisibility copy.ex_Visibility
62 #define exId copy.ex_Id
63 #define exArgId copy.ex_ArgId
65 #define ADD_LVALUE(type) resolveType(AddTypeQual((type), SF_LVALUE))
66 #define DEL_LVALUE(type) resolveType(DelTypeQual((type), SF_LVALUE))
69 ResolveProject(Parse *p, Stmt *st)
71 dassert_stmt(st, st->st_Op == ST_Import);
73 ResolveTypes(st->st_MyGroup, st);
75 p->p_Format = PFMT_RESOLVED;
79 * ResolveClasses() - Resolve superclasses and do class merge
81 * This code implements the most complex feature of the language:
82 * subclassing and refinement.
84 * The hardest thing we have to do is 'dup' declarations and code in
85 * order to implement subclassing and refinement. For example, a
86 * procedure defined in Integer must be dup'd for each subclass of
87 * Integer. We have to do this because storage requirements will
88 * change due to both subclassing and refinement. Even auto variables
89 * may wind up with different types between superclass and subclass.
91 * We must scan ST_Import and ST_Class statements.
94 ResolveClasses(Stmt *st)
96 SemGroup *sg = st->st_MyGroup;
99 * Resolver interlock. Assert that we aren't looping. A loop can
100 * occur if class A embeds class B and class B embeds class A
101 * (verses a pointer to A).
103 dassert_stmt(st, (st->st_Flags & STF_RESOLVING) == 0);
104 if (st->st_Flags & STF_RESOLVED)
106 st->st_Flags |= STF_RESOLVING;
109 * If this is a subclass, integrate the superclass into it
111 if (st->st_Op == ST_Class && st->st_ClassStmt.es_Super) {
112 Type *super = st->st_ClassStmt.es_Super;
119 * Locate the superclass. 'super' does not appear in any
120 * other list.. this is a unique Type structure.
122 dassert_stmt(st, super->ty_Op == TY_UNRESOLVED);
124 super = resolveSuperClass(super);
127 "Unable to resolve superclass of %s\n",
128 st->st_ClassStmt.es_Decl->d_Id);
131 } while (super->ty_Op == TY_UNRESOLVED);
133 dassert_stmt(st, super->ty_Op == TY_CLASS);
136 * Cleanup (XXX free qualified segments??)
138 st->st_ClassStmt.es_Super = super;
139 st->st_ClassStmt.es_Decl->d_ClassDecl.ed_Super = super;
142 * Inherit internal unsigned integer and floating point flags.
144 sg->sg_Flags |= super->ty_ClassType.et_SemGroup->sg_Flags &
145 (SGF_ISUNSIGNED | SGF_ISFLOATING);
148 * Locate the class statement associated with the superclass
151 sst = super->ty_ClassType.et_SemGroup->sg_Stmt;
152 dassert_stmt(st, sst != NULL);
153 dassert_stmt(st, sst->st_Op == ST_Class);
158 * Assign the sg_Level for the subclass. This is used
159 * for semantic searches when a subclass is passed to a
160 * procedure expecting the superclass.
162 sg->sg_Level = sst->st_MyGroup->sg_Level + 1;
165 * First move all the declarations from sg to tsg so we
166 * can merge the superclass properly (keep all the d_Index's
167 * correct). Note that tsg is not 100% integrated so we can
168 * only use it for search purposes. We absolutely CANNOT
169 * DupDeclaration() into tsg!
171 tsg = AllocSemGroup(sg->sg_Parse, NULL, sg->sg_Stmt);
172 while ((d = getHead(&sg->sg_DeclList)) != NULL) {
175 sg->sg_DeclCount = 0; /* reset */
178 * Merge the superclass into this class, in sequence.
179 * Iterate through declarations in the superclass and pull
180 * them into the subclass. Figure out compatibility between
181 * super and subclasses.
184 d = getHead(&sst->st_MyGroup->sg_DeclList);
186 d = getSucc(&sst->st_MyGroup->sg_DeclList, &d->d_Node)
191 dassert(d->d_Level != NULL &&
192 d->d_Level->sg_Level < sg->sg_Level);
195 * See if the superclass decl conflicts with a
196 * subclass decl. If there is no conflict pull it
197 * into the subclass and adjust the visibility.
198 * Note that the superclass may have duplicate ids,
199 * but they will be at different levels if so.
201 * The super linkage is required when findDecl()
202 * checks visibility of a declaration hidden relative
203 * to our subclass, but not necessarily hidden
204 * relative to the superclass.
208 rd = FindDeclId(tsg, d->d_Id, &eno);
210 nd = DupDeclaration(sg, d);
211 dassert(d->d_Index == nd->d_Index);
212 nd->d_ScopeFlags &= ~SCOPE_ALL_VISIBLE |
213 super->ty_Visibility;
214 nd->d_ScopeFlags &= ~SCOPE_REFINE;
219 * If there is a conflict and we are not refining
220 * the superclass entity, then pull it in and make
221 * it invisible to sg_Level searches. This could
222 * bring in multiple levels of the same id.
224 * Note that this may result in multiple ids, but
225 * they will be at different levels. In this case
226 * rd will be at the current level and nd will be
227 * at some prior level.
229 if ((rd->d_ScopeFlags & SCOPE_REFINE) == 0) {
230 nd = DupDeclaration(sg, d);
231 dassert(d->d_Index == nd->d_Index);
232 nd->d_ScopeFlags &= ~(SCOPE_ALL_VISIBLE |
235 printf(" conflict, not refined, overload\n");
241 * Ok, we need to refine. But the superclass may
242 * contain multiple levels of the same id. We only
243 * refine the one that is visible to us. None of
244 * these other declarations will be at the same level.
246 if ((d->d_ScopeFlags & SCOPE_ALL_VISIBLE) == 0) {
247 nd = DupDeclaration(sg, d);
248 dassert(d->d_Index == nd->d_Index);
249 nd->d_ScopeFlags &= ~(SCOPE_ALL_VISIBLE |
252 printf(" conflict, refined (skip this one)\n");
258 * Whew! Finally, we found the superclass decl
259 * that we wish to refine. We had better not have
260 * already refined it or there's something wrong
261 * with the algorithm.
263 * Since we inherit the superclass method's level
264 * our method will run in the superclass instead
265 * of the original, but d_Super still must be set
266 * for findDecl() to track down visibility relative
267 * to the superclass methods.
270 dassert_decl(rd, rd->d_Super == NULL);
271 dassert(d->d_Index == rd->d_Index);
272 rd->d_Level = d->d_Level;
276 * This is for the superclass method access special
279 if (d->d_Op == DOP_PROC) {
280 d->d_Flags |= DF_SUPERCOPY;
285 * Deal with any remaining elements in tsg. These are
286 * 'extensions' to the superclass. There may also be
287 * invisible DOP_PROC's to handle the special superclass
288 * method call case descibed above.
290 while ((rd = getHead(&tsg->sg_DeclList)) != NULL) {
291 if (rd->d_ScopeFlags & SCOPE_REFINE) {
292 if (rd->d_Super == NULL) {
294 "Unable to refine %s, it "
307 * We have to special case super.method() for a refined method.
308 * Normally this makes the original method inaccessible (for
309 * storage), but we want it to work for a procedure so we make
310 * a copy in tsg. (we can't dup it directly into sg because it
311 * will screw up the d_Index).
313 * We must not only clear the scope visibility and the
314 * temporary refine flag, we also have to clear
315 * constructor/destructor scope in the copy so only the
316 * refined constructor/destructor is called, not both the
317 * refined and the superclass constructor/destructor.
320 d = getHead(&sst->st_MyGroup->sg_DeclList);
322 d = getSucc(&sst->st_MyGroup->sg_DeclList, &d->d_Node)
326 if (d->d_Flags & DF_SUPERCOPY) {
327 d->d_Flags &= ~DF_SUPERCOPY;
328 nd = DupDeclaration(sg, d);
329 nd->d_ScopeFlags &= ~(SCOPE_ALL_VISIBLE |
335 } else if (st->st_Op == ST_Class) {
339 st->st_Flags &= ~STF_RESOLVING;
340 st->st_Flags |= STF_RESOLVED;
343 * If this is an ST_Import we must recurse through it. The only
344 * statements under an Import should be Modules. Well, really just
345 * one module. And under that module we only care about ST_Import
346 * and ST_Class statements.
348 * If this is a shared import the statement list will be empty (later
349 * it may be used for import refinement, I dunno). This is what we
350 * want since we should only resolve a shared import once.
352 if (st->st_Op == ST_Import) {
356 scan = getHead(&st->st_List);
358 scan = getSucc(&st->st_List, &scan->st_Node)
362 dassert_stmt(scan, scan->st_Op == ST_Module);
364 scan2 = getHead(&scan->st_List);
366 scan2 = getSucc(&scan->st_List, &scan2->st_Node)
368 if (scan2->st_Op == ST_Import ||
369 scan2->st_Op == ST_Class) {
370 ResolveClasses(scan2);
374 if (st->st_ImportStmt.es_DLL) {
375 void (*func)(void) = dlsym(st->st_ImportStmt.es_DLL,
384 * ResolveTypes() - Resolve all types, declarations, and semantic refs
386 * Resolves all types, declarations, and identifiers. Additionally
387 * this function resolves intermediate types for expressions. Storage
388 * sizes are resolved but offsets are not assigned to declarations.
391 ResolveTypes(SemGroup *isg, Stmt *st)
394 * Deal with unresolved types here
396 if (st->st_Flags & STF_SEMANTIC) {
397 SemGroup *sg = st->st_MyGroup;
401 type = getHead(&sg->sg_ClassList);
403 type = getSucc(&sg->sg_ClassList, &type->ty_Node)
405 if (type->ty_Op == TY_UNRESOLVED) {
406 if (resolveSuperClass(type) == NULL) {
408 type->ty_UnresType.et_DottedId,
409 "Unable to resolve class");
417 * Resolve statements. Don't worry about declarations, those are
418 * handled after this switch.
424 * Recursively resolve contents
429 scan = getHead(&st->st_List);
431 scan = getSucc(&st->st_List, &scan->st_Node)
434 * XXX pass isg for import, st_MyGroup for
437 ResolveTypes(st->st_MyGroup, scan);
439 if (st->st_Op == ST_Import &&
440 st->st_ImportStmt.es_DLL) {
442 dlsym(st->st_ImportStmt.es_DLL,
450 resolveDecl(st->st_ClassStmt.es_Decl);
453 resolveDecl(st->st_TypedefStmt.es_Decl);
457 Declaration *d = st->st_DeclStmt.es_Decl;
460 for (i = 0; i < st->st_DeclStmt.es_DeclCount; ++i) {
462 d = getSucc(&d->d_MyGroup->sg_DeclList,
471 scan = getHead(&st->st_List);
473 scan = getSucc(&st->st_List, &scan->st_Node)
475 ResolveTypes(isg, scan);
482 if (st->st_LoopStmt.es_Init)
483 ResolveTypes(isg, st->st_LoopStmt.es_Init);
484 if (st->st_LoopStmt.es_BCond) {
486 * NOTE: BoolType global implies an rvalue.
488 st->st_LoopStmt.es_BCond =
489 resolveExp(isg, st->st_MyGroup,
490 st->st_LoopStmt.es_BCond,
493 if (st->st_LoopStmt.es_ACond) {
495 * NOTE: BoolType global implies an rvalue.
497 st->st_LoopStmt.es_ACond =
498 resolveExp(isg, st->st_MyGroup,
499 st->st_LoopStmt.es_ACond,
502 if (st->st_LoopStmt.es_AExp) {
504 * NOTE: VoidType global implies an rvalue.
506 st->st_LoopStmt.es_AExp =
507 resolveExp(isg, st->st_MyGroup,
508 st->st_LoopStmt.es_AExp,
511 if (st->st_LoopStmt.es_Body) {
512 ResolveTypes(isg, st->st_LoopStmt.es_Body);
521 * NOTE: BoolType global implies an rvalue.
523 st->st_IfStmt.es_Exp = resolveExp(isg, st->st_MyGroup,
524 st->st_IfStmt.es_Exp,
526 ResolveTypes(isg, st->st_IfStmt.es_TrueStmt);
527 if (st->st_IfStmt.es_FalseStmt)
528 ResolveTypes(isg, st->st_IfStmt.es_FalseStmt);
532 * NOTE: lvalue/rvalue depends on return type.
534 st->st_RetStmt.es_ProcRetType =
535 resolveReturnType(st->st_MyGroup);
536 if (st->st_RetStmt.es_Exp) {
537 st->st_RetStmt.es_Exp =
538 resolveExp(isg, st->st_MyGroup,
539 st->st_RetStmt.es_Exp,
540 st->st_RetStmt.es_ProcRetType, 1);
545 * NOTE: lvalue/rvalue depends on return type.
547 st->st_ResStmt.es_ProcRetType =
548 resolveReturnType(st->st_MyGroup);
549 if (st->st_ResStmt.es_Exp) {
550 st->st_ResStmt.es_Exp =
551 resolveExp(isg, st->st_MyGroup,
552 st->st_ResStmt.es_Exp,
553 st->st_ResStmt.es_ProcRetType, 1);
558 * NOTE: Switch type must be an rvalue.
560 * NOTE: It is possible to switch on a type. See ST_Case
561 * below for more detail.
563 st->st_SwStmt.es_Exp->ex_Flags |= EXF_REQ_TYPE;
564 st->st_SwStmt.es_Exp = resolveExp(isg, st->st_MyGroup,
565 st->st_SwStmt.es_Exp,
569 * Switch-on-expression() expects an rvalue.
571 if ((st->st_SwStmt.es_Exp->ex_Flags & EXF_RET_TYPE) == 0) {
572 st->st_SwStmt.es_Exp->ex_Type =
573 DEL_LVALUE(st->st_SwStmt.es_Exp->ex_Type);
578 scan = getHead(&st->st_List);
580 scan = getSucc(&st->st_List, &scan->st_Node)
582 ResolveTypes(isg, scan);
588 * Handle a case/default. Note that when switching on a type,
589 * each case expression must return a type.
591 * NOTE: Case type must be an rvalue. We use the switch type
592 * to cast, so it will be.
600 * Set type to cast cases to if we are switching on
601 * an expression, otherwise we are switching on a
602 * type and should not try to coerce the cases (it
603 * doesn't make sense to).
605 dassert_stmt(st, st->st_Parent->st_Op == ST_Switch);
606 if (st->st_Parent->st_SwStmt.es_Exp->ex_Flags & EXF_RET_TYPE)
609 type = st->st_Parent->st_SwStmt.es_Exp->ex_Type;
612 * case: (if es_Exp is NULL, this is a default: )
614 if ((exp = st->st_CaseStmt.es_Exp) != NULL) {
616 exp->ex_Flags |= EXF_REQ_TYPE;
617 exp = resolveExp(isg, st->st_MyGroup,
620 dassert(exp->ex_Flags & EXF_RET_TYPE);
621 st->st_CaseStmt.es_Exp = exp;
625 * Elements of the case/default
628 scan = getHead(&st->st_List);
630 scan = getSucc(&st->st_List, &scan->st_Node)
632 ResolveTypes(isg, scan);
638 * NOTE: VoidType global implies an rvalue.
640 * NOTE: If resolveExp() doesn't cast to void for
641 * us, we will do it here.
646 exp = resolveExp(isg, st->st_MyGroup,
647 st->st_ExpStmt.es_Exp,
649 if (exp->ex_Type != &VoidType) {
650 exp = resolveExpCast(isg, st->st_MyGroup,
653 st->st_ExpStmt.es_Exp = exp;
660 scan = getHead(&st->st_List);
662 scan = getSucc(&st->st_List, &scan->st_Node)
664 ResolveTypes(isg, scan);
676 * Locate the ST_Proc statement and resolve & return its return type
680 resolveReturnType(SemGroup *sg)
687 * Locate the ST_Proc statement
689 while (sg && (sg->sg_Stmt == NULL || sg->sg_Stmt->st_Op != ST_Proc))
693 d = st->st_ProcStmt.es_Decl; /* decl is already resolved */
694 dassert_decl(d, d->d_Op == DOP_PROC);
695 dassert_decl(d, d->d_Flags & (DF_RESOLVING|DF_RESOLVED));
696 type = d->d_ProcDecl.ed_Type;
697 dassert_decl(d, type->ty_Op == TY_PROC);
698 return(type->ty_ProcType.et_RetType);
702 resolveArgsType(SemGroup *sg)
709 * Locate the ST_Proc statement
711 while (sg && (sg->sg_Stmt == NULL || sg->sg_Stmt->st_Op != ST_Proc))
715 d = st->st_ProcStmt.es_Decl; /* decl is already resolved */
716 dassert_decl(d, d->d_Op == DOP_PROC);
717 dassert_decl(d, d->d_Flags & (DF_RESOLVING|DF_RESOLVED));
718 type = d->d_ProcDecl.ed_Type;
719 dassert_decl(d, type->ty_Op == TY_PROC);
720 return(type->ty_ProcType.et_ArgsType);
724 * resolveDecl() - resolve a declaration
726 * Note: we do not resolve d_Offset here.
728 * If the declaration represents a procedure argument, special
729 * processing of LVALUE scope is required to pass the declaration
730 * by reference instead of by value. Note that the size of the
731 * underlying type DOES NOT CHANGE... it may be much larger.
734 resolveDecl(Declaration *d)
740 if (d->d_Flags & DF_RESOLVED)
742 dassert_decl(d, (d->d_Flags & DF_RESOLVING) == 0);
743 d->d_Flags |= DF_RESOLVING;
747 if (d->d_ClassDecl.ed_Super) {
748 d->d_ClassDecl.ed_Super =
749 resolveType(d->d_ClassDecl.ed_Super);
751 sg = d->d_ClassDecl.ed_SemGroup;
752 if (resolveSemGroup1(sg))
753 resolveSemGroup2(sg);
754 d->d_Bytes = d->d_ClassDecl.ed_SemGroup->sg_Bytes;
755 d->d_AlignMask = d->d_ClassDecl.ed_SemGroup->sg_AlignMask;
759 * Alias access is a barrier and always returns an rvalue.
761 type = d->d_AliasDecl.ed_Type =
762 resolveType(d->d_AliasDecl.ed_Type);
763 if (d->d_AliasDecl.ed_AssExp) {
764 d->d_AliasDecl.ed_AssExp =
765 resolveExp(d->d_ImportSemGroup, d->d_MyGroup,
766 d->d_AliasDecl.ed_AssExp,
767 DEL_LVALUE(type), 1);
769 /* handled in DOT and STRIND resolver */
770 SetDupExp(NULL, d->d_AliasDecl.ed_AssExp);
773 d->d_Flags |= DF_RESOLVED;
774 type = resolveType(d->d_TypedefDecl.ed_Type);
775 d->d_Flags &= ~DF_RESOLVED;
776 d->d_TypedefDecl.ed_Type = type;
780 * This only occurs when resolving an import's semantic group.
781 * Since we are scanning statements in that context we do not
782 * have to recurse here, ResolveTypes() will do it for us.
787 * XXX global procedure, later on, make the argument a
788 * type instead of storage?
790 d->d_ProcDecl.ed_Type = resolveType(d->d_ProcDecl.ed_Type);
793 * Deal with constructor/destructor chaining. The chaining
794 * winds up being reversed and will be corrected by the caller.
796 if (d->d_ScopeFlags & SCOPE_GLOBAL) {
797 if (d->d_ScopeFlags & (SCOPE_CONSTRUCTOR |
799 d->d_GNext = d->d_MyGroup->sg_GBase;
800 d->d_MyGroup->sg_GBase = d;
803 if (d->d_ScopeFlags & SCOPE_CONSTRUCTOR) {
804 d->d_CNext = d->d_MyGroup->sg_CBase;
805 d->d_MyGroup->sg_CBase = d;
807 if (d->d_ScopeFlags & SCOPE_DESTRUCTOR) {
808 d->d_DNext = d->d_MyGroup->sg_DBase;
809 d->d_MyGroup->sg_DBase = d;
814 * If this procedure is bound to a DLL we have to resolve
817 if (d->d_ScopeFlags & SCOPE_CLANG) {
818 d->d_ProcDecl.ed_DLLFunc =
819 FindDLLSymbol(NULL, d->d_ImportSemGroup,
823 case DOP_ARGS_STORAGE:
824 case DOP_STACK_STORAGE:
825 case DOP_GLOBAL_STORAGE:
826 case DOP_GROUP_STORAGE:
827 type = resolveType(d->d_StorDecl.ed_Type);
828 d->d_StorDecl.ed_Type = type;
831 * Promote the lvalue storage qualifier (e.g. from a typedef)
832 * into the declaration's scope. This is what ultimately
833 * controls lvalue vs rvalue arguments to procedures and such.
835 if ((type->ty_SQFlags & SF_LVALUE) &&
836 (d->d_ScopeFlags & SCOPE_LVALUE) == 0
838 d->d_ScopeFlags |= SCOPE_LVALUE;
842 * Default assignment handling expects an rvalue.
844 if (d->d_StorDecl.ed_AssExp) {
845 d->d_StorDecl.ed_AssExp =
846 resolveExp(d->d_ImportSemGroup, d->d_MyGroup,
847 d->d_StorDecl.ed_AssExp,
848 DEL_LVALUE(type), 1);
850 if (d->d_ScopeFlags & SCOPE_LVALUE) {
852 * Object is passed as a LValueStor structure. Note
853 * that d_Bytes is going to be different then the
854 * underlying type (which represents the actual
857 d->d_Bytes = sizeof(LValueStor);
858 d->d_AlignMask = LVALUE_ALIGN;
861 * Object is passed by value.
863 d->d_AlignMask = type->ty_AlignMask;
864 d->d_Bytes = type->ty_Bytes;
868 * If the declaration represents or contains an
869 * argument-lvalue or a pointer we have to add it to
870 * the SemGroup's SRBase list to properly reference or
871 * dereference the elements. XXX only do this for non-global
874 * If the declaration has LVALUE scope we must do the same
875 * because the ref is tracked.
877 if (d->d_Op != DOP_GLOBAL_STORAGE &&
878 (type->ty_Flags & TF_HASLVPTR)) {
879 d->d_SRNext = d->d_MyGroup->sg_SRBase;
880 d->d_MyGroup->sg_SRBase = d;
881 } else if (d->d_ScopeFlags & SCOPE_LVALUE) {
882 d->d_SRNext = d->d_MyGroup->sg_SRBase;
883 d->d_MyGroup->sg_SRBase = d;
887 * Deal with constructor/destructor chaining. The chaining
888 * winds up being reversed and will be corrected by the
891 if (type->ty_Flags & TF_HASCONSTRUCT) {
892 d->d_CNext = d->d_MyGroup->sg_CBase;
893 d->d_MyGroup->sg_CBase = d;
895 if (type->ty_Flags & TF_HASDESTRUCT) {
896 d->d_DNext = d->d_MyGroup->sg_DBase;
897 d->d_MyGroup->sg_DBase = d;
899 if (type->ty_Flags & (TF_HASGCONSTRUCT|TF_HASGDESTRUCT)) {
900 d->d_GNext = d->d_MyGroup->sg_GBase;
901 d->d_MyGroup->sg_GBase = d;
907 d->d_Flags &= ~DF_RESOLVING;
908 d->d_Flags |= DF_RESOLVED;
911 * Post resolution flag resolving (to handle recursion)
916 * Create copies of procedures as they are needed (thus
917 * avoiding an XxY matrix effect).
919 if ((st = d->d_ProcDecl.ed_OrigBody) == NULL) {
920 Declaration *super = d->d_Super;
921 while (super && super->d_ProcDecl.ed_OrigBody == NULL) {
922 super = super->d_Super;
925 st = super->d_ProcDecl.ed_OrigBody;
926 if (super->d_MyGroup->sg_Stmt->st_Op == ST_Class) {
928 * Copy-down a procedure from a
929 * superclass. The procedure must
930 * still be linked into its superclass
931 * for semantic searches to work as
932 * expected, hence the use of super->
933 * d_MyGroup and st->st_Parent.
935 * Note that this code is not reached
936 * in the case of a nested procedure,
937 * since nested procedures are copied
940 st = DupStmt(super->d_MyGroup,
944 * Copy-down a nested procedure.
945 * The procedure must be linked
946 * into the copy of the parent
947 * prodedure, not the original
948 * parent procedure, or it will
951 st = DupStmt(d->d_Stmt->st_MyGroup,
956 * Internal procedure (we do not need to do
957 * anything), there is no statement body
963 * Procedure is being used in the primary class it
966 st = DupStmt(d->d_MyGroup, st->st_Parent, st);
970 * Link the procedure body to the declaration and
971 * resolve the procedure body.
973 dassert_stmt(st, d->d_ProcDecl.ed_ProcBody == NULL);
974 d->d_ProcDecl.ed_ProcBody = st;
975 st->st_ProcStmt.es_Decl = d;
976 st->st_ProcStmt.es_Scope = d->d_Scope;
977 ResolveTypes(d->d_ImportSemGroup, st);
985 * __align(%d) scope qualifier, override the type's alignment
987 if ((d->d_Scope.s_Flags & SCOPE_ALIGN) && d->d_Scope.s_AlignOverride)
988 d->d_AlignMask = d->d_Scope.s_AlignOverride - 1;
992 * resolveExp() - resolve expression
994 * Resolve an expression. We are expected to resolve all ex_Type's
995 * for the expression tree as well as expected to track down
996 * operators and base identifiers.
998 * itype is a type hint. If non-NULL, the caller would like our
999 * expression to return the specified type. There are a few special
1002 * EXF_REQ_ARRAY - when OBRACKET requests an arry optimization it
1003 * passes a post-array-indexed typehint (as if
1004 * you had done the optimization). You must ignore
1005 * itype if you are unable to do the optimization.
1007 * NOTE: Even rvalues may have refstor side-effects at run-time.
1010 resolveExp(SemGroup *isg, SemGroup *sg, Exp *exp, Type *itype, int autocast)
1014 loadExpCopy(©, exp);
1017 * note: certain cases below call other resolver functions and assume
1018 * that ex* variables are unchanged.
1021 dassert((exFlags & EXF_DUPEXP) || (exFlags & EXF_RESOLVED) == 0);
1026 * An assignment. Note that we optimize void returns
1027 * (such as when an assignment is a statement like 'a = 4;'
1028 * ... the result of the assignment is cast to void.
1030 * NOTE: Left-hand-side must be an LVALUE, return type
1031 * inherits this feature unless the parent turns off
1032 * the bit so the TOK_ASS run-time must deal with that.
1034 exLhs = resolveExp(isg, sg, exLhs, NULL, 0);
1035 dassert_exp(exLhs, exLhs->ex_Type->ty_SQFlags & SF_LVALUE);
1036 exRhs = resolveExp(isg, sg, exRhs,
1037 DEL_LVALUE(exLhs->ex_Type), 1);
1039 /* AssExp handles this optimization */
1040 if (itype == &VoidType) {
1042 exFlags |= EXF_RET_VOID;
1044 exType = exLhs->ex_Type;
1049 * Check @ref assignment compatibility.
1051 if (exLhs->ex_Type->ty_Op == TY_REFTO) {
1052 switch(MatchType(exLhs->ex_Type, exRhs->ex_Type)) {
1053 case SG_COMPAT_FULL:
1054 printf("assign %s compatibility FULL\n",
1057 case SG_COMPAT_PART:
1058 printf("assign %s compatibility PART\n",
1061 case SG_COMPAT_SUBCLASS:
1062 printf("assign %s compatibility SUBCL\n",
1065 case SG_COMPAT_FAIL:
1066 printf("assign %s compatibility FAIL\n",
1075 * NOTE: BoolType global implies an rvalue.
1077 exLhs = resolveExp(isg, sg, exLhs, &BoolType, 1);
1078 exRhs = resolveExp(isg, sg, exRhs, &BoolType, 1);
1083 * NOTE: BoolType global implies an rvalue.
1085 exLhs = resolveExp(isg, sg, exLhs, &BoolType, 1);
1086 exRhs = resolveExp(isg, sg, exRhs, &BoolType, 1);
1091 * This synthesized token occurs when we are able to collapse
1092 * a structural indirection or dotted element into a
1093 * declaration. For example, 'module.routine'.
1099 * Structual field access. The left hand side may be an object
1100 * (class or compound), a class type, or a compound type.
1102 * A dotted access requires an lvalue on the left hand side
1103 * if the left hand side represents storage.
1105 * The result will be an lvalue if the right hand side
1106 * represents storage. We only loop if the right hand side
1107 * is an alias replacement.
1118 int procedureOnly = 0;
1119 int eno = TOK_ERR_ID_NOT_FOUND;
1122 * NOTE: Hint must 'always happen' since we may be
1123 * modifying an expression that will later be
1126 * NOTE: Lhs is always an lvalue for TOK_DOT, but
1127 * does not have to be for TOK_STRIND.
1129 exLhs->ex_Flags |= EXF_REQ_TYPE;
1130 exLhs = resolveExp(isg, sg, exLhs, NULL, 0);
1133 * The RHS may have been turned into a TOK_SEMGRP_ID
1134 * in a previous duplicate. The change is considered
1137 if (exRhs->ex_Token != TOK_SEMGRP_ID) {
1139 exRhs->ex_Token == TOK_STRUCT_ID);
1140 exRhs = resolveExp(isg, sg, exRhs, NULL, 0);
1143 type = exLhs->ex_Type;
1146 * Calculate scope and SemGroup to search. Note
1147 * that it is legal to do a structural '.' selection
1148 * on a pointer, but it works differently then
1149 * indirecting through a pointer via '->'. In the
1150 * case of '.' on a pointer, we first search the
1151 * system Pointer class.
1153 if (exLhs->ex_Flags & EXF_RET_TYPE) {
1158 * Figure out the base type used to look-up the
1159 * identifier. An identifier that resolves into a
1160 * procedure winds up only being a hint for a
1163 if (exToken == TOK_STRIND) {
1164 switch(type->ty_Op) {
1166 type = type->ty_CPtrType.et_Type;
1169 type = type->ty_PtrType.et_Type;
1172 type = type->ty_RefType.et_Type;
1176 dassert_exp(exp, 0);
1182 switch(type->ty_Op) {
1184 sg2 = type->ty_ClassType.et_SemGroup;
1187 sg2 = type->ty_CompType.et_SemGroup;
1190 sg2 = type->ty_ArgsType.et_SemGroup;
1193 sg2 = type->ty_VarType.et_SemGroup;
1196 sg2 = type->ty_ImportType.et_SemGroup;
1200 dassert_exp(exp, PointerType.ty_Op == TY_CLASS);
1201 sg2 = PointerType.ty_ClassType.et_SemGroup;
1204 dassert_exp(exp, PointerType.ty_Op == TY_CLASS);
1205 sg2 = PointerType.ty_ClassType.et_SemGroup;
1209 dassert_exp(exp, PointerType.ty_Op == TY_CLASS);
1210 sg2 = PointerType.ty_ClassType.et_SemGroup;
1214 * Possibly a pointer, aka ptr.NULL
1218 visibility = exLhs->ex_Visibility;
1221 * Locate the identifier normally, via its type.
1222 * ty_TypeVisbility is the initial visibility (scope)
1223 * that the semantic search should use in locating
1227 string_t ary[2] = { id, NULL };
1230 if (exLhs->ex_Token == TOK_ID ||
1231 exLhs->ex_Token == TOK_DECL) {
1232 if (exLhs->ex_Decl->d_Search) {
1233 level = exLhs->ex_Decl->
1236 level = sg2->sg_Level;
1242 if (exLhs->ex_Flags & EXF_SUPER) {
1244 fprintf(stderr, "Can't super with reference type\n");
1245 dassert_exp(exp, 0);
1248 fprintf(stderr, "No superclass available\n");
1249 dassert_exp(exp, 0);
1254 level = sg2->sg_Level; /* may be -1 */
1256 visibility &= type->ty_Visibility;
1257 d = FindDeclPath(&exp->ex_LexRef, NULL,
1260 &visibility, level, &eno);
1262 * XXX more hack. If the super is visible
1263 * and a procedure we just found our own
1264 * refinement, not the superclass method.
1265 * This is because there is no 'superclass
1266 * method' per say, refinements *REPLACE*
1267 * superclass declarations and inherit the
1268 * superclass's level. However, we still
1269 * want to be able to chain method calls so
1270 * what we do instead is go through and find
1271 * the procedure that we smacked when we did
1272 * the refinement. This procedure has
1273 * already been conveniently brought into
1274 * the subclass context as an 'invisible'
1275 * entity at the same d_Level.
1277 if ((exLhs->ex_Flags & EXF_SUPER) &&
1279 d->d_Op == DOP_PROC &&
1280 (d->d_ScopeFlags & SCOPE_ALL_VISIBLE)
1282 string_t id2 = d->d_Id;
1283 SemGroup *olevel = d->d_Level;
1285 dassert_exp(exp, isRefTo == 0);
1287 while ((d = getSucc(&d->d_MyGroup->sg_DeclList, &d->d_Node)) != NULL) {
1288 if (d->d_Id == id2 &&
1289 d->d_Level == olevel &&
1290 d->d_Op == DOP_PROC) {
1299 if (d && procedureOnly && d->d_Op != DOP_PROC) {
1301 "PTR.ELEMENT may be used for special "
1302 "pointer method calls, but not to "
1303 "access storage elements. "
1304 "Use PTR->ELEMENT instead\n");
1305 dassert_exp(exp, 0);
1309 * If referencing actual storage the storage must be
1312 if (d && globalOnly && (d->d_Op & DOPF_STORAGE) &&
1313 (d->d_ScopeFlags & SCOPE_GLOBAL) == 0
1316 "%s is not global. Only globals "
1317 "can be accessed through a type\n",
1319 dassert_exp(exp, 0);
1324 * Identifier found. Note that if we are
1325 * going through a reference type the
1326 * declaration is not the actual one we
1327 * use at run time. It's just a template.
1331 exVisibility = visibility;
1335 exType = d->d_ProcDecl.ed_Type;
1336 if (d->d_ProcDecl.ed_Type->ty_SQFlags & SF_METHOD) {
1338 * Method call, do not
1339 * collapse the expression into
1340 * a direct declaration because
1341 * the object is needed later.
1343 if (exLhs->ex_Flags & EXF_RET_TYPE)
1344 ExpPrintError(exLhs, TOK_ERR_METHOD_REQUIRES_OBJ);
1345 dassert((exLhs->ex_Flags & EXF_RET_TYPE) == 0);
1346 } else if (isRefTo) {
1348 * Call via reference. The
1349 * lhs is required to evaluate
1350 * the actual method call at
1355 * Global method call or normal
1356 * call. For the global method
1357 * case the lhs is not needed
1358 * because the parser entered
1359 * the first argument as a
1362 * Degenerate into a TOK_DECL.
1363 * We depend on this later.
1365 exFlags &= ~EXF_BINARY;
1372 exType = DEL_LVALUE(d->d_AliasDecl.ed_Type);
1373 dassert_decl(d, d->d_AliasDecl.ed_AssExp != NULL);
1375 * NOTE: exLhs must be NULL if exp is
1376 * unresolved. exp tree duplications
1377 * do not duplicate the alias's exLHS
1378 * even though UNARY is set.
1380 dassert_exp(exp, exRhs->ex_Lhs == NULL);
1381 exRhs->ex_Flags |= EXF_ALIAS | EXF_UNARY;
1382 exRhs->ex_Lhs = DupExp(sg2,
1383 d->d_AliasDecl.ed_AssExp);
1384 exRhs->ex_Lhs = resolveExp(isg, sg2,
1388 case DOP_ARGS_STORAGE:
1389 case DOP_STACK_STORAGE:
1390 case DOP_GLOBAL_STORAGE:
1391 case DOP_GROUP_STORAGE:
1393 * Set type. The Rhs is a STRUCT_ID
1394 * and does not require a type to be
1397 * Return type is always an LVALUE,
1398 * parent may adjust.
1400 exType = ADD_LVALUE(d->d_StorDecl.ed_Type);
1404 * XXX make sure this is only used
1405 * in the lhs of a structural
1408 * XXX what if we went through a
1409 * TY_RETO type? This type will
1412 * collapse the exp node.
1414 exType = d->d_TypedefDecl.ed_Type;
1416 exFlags &= ~EXF_BINARY;
1420 * Do not collapse an import, we
1421 * require more resolution. e.g.
1422 * import.<blah> will be collapsed,
1423 * but 'import' cannot be.
1425 if (exFlags & EXF_REQ_TYPE) {
1428 &d->d_ImportDecl.ed_SemGroup->sg_ClassList,
1429 d->d_ImportDecl.ed_SemGroup,
1431 exFlags |= EXF_RET_TYPE;
1437 * Do not collapse a class, we require
1438 * more resolution. e.g. class.<blah>
1439 * will be collapsed, but 'class'
1442 if (exFlags & EXF_REQ_TYPE) {
1445 &d->d_ClassDecl.ed_SemGroup->sg_ClassList,
1446 d->d_ClassDecl.ed_Super,
1447 d->d_ClassDecl.ed_SemGroup,
1449 exFlags |= EXF_RET_TYPE;
1454 dassert_exp(exp, 0);
1457 } else if ((s = StrTableSpecial(id)) &
1458 SPECIALF_SEMGROUP) {
1460 * Identifier not found, check for a special
1463 exRhs->ex_Token = TOK_SEMGRP_ID;
1464 exRhs->ex_Int32 = s;
1469 dassert(type->ty_Op == TY_PTRTO ||
1470 type->ty_Op == TY_REFTO ||
1471 type->ty_Op == TY_CPTRTO);
1472 /* NULL is not an lvalue */
1473 exType = DEL_LVALUE(type);
1474 exFlags |= EXF_NULL;
1477 dassert(type->ty_Op != TY_PTRTO &&
1478 type->ty_Op != TY_REFTO &&
1479 type->ty_Op != TY_CPTRTO);
1480 exType = &Int32Type;
1484 * typeof(self.__data[]) vs
1485 * (cast)self.__data[]
1487 dassert(type->ty_Op != TY_PTRTO &&
1488 type->ty_Op != TY_REFTO &&
1489 type->ty_Op != TY_CPTRTO);
1490 dassert(exFlags & EXF_REQ_ARRAY);
1491 exFlags |= EXF_RET_ARRAY;
1492 if (exFlags & EXF_REQ_TYPE) {
1493 exFlags |= EXF_RET_TYPE;
1494 exType = &DynamicLValueType;
1499 * dynamic data must be cast
1501 dassert_exp(exp, 0);
1502 exType = &DynamicLValueType;
1505 case SPECIAL_VAR_COUNT:
1506 dassert(type->ty_Op != TY_PTRTO &&
1507 type->ty_Op != TY_REFTO &&
1508 type->ty_Op != TY_CPTRTO);
1509 exType = &Int32Type;
1511 case SPECIAL_VAR_DATA:
1513 * typeof(self.__vardata[]) vs
1514 * (cast)self.__vardata[]
1516 dassert(type->ty_Op != TY_PTRTO &&
1517 type->ty_Op != TY_REFTO &&
1518 type->ty_Op != TY_CPTRTO);
1519 dassert(exFlags & EXF_REQ_ARRAY);
1520 exFlags |= EXF_RET_ARRAY;
1521 if (exFlags & EXF_REQ_TYPE) {
1522 exFlags |= EXF_RET_TYPE;
1523 exType = &DynamicLValueType;
1528 * dynamic data must be cast
1530 dassert_exp(exp, 0);
1531 exType = &DynamicLValueType;
1534 case SPECIAL_TYPEID:
1535 exType = &Int32Type;
1537 case SPECIAL_TYPESTR:
1541 dassert_exp(exRhs, 0);
1546 * This is nasty, I admit. If we have a
1547 * pointer or reference type try again.
1550 if (type->ty_Op == TY_PTRTO) {
1551 type = type->ty_PtrType.et_Type;
1555 if (type->ty_Op == TY_REFTO) {
1556 type = type->ty_RefType.et_Type;
1560 if (type->ty_Op == TY_CPTRTO) {
1561 type = type->ty_CPtrType.et_Type;
1565 ExpPrintError(exRhs, eno);
1569 dassert_exp(exp, exType != NULL);
1573 * NOTE: unresolved identifiers should not have alias
1574 * expression sub-tree duplications attached to them.
1577 dassert_exp(exp, exLhs == NULL);
1581 * NOTE: LVALUE/RVALUE for elements and return type depends
1582 * on the operator. Operator functions normally
1583 * self-optimize the cases at run-time.
1585 saveExpCopy(©, exp);
1586 exp = resolveExpOper(isg, sg, exp, itype);
1587 loadExpCopy(©, exp);
1591 * Indirect through an expression.
1593 * Return type is typically an LVALUE (if representing
1594 * storage). Exp parent might turn it off so run-time
1595 * must test. Lhs may or may not be.
1600 exLhs = resolveExp(isg, sg, exLhs, NULL, 0);
1601 type = exLhs->ex_Type;
1603 switch(type->ty_Op) {
1605 if ((exFlags & EXF_INDREF) == 0) {
1606 fprintf(stderr, "You cannot use '*' on a reference type\n");
1607 dassert_exp(exLhs, 0);
1609 exType = ADD_LVALUE(type->ty_RefType.et_Type);
1612 exType = ADD_LVALUE(type->ty_PtrType.et_Type);
1615 exType = ADD_LVALUE(type->ty_CPtrType.et_Type);
1618 dassert_exp(exLhs, 0);
1625 * Take the address of an (LVALUE) expression. Returns an
1626 * RVALUE. Allow for a short-cut optimization which replaces
1627 * the TOK_ADDR sequence with its argument in the &ary[n]
1634 * note: hint must 'always happen' since we may be
1635 * modifying an expression that will later be Dup'd.
1637 exLhs->ex_Flags |= EXF_REQ_ADDROF;
1638 exLhs = resolveExp(isg, sg, exLhs, NULL, 0);
1639 if (exLhs->ex_Flags & EXF_RET_ADDROF) {
1641 loadExpCopy(©, exp);
1643 type = exLhs->ex_Type;
1645 type->ty_SQFlags & SF_LVALUE);
1646 exType = resolveType(TypeToPtrType(type));
1647 /* DEL_LVALUE() not needed here */
1653 * Array index, takes an RVALUE, returns an LVALUE.
1655 * Note: we have to convert the special __data[exp] case.
1657 * Note: ex_Flags hints must 'always happen' since we may be
1658 * modifying an expression that will later be Dup'd.
1660 exRhs = resolveExp(isg, sg, exRhs, NULL, 0);
1661 exLhs->ex_Flags |= EXF_REQ_ARRAY | (exFlags & EXF_REQ_TYPE);
1662 exLhs->ex_AuxExp = exRhs;
1663 exLhs = resolveExp(isg, sg, exLhs, itype, 0);
1665 if (MatchType(&IntegralType, exRhs->ex_Type) <= SG_COMPAT_PART) {
1666 ExpPrintError(exRhs, TOK_ERR_EXPECTED_INTEGRAL_TYPE);
1667 dassert_exp(exp, 0);
1670 if (exLhs->ex_Flags & EXF_RET_ARRAY) {
1672 * __data and __vardata specials
1674 exp->ex_Token = TOK_ERR_EXP_REMOVED;
1676 } else if (exFlags & EXF_REQ_ADDROF) {
1678 * &ary[i] optimization - allows us to create
1679 * a bounded pointer (returns an RVALUE).
1683 exFlags |= EXF_RET_ADDROF;
1685 dassert((exLhs->ex_Flags & EXF_RET_TYPE) == 0);
1687 exLhs->ex_AuxExp = NULL;
1688 type = exLhs->ex_Type;
1689 switch(type->ty_Op) {
1691 type = type->ty_AryType.et_Type;
1694 type = type->ty_CPtrType.et_Type;
1697 type = type->ty_PtrType.et_Type;
1700 /* Cannot take address of a reference type */
1701 dassert_exp(exp, 0);
1704 exType = resolveType(TypeToPtrType(type));
1705 /* returns an RVALUE */
1708 * Unoptimized array lookup, returns an lvalue
1712 dassert((exLhs->ex_Flags & EXF_RET_TYPE) == 0);
1714 exLhs->ex_AuxExp = NULL;
1715 type = exLhs->ex_Type;
1716 switch(type->ty_Op) {
1718 type = type->ty_AryType.et_Type;
1721 type = type->ty_CPtrType.et_Type;
1724 type = type->ty_PtrType.et_Type;
1728 "Cannot index a reference type\n");
1729 dassert_exp(exp, 0);
1732 exType = ADD_LVALUE(type);
1733 /* returns an LVALUE */
1737 dassert_exp(exp, 0); /* XXX */
1741 * XXX we should return a bounded pointer here.
1744 exId = StrTableEscapeQuotedString(exId, strlen(exId), 1);
1745 ReplaceStrTable(&exp->ex_Id, exId);
1749 exId = StrTableEscapeQuotedString(exId, strlen(exId), 0);
1750 dassert(StrTableLen(exId) == 1);
1751 ReplaceStrTable(&exp->ex_Id, exId);
1754 /* reserved for inline execution or something else */
1755 dassert_exp(exp, 0); /* XXX */
1761 strtol(exp->ex_Id, &ptr, 0);
1769 exFlags |= EXF_UNSIGNED;
1772 exType = (doUnsigned) ? &UInt8Type :
1774 } else if (*ptr == 'W') {
1775 exType = (doUnsigned) ? &UInt16Type :
1777 } else if (*ptr == 'L') {
1778 exType = (doUnsigned) ? &UInt64Type :
1780 } else if (*ptr == 0) {
1781 exType = (doUnsigned) ? &UInt32Type :
1784 dassert_exp(exp, 0);
1787 exType = &Int32Type;
1795 strtod(exp->ex_Id, &ptr);
1799 exType = &Float32Type;
1800 } else if (*ptr == 'D') {
1801 exType = &Float64Type;
1802 } else if (*ptr == 'X') {
1803 exType = &Float128Type;
1805 dassert_exp(exp, 0);
1808 exType = &Float64Type;
1817 * The self identifier represents the current procedure's
1818 * arguments. A varargs procedure will actually be called
1819 * with an extended version of this type, but for resolution
1820 * purposes we can use this time.
1822 * This is an LVALUE to support things like self.new() XXX.
1824 exType = ADD_LVALUE(resolveArgsType(sg));
1828 * The '$' identifier represents the current procedure's
1831 exType = ADD_LVALUE(resolveReturnType(sg));
1836 * Lookup the identifier. The returned declaration could
1837 * represent a class, typedef, module, or storage, but for
1838 * this case we only allow storage or a constant. Since
1839 * we are starting from our own semantic group, visibility
1840 * is initially ALL (private, library, and public).
1842 * The identifier might represent something at a higher scoping
1843 * layer. For example, a nested procedure accessing a variable
1844 * in the parent procedure or a method procedure in a class
1845 * accessing an element of the object.
1847 * This returns an LVALUE if the id represents storage.
1851 int eno = TOK_ERR_ID_NOT_FOUND;
1856 * Special case 'super'. XXX TY_REFTO
1858 * Make an in-place change to the expression
1859 * structure. 'super' is actually 'this' with the
1860 * EXF_SUPER flag set.
1862 if (exId == String_Super) {
1864 ReplaceStrTable(&exp->ex_Id, exId);
1865 exFlags |= EXF_SUPER;
1867 ary[0] = exp->ex_Id;
1870 exDecl = FindDeclPath(&exp->ex_LexRef, isg, sg,
1872 FDC_NULL, &exVisibility,
1874 if (exDecl == NULL) {
1875 ExpPrintError(exp, eno);
1876 dassert_exp(exp, 0);
1879 switch(exDecl->d_Op) {
1880 case DOP_ARGS_STORAGE:
1881 case DOP_STACK_STORAGE:
1882 case DOP_GLOBAL_STORAGE:
1883 case DOP_GROUP_STORAGE:
1885 * Storage identifiers are lvalues.
1887 exType = ADD_LVALUE(exDecl->d_StorDecl.ed_Type);
1891 * Aliases are rvalues (even if they could be lvalues).
1893 exType = DEL_LVALUE(exDecl->d_AliasDecl.ed_Type);
1894 exFlags |= EXF_ALIAS | EXF_UNARY;
1897 * NOTE: exLhs must be NULL if exp is unresolved.
1898 * exp tree duplications do not duplicate
1899 * the alias's exLHS even though UNARY is set.
1901 dassert_exp(exp, exLhs == NULL);
1902 exLhs = DupExp(sg, exDecl->d_AliasDecl.ed_AssExp);
1903 exLhs = resolveExp(isg, sg, exLhs, exType, 1);
1906 * Inherit EXF_NULL (NULL pointer special) through
1907 * the alias, otherwise it will not be assignable
1908 * to arbitrary pointers.
1910 exFlags |= exLhs->ex_Flags & EXF_NULL;
1915 * A procedural identifier.
1917 * Note: procedural pointers cannot be changed so
1918 * they are not lvalues.
1920 dassert_exp(exp, (exFlags & EXF_REQ_PROC));
1921 exType = exDecl->d_ProcDecl.ed_Type;
1924 if (exFlags & EXF_REQ_TYPE) {
1925 exType = exDecl->d_TypedefDecl.ed_Type;
1926 exFlags |= EXF_RET_TYPE;
1929 dassert_exp(exp, 0);
1932 if (exFlags & EXF_REQ_TYPE) {
1935 &exDecl->d_ClassDecl.ed_SemGroup->sg_ClassList,
1936 exDecl->d_ClassDecl.ed_Super,
1937 exDecl->d_ClassDecl.ed_SemGroup,
1939 exFlags |= EXF_RET_TYPE;
1942 dassert_exp(exp, 0);
1945 if (exFlags & EXF_REQ_TYPE) {
1948 &exDecl->d_ImportDecl.ed_SemGroup->sg_ClassList,
1949 exDecl->d_ImportDecl.ed_SemGroup,
1951 exFlags |= EXF_RET_TYPE;
1954 dassert_exp(exp, 0);
1957 dassert_exp(exp, 0);
1962 * NOTE: BoolType global implies an rvalue.
1964 exLhs = resolveExp(isg, sg, exLhs, &BoolType, 1);
1967 if (exFlags & EXF_REQ_TYPE) {
1968 exType = resolveType(exType);
1969 exFlags |= EXF_RET_TYPE;
1971 dassert_exp(exp, 0);
1976 * User cast (or maybe the parser inserted it). Try to
1977 * resolve the expression with the requested type hint
1978 * but tell resolveExp() not to force the cast.
1980 * Then check the result. If resolveExp() was not able to
1981 * optimize the requested cast then resolve the cast.
1983 * If the types are compatible we still keep the TOK_CAST
1984 * node in place for the moment. XXX we really need to
1985 * formalized how ex_Type is set Similar vs Exact.
1987 * NOTE: Cast results are always an RVALUE. XXX validate here.
1989 if ((exFlags & EXF_PARSE_TYPE) == 0) {
1990 exRhs->ex_Flags |= EXF_REQ_TYPE;
1991 exRhs = resolveExp(isg, sg, exRhs, NULL, 0);
1992 exType = exRhs->ex_Type;
1994 exLhs = resolveExp(isg, sg, exLhs, exType, 0);
1995 if (SimilarType(exType, exLhs->ex_Type) == 0) {
1996 saveExpCopy(©, exp);
1997 exp = resolveExpCast(isg, sg, exLhs, exType);
1998 loadExpCopy(©, exp);
2001 /* propagate NULL flag to allow cast to any pointer type */
2002 if (exLhs->ex_Flags & EXF_NULL)
2003 printf("LHS NULL\n");
2004 exp->ex_Flags |= exLhs->ex_Flags & EXF_NULL;
2009 * Calls require the RHS to be a compound expression
2010 * representing the procedure arguments.
2012 * XXX deal with pointer-to-function verses function
2013 * XXX the lhs must at the moment resolve to the procedure
2016 * In regards to procedure pointers, the declaration
2017 * will require a pointer to the procedure's statement
2018 * body. XXX this pointer can be the physical storage
2019 * associated with the lhs data but thus requires the
2020 * type to be a pointer. We do not support the 'C'
2021 * (*ptr_to_func)(...) form. You have to use ptr_to_func(...).
2026 dassert_exp(exRhs, exRhs->ex_Token == TOK_COMPOUND);
2029 * Note: ex_Flags hints must 'always happen' since
2030 * we may be modifying an expression that will later
2033 exLhs->ex_Flags |= EXF_REQ_PROC;
2034 exLhs = resolveExp(isg, sg, exLhs, NULL, 0);
2035 ltype = exLhs->ex_Type;
2037 if (ltype->ty_Op == TY_PTRTO)
2038 ltype = type->ty_PtrType.et_Type; /* XXX */
2041 dassert_exp(exLhs, exLhs->ex_Token == TOK_DECL ||
2042 exLhs->ex_Token == TOK_ID);
2044 dassert_exp(exLhs, ltype != NULL &&
2045 ltype->ty_Op == TY_PROC);
2046 dassert_exp(exLhs, exLhs->ex_Decl != NULL);
2047 dassert_exp(exRhs, exRhs->ex_Token == TOK_COMPOUND);
2050 * If the lhs type indicates a method procedure, then
2051 * it's lhs is the object we wish to pass as the
2052 * first argument to the method. We move the lhs lhs
2053 * exp. For a STRIND TY_PTRTO method call we
2054 * indirect the element and convert it to a TOK_DOT
2055 * lvalue argument of the underlying object.
2057 * A method call via a reference object is a very
2060 * Since the method called through an object winds up
2061 * being a method taylored for that object, and we
2062 * are calling through a reference to an object,
2063 * the actual method will be looked up at run time
2064 * and will match the object. Thus we can safely
2065 * indirect through the reference object for this
2066 * one case. Since (*ref_obj) is not normally
2067 * allowed this will be special-cased at
2070 * Note that this occurs before we evaluate the
2071 * compound expression on the right hand side. Also
2072 * note that since the resolver can be called multiple
2073 * times on a shared expression, we have to be
2074 * careful to shift the arguments around only once.
2076 if ((ltype->ty_SQFlags & SF_METHOD) &&
2077 (exRhs->ex_Flags & EXF_CALL_CONV) == 0
2081 exRhs->ex_Flags |= EXF_CALL_CONV;
2083 switch(exLhs->ex_Token) {
2084 case TOK_STRIND: /* indirect */
2085 obj = exLhs->ex_Lhs;
2086 if (obj->ex_Type->ty_Op == TY_PTRTO) {
2087 Exp *nexp = AllocExp(NULL);
2090 nexp->ex_Token = TOK_PTRIND;
2091 nexp->ex_Type = ADD_LVALUE(obj->ex_Type->ty_PtrType.et_Type);
2092 nexp->ex_Flags |= EXF_RESOLVED |
2094 LexDupRef(&obj->ex_LexRef,
2096 exLhs->ex_Token = TOK_DOT;
2098 } else if (obj->ex_Type->ty_Op ==
2100 Exp *nexp = AllocExp(NULL);
2103 nexp->ex_Token = TOK_PTRIND;
2104 nexp->ex_Type = ADD_LVALUE(obj->ex_Type->ty_CPtrType.et_Type);
2105 nexp->ex_Flags |= EXF_RESOLVED |
2107 LexDupRef(&obj->ex_LexRef,
2109 exLhs->ex_Token = TOK_DOT;
2111 } else if (obj->ex_Type->ty_Op ==
2113 Exp *nexp = AllocExp(NULL);
2116 nexp->ex_Token = TOK_PTRIND;
2117 nexp->ex_Type = ADD_LVALUE(obj->ex_Type->ty_RefType.et_Type);
2118 nexp->ex_Flags |= EXF_RESOLVED |
2121 LexDupRef(&obj->ex_LexRef,
2125 dassert_exp(obj, 0);
2128 case TOK_DOT: /* pass directly as lvalue */
2129 obj = exLhs->ex_Lhs;
2132 dassert_exp(exp, 0);
2138 * Leave the lhs intact, but set the
2139 * duplication flag in case things get
2142 exLhs->ex_Lhs = SetDupExp(sg, exLhs->ex_Lhs);
2143 obj->ex_Next = exRhs->ex_Lhs;
2144 exRhs->ex_Lhs = obj;
2148 * Resolve the right hand side, which are the
2149 * procedure arguments as a compound type. This
2150 * can get tricky. XXX
2152 * NOTE: We inherit the SF_LVALUE flag from the
2153 * return type. Parent might turn it off.
2155 /*d = exLhs->ex_Decl;*/
2156 exRhs = resolveExp(isg, sg, exRhs,
2157 ltype->ty_ProcType.et_ArgsType, 1);
2158 exType = ltype->ty_ProcType.et_RetType;
2163 * (NOTE EARLY RETURN)
2165 * A compound expression should always be an RVALUE, but
2166 * might contain LVALUEs (XXX).
2168 exp = resolveCompoundExp(isg, sg, exp, itype);
2173 * The caller must be able to handle a type return when
2176 dassert_exp(exp, exFlags & EXF_REQ_TYPE);
2181 * If an expression was supplied, convert it to a type.
2183 * NOTE: ex_Flags hints must 'always happen' since we may be
2184 * modifying an expression that will later be Dup'd.
2186 if ((exFlags & EXF_RET_TYPE) == 0) {
2187 dassert(exLhs != NULL);
2188 exLhs->ex_Flags |= EXF_REQ_TYPE;
2189 exLhs = resolveExp(isg, sg, exLhs, NULL, 0);
2190 exType = exLhs->ex_Type;
2191 exFlags &= ~EXF_UNARY;
2192 exFlags |= EXF_RET_TYPE;
2193 /* XXX delete the lhs */
2195 exType = resolveType(exType);
2199 exId = StrTableInt(exType->ty_Bytes);
2200 exp->ex_Token = exToken = TOK_INTEGER;
2202 exFlags &= ~EXF_RET_TYPE;
2205 dassert_exp(exp, exType->ty_Op == TY_ARYOF);
2206 if (exType->ty_AryType.et_Type->ty_Bytes) {
2207 exId = StrTableInt(exType->ty_Bytes /
2208 exType->ty_AryType.et_Type->ty_Bytes);
2210 exId = StrTableInt(0);
2212 exp->ex_Token = exToken = TOK_INTEGER;
2214 exFlags &= ~EXF_RET_TYPE;
2217 /* type is returned */
2222 dassert_exp(exp, 0);
2230 exType = resolveType(exType);
2231 /* XXX exType was ex_Type */
2234 * If we can autocast and itype is compound and the
2235 * expression turns out to not be compound, then the Rune
2236 * language converts the expression to compound. This way
2237 * (int x, int y = 2) = ( 7 ); works because ( 7 ) is
2238 * parsed as a standard expression and thus not compound.
2240 * (another way to do it would be to require that the element
2241 * be named, i.e. (x:7), which is compound after standard
2244 if (autocast && itype &&
2245 itype->ty_Op == TY_COMPOUND &&
2246 exType->ty_Op != TY_COMPOUND) {
2247 saveExpCopy(©, exp);
2248 exp = ExpToCompoundExp(exp, TOK_COMPOUND);
2249 exp = resolveCompoundExp(isg, sg, exp, itype);
2250 loadExpCopy(©, exp);
2254 * If the type hint did not succeed we may have to cast the
2255 * expression to the requested type. Note that if the itype
2256 * was set as part of an array optimization request which could
2257 * not be handled, we must ignore itype.
2259 * Note that SimilarType() will allow exp->ex_Type to be a
2260 * var-args TY_ARGS, and since the original Rhs of a call
2261 * is set to the procedure arguments type, VarType.et_Type
2262 * should match exactly.
2265 (exFlags & (EXF_REQ_ARRAY|EXF_RET_ARRAY)) != EXF_REQ_ARRAY
2267 if ((itype->ty_Flags & TF_RESOLVED) == 0)
2268 itype = resolveType(itype);
2269 if ((itype->ty_SQFlags & SF_LVALUE) &&
2270 (exType->ty_SQFlags & SF_LVALUE) == 0
2273 fprintf(stderr, "Exp must be an lvalue here\n");
2274 dassert_exp(exp, 0);
2276 if (!SimilarType(itype, exType) && autocast) {
2277 if (exp->ex_Flags & EXF_DUPEXP) {
2278 Exp *nexp = AllocExp(NULL);
2281 LexDupRef(&exp->ex_LexRef,
2284 exFlags &= ~EXF_DUPEXP;
2285 /*exp = DupExp(sg, exp);*/
2287 exFlags |= EXF_RESOLVED;
2288 exp = dupExpCopy(©, exp);
2289 exp = resolveExpCast(isg, sg, exp, itype);
2290 loadExpCopy(©, exp);
2294 exFlags |= EXF_RESOLVED;
2295 exp = dupExpCopy(©, exp);
2300 resolveConstExp(SemGroup *isg, SemGroup *sg, Exp *exp)
2304 exp = resolveExp(isg, sg, exp, NULL, 0);
2306 if (exp->ex_Token != TOK_ID)
2309 if ((d->d_StorDecl.ed_Type->ty_SQFlags & SF_CONST) == 0)
2313 case DOP_ARGS_STORAGE:
2314 case DOP_STACK_STORAGE:
2315 case DOP_GLOBAL_STORAGE:
2316 case DOP_GROUP_STORAGE:
2317 exp = d->d_StorDecl.ed_AssExp;
2323 if (exp->ex_Token != TOK_INTEGER) {
2324 ExpPrintError(exp, TOK_ERR_EXPECTED_INTEGRER_CONST);
2325 dassert_exp(exp, 0);
2331 * resolveCompoundExp() - resolve a compound expression (called from
2332 * resolveExp() and resolveExpOper()).
2334 * Resolve a compound expression. Compound expressions require
2335 * a compound type to normalize against. This will work for
2336 * direct assignments, return values, casts, and procedure arguments
2339 * NOTE: We can't use itype if EXF_REQ_ARRAY is specified because
2340 * its hinting for the array optimization case, which we cannot do.
2342 * Compound expressions may be used in conjuction with types
2343 * reprsenting classes, compound types, and procedure arguments. The
2344 * compound expression may contain subclasses of the superclasses expected
2345 * by itype. This is only allowed if the procedure's body has not yet been
2346 * generated (for example, a method call in a subclass).
2348 * Partially resolved operators are typically converted into procedure calls
2349 * and method calls are also partially resolved, so some elements may already
2352 * XXX named initialization, missing elements (structural
2353 * initialization), and so forth needs to be dealt with.
2356 resolveCompoundExp(SemGroup *isg, SemGroup *sg, Exp *exp, Type *itype)
2366 * Expression dup()ing
2368 if (exp->ex_Flags & EXF_DUPEXP) {
2370 static int count; fprintf(stderr, "DUPEXPC %d\n", ++count);
2372 exp = DupExp(sg, exp);
2375 if (itype && (exp->ex_Flags & EXF_REQ_ARRAY) == 0)
2376 exp->ex_Type = itype;
2379 * If we don't have a SemGroup to normalize against, XXX how should
2380 * we normalize the compound expression?
2382 if (exp->ex_Type == NULL) {
2383 dassert_exp(exp, 0);
2387 * Normalize the compound expression based on the
2388 * argument types expected by the procedure. We have
2389 * to resolve the type before we start the scan in order
2390 * to ensure that d_Offset is properly assigned.
2392 * Use the declarations found in the compound type
2393 * semantic group to coerce the procedure arguments to
2394 * generate the correct compound type. Note that resolveExp()
2395 * recursion must still use the SemGroup that was passed to us.
2397 * XXX deal with defaults and pre-resolved arguments. XXX
2399 type = exp->ex_Type = resolveType(exp->ex_Type);
2401 switch(type->ty_Op) {
2403 sg2 = type->ty_ArgsType.et_SemGroup;
2406 sg2 = type->ty_VarType.et_SemGroup;
2409 sg2 = type->ty_CompType.et_SemGroup;
2412 sg2 = type->ty_ClassType.et_SemGroup;
2415 dassert_exp(exp, 0);
2416 sg2 = NULL; /* NOT REACHED */
2419 pscan = &exp->ex_Lhs;
2422 * Scan the compound expression and match it up against the compound
2425 d = getHead(&sg2->sg_DeclList);
2426 while ((scan = *pscan) != NULL) {
2427 if (scan->ex_ArgId != NULL) {
2429 * Named argument, find it
2431 * (Overloading not allowed)
2433 int eno = TOK_ERR_ID_NOT_FOUND;
2434 d = FindDeclId(sg2, scan->ex_ArgId, &eno);
2436 ExpPrintError(scan, eno);
2441 * Unnamed argument, run through sequentially. Skip
2442 * any non-storage or global storage.
2444 while (d && d->d_Op != DOP_ARGS_STORAGE &&
2445 d->d_Op != DOP_STACK_STORAGE &&
2446 d->d_Op != DOP_GROUP_STORAGE
2448 d = getSucc(&sg2->sg_DeclList, &d->d_Node);
2452 * Ran out of storage declarations. If this is a
2453 * var-args SemGroup then we actually create a new
2454 * SemGroup (and eventually a new type) to represent
2457 * We then extend the varargs SemGroup. This isn't
2462 (sg2->sg_Flags & SGF_VARARGS)) {
2463 sg2 = DupSemGroup(sg2->sg_Parent, NULL, sg2, 1);
2465 if (resolveSemGroup1(sg3))
2466 resolveSemGroup2(sg3);
2473 "Too many arguments in "
2475 dassert_exp(scan, 0);
2481 * Unlink the expression from the compound list temporarily
2482 * so we can safely resolve it. Either cast the expression
2483 * to the compound element, or create a compound element
2484 * (e.g. varargs call) to match the expression.
2486 * Due to the resolver moving things around, the elements of
2487 * a compound expression are sometimes resolved multiple times.
2489 *pscan = scan->ex_Next;
2490 scan->ex_Next = NULL;
2492 Type *stype = d->d_StorDecl.ed_Type;
2498 if (SimilarType(stype, &PointerType) &&
2499 (stype->ty_SQFlags & SF_LVALUE) == SF_LVALUE
2506 if ((scan->ex_Flags & EXF_RESOLVED) == 0) {
2507 scan = resolveExp(isg, sg, scan,
2511 * Since we have already resolved the
2512 * expression we need to do the same sanity
2513 * checking that it would do to cast.
2516 (stype->ty_SQFlags & SF_LVALUE) == 0 ||
2517 (scan->ex_Type->ty_SQFlags & SF_LVALUE));
2518 if (!SimilarType(stype, scan->ex_Type)) {
2519 scan = resolveExpCast(isg, sg, scan,
2524 Scope tscope = INIT_SCOPE(0);
2526 if ((scan->ex_Flags & EXF_RESOLVED) == 0)
2527 scan = resolveExp(isg, sg, scan, NULL, 0);
2528 dassert(varargs != 0);
2529 d = AllocDeclaration(sg2, DOP_ARGS_STORAGE, &tscope);
2530 d->d_StorDecl.ed_Type = DEL_LVALUE(scan->ex_Type);
2532 d->d_Bytes = scan->ex_Type->ty_Bytes;
2533 d->d_AlignMask = scan->ex_Type->ty_AlignMask;
2536 * __align(%d) scope qualifier, override the type's
2539 if ((d->d_Scope.s_Flags & SCOPE_ALIGN) &&
2540 d->d_Scope.s_AlignOverride) {
2541 d->d_AlignMask = d->d_Scope.s_AlignOverride - 1;
2545 sg2->sg_Bytes = (sg2->sg_Bytes + d->d_AlignMask) &
2548 d->d_Offset = sg2->sg_Bytes;
2550 sg2->sg_Bytes += d->d_Bytes;
2551 if (sg2->sg_AlignMask < d->d_AlignMask)
2552 sg2->sg_AlignMask = d->d_AlignMask;
2555 scan->ex_Next = *pscan;
2559 * If the declaration requires an LVALUE, assert that
2560 * we have an lvalue. Otherwise set the direct-store
2561 * request (also see InterpCompoundExp).
2563 if (d->d_ScopeFlags & SCOPE_LVALUE) {
2564 if ((scan->ex_Type->ty_SQFlags & SF_LVALUE) == 0)
2565 fprintf(stderr, "argument must be an lvalue\n");
2567 scan->ex_Type->ty_SQFlags & SF_LVALUE);
2573 d = getSucc(&sg2->sg_DeclList, &d->d_Node);
2574 pscan = &scan->ex_Next;
2578 * Resolve the varargs sg2 after building it.
2581 if (resolveSemGroup1(sg2))
2582 resolveSemGroup2(sg2);
2583 resolveStorageSemGroup(sg2, 0, 0);
2587 * If we made a var-args call, adjust the expression's type
2590 dassert(type->ty_Op == TY_ARGS);
2591 exp->ex_Type = resolveType(TypeToVarType(type, sg2));
2593 exp->ex_Flags |= EXF_RESOLVED;
2598 * resolveExpCast() - Cast the expression to the specified type and return
2599 * the cast expression.
2601 * Note that expression nodes depend on their ex_Type being correct,
2602 * and also expressions may be shared, so be careful not to modify the
2603 * ex_Type (or anything else) in the existing expression.
2605 * This code is somewhat different then resolveExpOper() and friends.
2606 * The Exp argument has already been resolved so do not resolve it
2607 * again, and the cast type already has SF_LVALUE set or cleared as
2608 * appropriate (had better be cleared!)
2610 * As with operators we have to locate the cast declaration matching
2611 * the cast we want to do.
2614 resolveExpCast(SemGroup *isg, SemGroup *sg, Exp *exp, Type *ltype)
2619 rtype = exp->ex_Type;
2620 dassert(rtype && ltype);
2622 * XXX attempt to cast from subclass to superclass?
2626 * XXX look in our local semantic hierarchy for a compatible cast ?
2630 * Look in the right hand (source) type for the cast
2632 d = findCast(rtype, ltype, rtype);
2635 * If that fails then look in the left hand (destination) type for
2639 d = findCast(ltype, ltype, rtype);
2642 if (d == NULL && (rtype->ty_Op == TY_PTRTO ||
2643 rtype->ty_Op == TY_REFTO ||
2644 rtype->ty_Op == TY_CPTRTO)) {
2645 d = findCast(&PointerType, ltype, rtype);
2651 * We could not find a specific cast operator. There are
2652 * some inherent casts that we can do. We run through these
2653 * in attempt to come up with matching types.
2655 if (ltype->ty_Op != rtype->ty_Op &&
2656 (ltype->ty_Op == TY_PTRTO || ltype->ty_Op == TY_CPTRTO ||
2657 ltype->ty_Op == TY_ARYOF) &&
2658 (rtype->ty_Op == TY_PTRTO || rtype->ty_Op == TY_CPTRTO ||
2659 rtype->ty_Op == TY_ARYOF)) {
2661 * Pointers, C pointers, or arrays can be cast to
2662 * pointers, C pointers, or arrays of the same type.
2664 * Cast the right hand type to an equivalent
2665 * pointer/cpointer/array of the right hand type
2666 * and re-resolve the cast.
2668 exp = ExpToCastExp(exp,
2669 resolveType(ChangeType(rtype, ltype->ty_Op)));
2670 return(resolveExpCast(isg, sg, exp, ltype));
2671 } else if (MatchType(ltype, rtype) <= SG_COMPAT_PART) {
2673 * If the types are compatible (casting rtype->ltype),
2674 * we can cast trivially.
2676 exp = ExpToCastExp(exp, ltype);
2677 } else if (MatchType(&NumericType, ltype) <= SG_COMPAT_PART &&
2678 MatchType(&NumericType, rtype) <= SG_COMPAT_PART) {
2680 * Casting from one numeric type to another must be
2681 * supported by the interpreter/compiler.
2683 exp = ExpToCastExp(exp, ltype);
2684 } else if (SimilarType(&VoidType, ltype)) {
2686 * Casting anything to void is allowed (throwing the
2687 * object away). E.g. statement-expressions.
2689 exp = ExpToCastExp(exp, ltype);
2690 } else if (SimilarType(&VoidPtrType, ltype)) {
2692 * Casting a pointer to a (void *) is trivial, but is
2693 * only allowed if the underlying structure does not
2694 * contain any pointers.
2696 * NOTE: Generally only used when a pointer is being
2697 * cast to an integer. Rune does not allow
2698 * casting back to other pointer types.
2700 * XXX validate integral # of objects fit in pointer
2703 dassert_exp(exp, (rtype->ty_PtrType.et_Type->ty_Flags & TF_HASLVPTR) == 0);
2704 exp = ExpToCastExp(exp, ltype);
2705 } else if (SimilarType(&VoidRefType, ltype)) {
2707 * Casting a pointer to a (void @) is trivial.
2709 * NOTE: Generally only used when a pointer is being
2710 * cast to an integer. Rune does not allow
2711 * casting back to other pointer types.
2713 * XXX validate integral # of objects fit in pointer
2716 dassert_exp(exp, (rtype->ty_RefType.et_Type->ty_Flags & TF_HASLVPTR) == 0);
2717 exp = ExpToCastExp(exp, ltype);
2718 } else if (SimilarType(rtype, &VoidPtrType)) {
2720 * Casting from a void pointer may not be trivial
2721 * but we leave it up to the interpreter/compiler.
2723 * Only allow if the target does not contain any
2724 * pointers or if the right-hand-side is NULL.
2726 * XXX validate integral # of objects fit in pointer
2729 switch(ltype->ty_Op) {
2731 if ((exp->ex_Flags & EXF_NULL) == 0)
2732 dassert_exp(exp, (ltype->ty_RefType.et_Type->ty_Flags & TF_HASLVPTR) == 0);
2735 if ((exp->ex_Flags & EXF_NULL) == 0)
2736 dassert_exp(exp, (ltype->ty_PtrType.et_Type->ty_Flags & TF_HASLVPTR) == 0);
2743 exp = ExpToCastExp(exp, ltype);
2744 } else if (ltype->ty_Op == rtype->ty_Op &&
2745 (ltype->ty_Op == TY_PTRTO ||
2746 ltype->ty_Op == TY_CPTRTO ||
2747 ltype->ty_Op == TY_ARYOF)) {
2749 * We allow casts of pointers to similar numeric
2750 * types if they are the same size, though this is
2751 * really rather a hack. This is mainly to handle
2752 * the signed<->unsigned cast case. XXX
2756 switch(ltype->ty_Op) {
2758 if (MatchType(&NumericType,
2759 ltype->ty_PtrType.et_Type) <=
2760 SG_COMPAT_SUBCLASS &&
2761 MatchType(&NumericType,
2762 rtype->ty_PtrType.et_Type) <=
2763 SG_COMPAT_SUBCLASS &&
2764 ltype->ty_Bytes == rtype->ty_Bytes
2766 exp = ExpToCastExp(exp, ltype);
2771 if (MatchType(&NumericType,
2772 ltype->ty_CPtrType.et_Type) <=
2773 SG_COMPAT_SUBCLASS &&
2774 MatchType(&NumericType,
2775 rtype->ty_CPtrType.et_Type) <=
2776 SG_COMPAT_SUBCLASS &&
2777 ltype->ty_Bytes == rtype->ty_Bytes
2779 exp = ExpToCastExp(exp, ltype);
2784 if (MatchType(&NumericType,
2785 ltype->ty_AryType.et_Type) <=
2786 SG_COMPAT_SUBCLASS &&
2787 MatchType(&NumericType,
2788 rtype->ty_AryType.et_Type) <=
2789 SG_COMPAT_SUBCLASS &&
2790 ltype->ty_Bytes == rtype->ty_Bytes
2792 exp = ExpToCastExp(exp, ltype);
2799 "Unable to resolve cast from pointers "
2800 "to dissimilar numeric types "
2802 TypeToStr(rtype, NULL),
2803 TypeToStr(ltype, NULL));
2804 dassert_exp(exp, 0);
2808 "Unable to resolve cast from %s to %s\n",
2809 TypeToStr(rtype, NULL),
2810 TypeToStr(ltype, NULL));
2811 dassert_exp(exp, 0);
2813 } else if (d->d_ScopeFlags & SCOPE_INTERNAL) {
2815 * We found a cast operator and it is an internal operator
2817 exp = ExpToCastExp(exp, ltype);
2821 * We found a cast operator and it is a Rune cast procedure. We
2822 * must convert the cast to a procedure call. If we want
2823 * resolveCompoundExp() to be able to generate a compatible
2824 * procedure (in a subclass) we have to tell it about the
2829 sexp = ExpToCompoundExp(exp, TOK_COMPOUND);
2830 if (d->d_ProcDecl.ed_ProcBody == NULL)
2832 sexp = resolveCompoundExp(isg, sg, sexp,
2833 d->d_ProcDecl.ed_Type->ty_ProcType.et_ArgsType);
2834 exp = AllocExp(NULL);
2835 exp->ex_Lhs = AllocExp(NULL);
2836 exp->ex_Lhs->ex_Token = TOK_DECL;
2837 exp->ex_Lhs->ex_Id = d->d_Id;
2838 exp->ex_Lhs->ex_Decl = d;
2839 exp->ex_Lhs->ex_Type = d->d_ProcDecl.ed_Type;
2840 exp->ex_Lhs->ex_Flags |= EXF_RESOLVED;
2842 exp->ex_Flags |= EXF_BINARY;
2843 exp->ex_Token = TOK_CALL;
2844 /* XXX use ltype or procedure's rettype? */
2845 exp->ex_Type = ltype;
2846 LexDupRef(&sexp->ex_LexRef, &exp->ex_LexRef);
2847 LexDupRef(&sexp->ex_LexRef, &exp->ex_Lhs->ex_LexRef);
2849 exp->ex_Flags |= EXF_RESOLVED;
2855 findCast(Type *btype, Type *ltype, Type *rtype)
2861 * Locate the base type. If the base type does not have a SemGroup
2862 * there are no casts. (XXX put system operators here)
2864 sg = BaseType(&btype);
2870 * Look for the cast in the SemGroup
2872 for (d = getHead(&sg->sg_DeclList);
2874 d = getSucc(&sg->sg_DeclList, &d->d_Node)
2876 if (d->d_Op == DOP_PROC && (d->d_ScopeFlags & SCOPE_CAST)) {
2877 if (MatchCastTypes(d, ltype, rtype))
2883 * Failed. If the base type is a compound type, look for the
2884 * cast in the SemGroup for each element making up the compound
2885 * type. e.g. so (mycustomtype, double) would find the cast
2888 if (btype->ty_Op == TY_COMPOUND) {
2889 for (d = getHead(&sg->sg_DeclList);
2891 d = getSucc(&sg->sg_DeclList, &d->d_Node)
2894 if (d->d_Op & DOPF_STORAGE) {
2895 d2 = findCast(d->d_StorDecl.ed_Type,
2897 } else if (d->d_Op == DOP_TYPEDEF) {
2898 d2 = findCast(d->d_TypedefDecl.ed_Type,
2912 * resolveExpOper() - resolve an operator
2914 * This is complex enough that it is broken out into its own procedure.
2915 * Normally we just look the operator up but we have to special case
2916 * pointer arithmatic because we do will not know until now that we
2919 * itype is a return-type hint only. resolveExpOper() can ignore it
2920 * if it wishes. We currently use it to detect cast-to-void, such as
2921 * when an expression like "++i" is used in a for() loop or as a
2922 * standalone statement. This allows us to optimize the case.
2925 resolveExpOper(SemGroup *isg, SemGroup *sg, Exp *exp, Type *itype)
2928 int isPointerOp = 0;
2931 loadExpCopy(©, exp);
2932 dassert_exp(exp, exp->ex_Id != NULL);
2933 if (exFlags & EXF_BINARY) {
2934 exLhs = resolveExp(isg, sg, exLhs, NULL, 0);
2935 exRhs = resolveExp(isg, sg, exRhs, NULL, 0);
2936 } else if (exFlags & EXF_UNARY) {
2937 exLhs = resolveExp(isg, sg, exLhs, NULL, 0);
2939 dassert_exp(exp, 0);
2943 * If the lhs is a pointer look the operator up in the Pointer
2944 * class first. Operators in the Pointer class are special-cased.
2945 * A second pointer argument or a pointer return value must match
2948 * If this fails, or if the ltype is not a pointer, then look
2949 * the operator up normally.
2951 if (exLhs->ex_Type->ty_Op == TY_PTRTO ||
2952 exLhs->ex_Type->ty_Op == TY_REFTO ||
2953 exLhs->ex_Type->ty_Op == TY_CPTRTO
2958 if (exFlags & EXF_BINARY) {
2959 rtype = exRhs->ex_Type;
2960 ltype = exLhs->ex_Type;
2962 dassert(exFlags & EXF_UNARY);
2964 ltype = exLhs->ex_Type;
2966 d = findOper(&PointerType, exp->ex_Id, ltype, rtype);
2970 d = findExpOper(©);
2972 d = findExpOper(©);
2976 * Fall through to finish up resolving the operator. We just set
2977 * ex_Decl for internal operators, and construct a call for
2978 * non-internal procedural operators.
2986 dassert_exp(exp, d != NULL);
2987 dassert_exp(exp, d->d_Op == DOP_PROC);
2988 dassert_exp(exp, d->d_ProcDecl.ed_Type->ty_Op == TY_PROC);
2989 type = d->d_ProcDecl.ed_Type;
2990 exType = type->ty_ProcType.et_RetType;
2993 * Special case for internal Pointer ops. The return type is
2994 * the left-hand type (we may still optimize it to void later).
2997 (d->d_ScopeFlags & SCOPE_INTERNAL) &&
2998 SimilarType(&VoidRefType, exType)
3000 if (exType->ty_SQFlags & SF_LVALUE)
3001 exType = ADD_LVALUE(exLhs->ex_Type);
3003 exType = DEL_LVALUE(exLhs->ex_Type);
3006 type = d->d_ProcDecl.ed_Type->ty_ProcType.et_ArgsType;
3007 dassert(type->ty_Op == TY_ARGS);
3008 sg2 = type->ty_ArgsType.et_SemGroup;
3011 * Assert that LVALUE requirements are met. XXX MatchType()
3012 * code should disallow the non-lvalue-cast-to-lvalue case
3013 * so we don't have to do a check here.
3016 d2 = getHead(&sg2->sg_DeclList);
3018 d2 = getSucc(&sg2->sg_DeclList, &d2->d_Node)
3020 if ((d2->d_Op & DOPF_STORAGE) &&
3021 d2->d_Op != DOP_GLOBAL_STORAGE) {
3023 if ((d2->d_ScopeFlags & SCOPE_LVALUE) &&
3024 (exLhs->ex_Type->ty_SQFlags &
3028 "lhs of exp must be "
3030 dassert_exp(exp, 0);
3032 } else if (count == 1) {
3033 if ((d2->d_ScopeFlags & SCOPE_LVALUE) &&
3034 (exRhs->ex_Type->ty_SQFlags &
3038 "rhs of exp must be "
3040 dassert_exp(exp, 0);
3047 if (d->d_ScopeFlags & SCOPE_INTERNAL) {
3049 * Internal operator. Optimize any cast to void
3050 * by having the internal function deal with it.
3051 * (since we aren't setting exType the optimization
3052 * currently doesn't do anything, see ST_Exp)
3055 if (itype == &VoidType) {
3057 exFlags |= EXF_RET_VOID;
3061 * Normal procedural operator. Convert the left and
3062 * right hand sides to a compound expression and
3063 * convert exp to a TOK_CALL. NOTE! ex_Rhs may be
3066 * The compound expression may need to rewrite a
3067 * subclass procedure, which it can do if the
3068 * procedure's body has not yet been created (or
3069 * duplicated from the superclass). ex_Decl must
3070 * be set in this case.
3072 * Note that the expression structure may be shared.
3073 * The conversion is permanent so that is ok.
3075 * XXX keep the type intact?
3077 exLhs->ex_Next = exRhs;
3079 exRhs = ExpToCompoundExp(exRhs, TOK_COMPOUND);
3080 if (d->d_ProcDecl.ed_ProcBody == NULL)
3082 exRhs = resolveCompoundExp(isg, sg, exRhs, type);
3083 exLhs = AllocExp(NULL);
3084 LexDupRef(&exp->ex_LexRef, &exLhs->ex_LexRef);
3085 exLhs->ex_Token = TOK_ID;
3086 exLhs->ex_Id = d->d_Id;
3088 exLhs->ex_Type = d->d_ProcDecl.ed_Type;
3089 exLhs->ex_Flags |= EXF_RESOLVED;
3090 exToken = exp->ex_Token = TOK_CALL;
3091 exFlags = EXF_BINARY;
3096 "Unable to resolve operator: %s\n", exp->ex_Id);
3097 dassert_exp(exp, 0);
3099 exFlags |= EXF_RESOLVED;
3100 return(dupExpCopy(©, exp));
3104 loadExpCopy(Exp *copy, Exp *exp)
3106 copy->ex_Lhs = exp->ex_Lhs;
3107 copy->ex_Rhs = exp->ex_Rhs;
3108 copy->ex_Flags = exp->ex_Flags;
3109 copy->ex_Type = exp->ex_Type;
3110 copy->ex_Decl = exp->ex_Decl;
3111 copy->ex_Token = exp->ex_Token;
3112 copy->ex_Visibility = exp->ex_Visibility;
3113 copy->ex_Id = exp->ex_Id;
3114 copy->ex_ArgId = exp->ex_ArgId;
3115 copy->ex_AuxExp = exp->ex_AuxExp;
3119 saveExpCopy(Exp *copy, Exp *exp)
3121 exp->ex_Lhs = copy->ex_Lhs;
3122 exp->ex_Rhs = copy->ex_Rhs;
3123 exp->ex_Flags = copy->ex_Flags;
3124 exp->ex_Type = copy->ex_Type;
3125 exp->ex_Decl = copy->ex_Decl;
3126 exp->ex_Token = copy->ex_Token;
3127 exp->ex_Visibility = copy->ex_Visibility;
3128 exp->ex_Id = copy->ex_Id;
3129 exp->ex_ArgId = copy->ex_ArgId;
3130 exp->ex_AuxExp = copy->ex_AuxExp;
3133 #define EXF_DUPSHAREFLAGS -1
3136 dupExpCopy(Exp *copy, Exp *exp)
3140 if ((exp->ex_Flags & EXF_DUPEXP) == 0) {
3141 saveExpCopy(copy, exp);
3146 * We can share the expression or subexpression across duplicated
3147 * elements in distinct subclasses if these conditions are met.
3149 * Note: 0x80000000 for ex_Visibility simply means that the visibility
3150 * was never modified and can be changed for the first time.
3151 * Superclasses are resolved first so we should be ok.
3153 if (exp->ex_Lhs == copy->ex_Lhs &&
3154 exp->ex_Rhs == copy->ex_Rhs &&
3155 ((exp->ex_Flags ^ copy->ex_Flags) & ~EXF_DUPSHAREFLAGS) == 0 &&
3156 (exp->ex_Type == copy->ex_Type || exp->ex_Type == NULL) &&
3157 exp->ex_Token == copy->ex_Token &&
3158 (exp->ex_Decl == copy->ex_Decl || exp->ex_Decl == NULL) &&
3159 (exp->ex_Id == copy->ex_Id || exp->ex_Id == NULL) &&
3160 (exp->ex_ArgId == copy->ex_ArgId || exp->ex_ArgId == NULL) &&
3161 (exp->ex_AuxExp == copy->ex_AuxExp || exp->ex_AuxExp == NULL) &&
3162 (exp->ex_Visibility == copy->ex_Visibility ||
3163 (exp->ex_Visibility & 0x80000000))
3167 fprintf(stderr, "DUPEXPB COMPARE %d %p\n", ++count, exp);
3169 saveExpCopy(copy, exp);
3173 nexp = AllocExp(NULL);
3174 LexDupRef(&exp->ex_LexRef, &nexp->ex_LexRef);
3180 "DUPEXPB %d %p lhs (%p,%p) rhs (%p,%p) "
3181 "flags (%08x,%08x) types (%p, %p) "
3182 "tokens (%04x, %04x), decl (%p, %p) "
3186 exp->ex_Lhs, copy->ex_Lhs,
3187 exp->ex_Rhs, copy->ex_Rhs,
3188 exp->ex_Flags & ~EXF_DUPSHAREFLAGS,
3189 copy->ex_Flags & ~EXF_DUPSHAREFLAGS,
3190 exp->ex_Type, copy->ex_Type,
3191 exp->ex_Token, copy->ex_Token,
3192 exp->ex_Decl, copy->ex_Decl,
3193 exp->ex_Visibility, copy->ex_Visibility
3195 ExpPrintError(exp, 0);
3199 copy->ex_Flags &= ~EXF_DUPEXP;
3200 saveExpCopy(copy, nexp);
3206 * resolveType() - Resolve a type
3208 * This routine is responsible for resolving the size and alignment
3209 * features of a type. Note that we do not special-case LVALUE
3210 * qualified types here.
3212 * This routine is also rsponsible for resolving the visibility of
3213 * a type's elements. Visibility is inherited from sub-types. Base
3214 * classes's visibility should already be set by resolveSuperClass()
3217 resolveType(Type *type)
3219 SemGroup *sg = NULL;
3223 if (type->ty_Flags & TF_RESOLVED)
3226 dassert_type(type, (type->ty_Flags & TF_RESOLVING) == 0);
3227 type->ty_Flags |= TF_RESOLVING;
3229 switch(type->ty_Op) {
3232 * NOTE: TF_HASLVPTR inherited as appropriate after switch.
3234 sg = type->ty_ClassType.et_SemGroup;
3235 do2 = resolveSemGroup1(sg);
3236 type->ty_Bytes = sg->sg_Bytes;
3237 type->ty_AlignMask = sg->sg_AlignMask;
3238 /* visibility already determined by resolveSuperClass? */
3241 * Type inherits ISUNSIGNED from class. This is a special
3242 * flag helper for the interpreter and code generator.
3244 if (sg->sg_Flags & SGF_ISUNSIGNED)
3245 type->ty_Flags |= TF_ISUNSIGNED;
3246 if (sg->sg_Flags & SGF_ISFLOATING)
3247 type->ty_Flags |= TF_ISFLOATING;
3248 dassert(type->ty_Visibility != 0);
3252 * NOTE: Do not set TF_HASLVPTR, C pointers are not tracked.
3254 type->ty_Bytes = sizeof(void *);
3255 type->ty_AlignMask = POINTER_ALIGN;
3256 type->ty_CPtrType.et_Type =
3257 resolveType(type->ty_CPtrType.et_Type);
3258 type->ty_Visibility = type->ty_CPtrType.et_Type->ty_Visibility;
3262 * Set TF_HASLVPTR, pointers are tracked.
3264 type->ty_Bytes = sizeof(PointerStor);
3265 type->ty_AlignMask = POINTER_ALIGN;
3266 type->ty_PtrType.et_Type =
3267 resolveType(type->ty_PtrType.et_Type);
3268 type->ty_Visibility = type->ty_PtrType.et_Type->ty_Visibility;
3269 type->ty_Flags |= TF_HASLVPTR;
3273 * Set TF_HASLVPTR, references are tracked.
3275 type->ty_Bytes = sizeof(PointerStor);
3276 type->ty_AlignMask = POINTER_ALIGN;
3277 type->ty_RefType.et_Type =
3278 resolveType(type->ty_RefType.et_Type);
3279 type->ty_Visibility = type->ty_RefType.et_Type->ty_Visibility;
3280 type->ty_Flags |= TF_HASLVPTR;
3284 * Inherit TF_HASLVPTR (if array type is or contains something
3285 * which needs to be tracked).
3287 * XXX allow ArySize resolve to local expression?
3288 * XXX use interpreter to resolve constant expression?
3289 * XXX SemGroup passed as NULL.
3291 * XXX hack, ex_ArySize can be shared amoungst qualified
3292 * array types. Only resolve it once. XXX
3294 * YYY hack what is our ImportSemGroup ???
3297 Exp *exp = type->ty_AryType.et_ArySize;
3298 if ((exp->ex_Flags & EXF_RESOLVED) == 0) {
3299 exp = resolveConstExp(NULL,
3300 type->ty_AryType.et_SemGroup,
3303 type->ty_AryType.et_ArySize = exp;
3304 type->ty_AryType.et_Type =
3305 resolveType(type->ty_AryType.et_Type);
3306 dassert(exp->ex_Token == TOK_INTEGER);
3307 type->ty_AryType.et_Count = strtoq(exp->ex_Id, NULL, 0);
3308 type->ty_AlignMask =
3309 type->ty_AryType.et_Type->ty_AlignMask;
3311 type->ty_AryType.et_Type->ty_Bytes *
3312 type->ty_AryType.et_Count;
3314 type->ty_Visibility = type->ty_AryType.et_Type->ty_Visibility;
3315 type->ty_Flags |= type->ty_AryType.et_Type->ty_Flags &
3316 (TF_HASLVPTR | TF_HASCONSTRUCT |
3317 TF_HASDESTRUCT | TF_HASGCONSTRUCT |
3322 * NOTE: TF_HASLVPTR inherited as appropriate after switch.
3324 sg = type->ty_CompType.et_SemGroup;
3325 do2 = resolveSemGroup1(sg);
3326 type->ty_Bytes = sg->sg_Bytes;
3327 type->ty_AlignMask = sg->sg_AlignMask;
3328 type->ty_Visibility = SCOPE_ALL_VISIBLE;
3332 * NOTE: TF_HASLVPTR inherited as appropriate after switch.
3334 sg = type->ty_VarType.et_SemGroup;
3335 do2 = resolveSemGroup1(sg);
3336 type->ty_Bytes = sg->sg_Bytes;
3337 type->ty_AlignMask = sg->sg_AlignMask;
3338 type->ty_Visibility = SCOPE_ALL_VISIBLE;
3342 * NOTE: TF_HASLVPTR inherited as appropriate after switch.
3344 sg = type->ty_ArgsType.et_SemGroup;
3345 do2 = resolveSemGroup1(sg);
3346 type->ty_Bytes = sg->sg_Bytes;
3347 type->ty_AlignMask = sg->sg_AlignMask;
3348 type->ty_Visibility = SCOPE_ALL_VISIBLE;
3352 * NOTE: Storage not tracked.
3354 type->ty_ProcType.et_ArgsType =
3355 resolveType(type->ty_ProcType.et_ArgsType);
3356 type->ty_ProcType.et_RetType =
3357 resolveType(type->ty_ProcType.et_RetType);
3359 type->ty_AlignMask = 0;
3360 type->ty_Visibility = SCOPE_ALL_VISIBLE;
3364 * NOTE: Base storage is not tracked.
3366 type->ty_Bytes = type->ty_StorType.et_Bytes;
3367 /* XXX check pwr of 2 */
3369 type->ty_AlignMask = type->ty_Bytes - 1;
3370 type->ty_Visibility = SCOPE_ALL_VISIBLE;
3374 * NOTE: Tracking set by resolveType().
3376 type->ty_Flags &= ~TF_RESOLVING;
3377 type = resolveSuperClass(type);
3379 errorDottedId(otype->ty_UnresType.et_DottedId,
3380 "Unable to resolve class");
3383 type = resolveType(type);
3384 type->ty_Flags |= TF_RESOLVING;
3385 /* visibility set by resolveSuperClass() */
3389 * NOTE: Tracking unknown (must be handled at run-time).
3391 type->ty_Visibility = SCOPE_ALL_VISIBLE;
3395 * NOTE: Storage is persistent, so wrapper is not tracked.
3397 type->ty_Visibility = SCOPE_ALL_VISIBLE; /* XXX */
3402 type->ty_Flags &= ~TF_RESOLVING;
3403 type->ty_Flags |= TF_RESOLVED;
3405 resolveSemGroup2(sg);
3408 * Resolve tracking flags so the run-time can take appropriate
3413 type->ty_Flags |= TF_HASLVPTR;
3414 if (sg->sg_Flags & SGF_VARARGS)
3415 type->ty_Flags |= TF_HASLVPTR; /* XXX TF_VARARGS */
3417 type->ty_Flags |= TF_HASCONSTRUCT;
3419 type->ty_Flags |= TF_HASDESTRUCT;
3421 * Combine constructor/destructor hint flags for globals
3422 * because we have just one linked list for global constructors
3423 * and destructors (no need to optimize heavily).
3426 type->ty_Flags |= TF_HASGCONSTRUCT|TF_HASGDESTRUCT;
3430 * Resolve the default expression for the type, if any.
3432 * XXX qualified types just copy the exp. bad bad YYY
3434 * YYY resolveExp() no ISG (import sem group)
3436 if (type->ty_AssExp) {
3437 if ((type->ty_AssExp->ex_Flags & EXF_RESOLVED) == 0) {
3438 type->ty_AssExp = resolveExp(NULL, sg, type->ty_AssExp,
3439 DEL_LVALUE(type), 1);
3446 * resolveSuperClass() - resolve an unresolved dotted id sequence into a class
3448 * Unresolved type identifier sequences must be resolved. We are also
3449 * responsible for setting the visibility of the type's elements.
3452 resolveSuperClass(Type *super)
3457 int visibility = SCOPE_ALL_VISIBLE;
3460 dassert_type(super, super->ty_Op == TY_UNRESOLVED);
3462 dottedId = super->ty_UnresType.et_DottedId;
3463 sg = super->ty_UnresType.et_SemGroup;
3465 d = FindDeclPath(NULL, super->ty_UnresType.et_ImportSemGroup,
3467 dottedId, FDC_NULL, &visibility, -1, &eno);
3473 * Resolve the unresolved type. Note that this occurs during class
3474 * resolution and we can't call resolveType() here without getting into
3475 * a loop, so we do not yet know storage requirements (ty_Bytes and
3480 super->ty_Op = TY_CLASS;
3481 super->ty_ClassType.et_SemGroup = d->d_ClassDecl.ed_SemGroup;
3482 super->ty_ClassType.et_Super = d->d_ClassDecl.ed_Super;
3483 super->ty_Visibility = visibility;
3484 dassert(visibility);
3486 * XXX should we move the class from the unresolved list to
3487 * the new SemGroup's actual list?
3492 dassert_type(super, d->d_TypedefDecl.ed_Type != super);
3494 d->d_TypedefDecl.ed_Type,
3497 d->d_TypedefDecl.ed_Type->ty_SQFlags,
3501 super->ty_Visibility = visibility;
3504 errorDottedId(dottedId, "identifier is not a class or typedef");
3505 dassert_type(super, 0);
3511 * Resolve the declarations in a semantic group. We have to do this if
3512 * (a) The declaration(s) would not otherwise be resolved by our statement
3513 * scan, or (b) We need definitive size/alignment information now rather
3516 * SemGroup resolution occurs in two stages in order to deal with
3517 * resolver loops. The first stage does just enough to figure out
3518 * how large the SemGroup is (e.g. doesn't run through pointers).
3519 * The second stage completes the process.
3521 * NOTE! This code does not resolve declarations related to executable
3522 * semantic groups, such as sub-blocks within a procedure, but it does
3523 * have to resolve procedure definitions found in Class's and such.
3525 * NOTE! This code handles the last stage of subclass refinement, by
3526 * checking the validity of the refinement and setting sg_Compat properly.
3530 resolveSemGroup1(SemGroup *sg)
3534 if (sg->sg_Flags & SGF_RESOLVED)
3536 if (sg->sg_Flags & SGF_RESOLVING) {
3538 "Unable to resolve embedded recursive reference\n");
3539 dassert_semgrp(sg, (sg->sg_Flags & SGF_RESOLVING) == 0);
3541 sg->sg_Flags |= SGF_RESOLVING;
3544 * First pass - resolve storage only. Note that this specifically
3545 * does not try to handle the multiple semantic layers inside a
3546 * procedure. See ResolveStorage() for that.
3549 d = getHead(&sg->sg_DeclList);
3551 d = getSucc(&sg->sg_DeclList, &d->d_Node)
3560 case DOP_STACK_STORAGE:
3562 * can't happen. Stack storage is only used in
3563 * executable contexts.
3566 case DOP_ARGS_STORAGE:
3567 case DOP_GROUP_STORAGE:
3568 switch(d->d_StorDecl.ed_Type->ty_Op) {
3570 d->d_Bytes = sizeof(void *);
3571 d->d_AlignMask = POINTER_ALIGN;
3572 if ((d->d_Scope.s_Flags & SCOPE_ALIGN) &&
3573 d->d_Scope.s_AlignOverride) {
3575 d->d_Scope.s_AlignOverride - 1;
3580 if (d->d_ScopeFlags & SCOPE_LVALUE) {
3582 * NOTE: d->d_Bytes is different from
3583 * the size of the underlying
3584 * type that the LValueStor
3587 dassert(d->d_Op == DOP_ARGS_STORAGE);
3588 d->d_Bytes = sizeof(LValueStor);
3589 d->d_AlignMask = LVALUE_ALIGN;
3591 d->d_Bytes = sizeof(PointerStor);
3592 d->d_AlignMask = POINTER_ALIGN;
3594 if ((d->d_Scope.s_Flags & SCOPE_ALIGN) &&
3595 d->d_Scope.s_AlignOverride) {
3597 d->d_Scope.s_AlignOverride - 1;
3604 if (sg->sg_AlignMask < d->d_AlignMask)
3605 sg->sg_AlignMask = d->d_AlignMask;
3606 sg->sg_Bytes = (sg->sg_Bytes + d->d_AlignMask) &
3608 d->d_Offset = sg->sg_Bytes;
3609 sg->sg_Bytes += d->d_Bytes;
3611 case DOP_GLOBAL_STORAGE:
3612 switch(d->d_StorDecl.ed_Type->ty_Op) {
3614 d->d_Bytes = sizeof(void *);
3615 d->d_AlignMask = POINTER_ALIGN;
3616 if ((d->d_Scope.s_Flags & SCOPE_ALIGN) &&
3617 d->d_Scope.s_AlignOverride) {
3619 d->d_Scope.s_AlignOverride - 1;
3624 d->d_Bytes = sizeof(PointerStor);
3625 d->d_AlignMask = POINTER_ALIGN;
3626 if ((d->d_Scope.s_Flags & SCOPE_ALIGN) &&
3627 d->d_Scope.s_AlignOverride) {
3629 d->d_Scope.s_AlignOverride - 1;
3636 if (sg->sg_GlobalAlignMask < d->d_AlignMask)
3637 sg->sg_GlobalAlignMask = d->d_AlignMask;
3638 sg->sg_GlobalBytes = (sg->sg_GlobalBytes +
3639 d->d_AlignMask) & ~d->d_AlignMask;
3640 d->d_Offset = sg->sg_GlobalBytes;
3641 sg->sg_GlobalBytes += d->d_Bytes;
3644 dassert_semgrp(sg, 0);
3652 sg->sg_Bytes = (sg->sg_Bytes + sg->sg_AlignMask) & ~sg->sg_AlignMask;
3653 sg->sg_GlobalBytes = (sg->sg_GlobalBytes + sg->sg_GlobalAlignMask) &
3654 ~sg->sg_GlobalAlignMask;
3655 sg->sg_Flags |= SGF_RESOLVED;
3660 resolveSemGroup2(SemGroup *sg)
3665 * Second pass, resolve non-storage entities after setting
3666 * SGF_RESOLVED, these entities may legally embed this class (if
3669 * Resolve pointers that were only partially resolved in the first
3672 * Refinements have been resolved but we have to check them for
3673 * legality and set sg_Compat.
3675 * Note that this is what allows us to typedef a subclass in its
3676 * superclass. The typedef itself is safe.
3678 * Also resolve storage pointer entities that were skipped in the
3679 * first pass. Such pointers could point to ourselves.
3682 d = getHead(&sg->sg_DeclList);
3684 d = getSucc(&sg->sg_DeclList, &d->d_Node)
3686 if (d->d_ScopeFlags & SCOPE_REFINE) {
3687 resolveDecl(d->d_Super);
3689 RefineDeclaration(sg, d->d_Super, d);
3699 case DOP_ARGS_STORAGE:
3700 case DOP_GROUP_STORAGE:
3701 /*case DOP_STACK_STORAGE:*/
3702 case DOP_GLOBAL_STORAGE:
3703 switch(d->d_StorDecl.ed_Type->ty_Op) {
3712 dassert_semgrp(sg, 0);
3716 sg->sg_Flags &= ~SGF_RESOLVING;
3720 * findExpOper() - Find operator declaration matching expression
3722 * Locate the operator declaration (a DOP_PROCDEF) that matches
3723 * the expression or NULL if no match could be found. The expression's
3724 * left and right hand sides must already be resolved.
3726 * NOTE! A temporary 'copy' Exp may be passed, not all fields are valid.
3730 findExpOper(Exp *exp)
3736 if (exp->ex_Flags & EXF_BINARY) {
3737 rtype = exp->ex_Rhs->ex_Type;
3738 ltype = exp->ex_Lhs->ex_Type;
3740 dassert(exp->ex_Flags & EXF_UNARY);
3742 ltype = exp->ex_Lhs->ex_Type;
3746 * XXX look in our local semantic hierarchy for a compatible operator ?
3750 * Attempt to find a matching operator from the left hand side
3752 d = findOper(ltype, exp->ex_Id, ltype, rtype);
3754 if (d || (exp->ex_Flags & EXF_BINARY) == 0)
3757 d = findOper(rtype, exp->ex_Id, ltype, rtype);
3763 findOper(Type *btype, string_t id, Type *ltype, Type *rtype)
3767 int args = (rtype != NULL) ? 2 : 1;
3770 * Locate the base type. If the base type does not have a SemGroup
3771 * there are no operators. (XXX put system operators here)
3773 sg = BaseType(&btype);
3779 * Look for the operator in the SemGroup
3781 for (d = FindOperId(sg, id, args); d; d = d->d_ONext) {
3783 if (d->d_MyGroup == sg &&
3784 d->d_Op == DOP_PROC &&
3785 d->d_ProcDecl.ed_OperId == id &&
3786 MatchOperatorTypes(d, ltype, rtype)
3793 * Failed. If the base type is a compound type, look for the
3794 * operator in the SemGroup for each element making up the compound
3795 * type. e.g. so (mycustomtype, double) would find the operator
3798 if (btype->ty_Op == TY_COMPOUND) {
3799 for (d = getHead(&sg->sg_DeclList);
3801 d = getSucc(&sg->sg_DeclList, &d->d_Node)
3804 if (d->d_Op & DOPF_STORAGE) {
3805 d2 = findOper(d->d_StorDecl.ed_Type, id,
3807 } else if (d->d_Op == DOP_TYPEDEF) {
3808 d2 = findOper(d->d_TypedefDecl.ed_Type, id,
3821 errorDottedId(string_t *ary, const char *ctl, ...)
3827 vfprintf(stderr, ctl, va);
3829 fprintf(stderr, ": %s", ary[0]);
3830 for (i = 1; ary[i]; ++i)
3831 fprintf(stderr, ".%s", ary[i]);
3832 fprintf(stderr, "\n");
3836 * ResolveStorage() - Final storage resolution pass
3838 * This pass carefully scans the SemGroup hierarchy and assigns
3839 * offsets to declarations.
3841 * PROCEDURES - all the various 'executable' semantic layers in
3842 * a procedure are collapsed together for efficiency, so we only
3843 * have to manage one context. This means that the d_Offset
3844 * assigned to declarations in sub-blocks may exceed the sg_ size
3845 * of the sub-block's SemGroup. We do not attempt to resolve
3846 * procedure body templates (d_ProcDecl.ed_OrigBody).
3848 * CLASSES - are given offsets in their SemGroup's relative to 0, if
3849 * not already resolved.
3851 * IMPORTS - are given offsets in their SemGroup's relative to 0
3853 * COMPOUND TYPES - (such as procedure arguments) are given offsets
3854 * in their SemGroup's relative to 0.
3856 * TEMPORARY STORAGE - expressions may require temporary storage
3857 * for intermediate results. That space is reserved here.
3859 * We specifically do not resolve unrelated storage.
3862 ResolveStorage(Stmt *st)
3867 runesize_t ngoffset;
3868 SemGroup *sg = st->st_MyGroup;
3871 * If this is an executable semantic layer or an import layer then
3872 * assign storage to declarations up-front. Of the various
3873 * DOP_*_STORAGE ops, we should only see DOP_STACK_STORAGE and
3874 * DOP_GLOBAL_STORAGE.
3876 * Note: if this is the root ST_Import STF_SEMANTIC is *NOT* set and
3879 if ((st->st_Flags & STF_SEMANTIC) && st->st_Op != ST_Class) {
3882 dassert((sg->sg_Flags & (SGF_RESOLVED|SGF_RESOLVING)) == 0);
3884 sg->sg_Flags |= SGF_RESOLVING;
3887 * Procedures consolidate their storage. To make d_Offset's
3888 * come out properly.
3890 if (st->st_Flags & STF_SEMTOP) {
3891 dassert(sg->sg_Bytes == 0);
3894 offset = sg->sg_Parent->sg_Bytes;
3897 sg->sg_BlkOffset = offset;
3899 for (d = getHead(&sg->sg_DeclList);
3901 d = getSucc(&sg->sg_DeclList, &d->d_Node)
3904 case DOP_STACK_STORAGE:
3905 case DOP_ARGS_STORAGE:
3906 case DOP_GROUP_STORAGE:
3907 offset = (offset + d->d_AlignMask) &
3909 dassert_decl(d, d->d_Offset == (runesize_t)-1);
3910 d->d_Offset = offset;
3911 offset += d->d_Bytes;
3913 case DOP_GLOBAL_STORAGE:
3914 sg->sg_GlobalBytes =
3915 (sg->sg_GlobalBytes + d->d_AlignMask) &
3917 dassert_decl(d, d->d_Offset == (runesize_t)-1);
3918 d->d_Offset = sg->sg_GlobalBytes;
3919 sg->sg_GlobalBytes += d->d_Bytes;
3927 * Final alignment so, for example, arrays work properly. We
3928 * incorporate the storage into our parent at the end.
3930 sg->sg_Bytes = (offset + sg->sg_AlignMask) &
3932 sg->sg_GlobalBytes =
3933 (sg->sg_GlobalBytes + sg->sg_GlobalAlignMask) &
3934 ~sg->sg_GlobalAlignMask;
3935 sg->sg_BlkBytes = sg->sg_Bytes - sg->sg_BlkOffset;
3936 sg->sg_Flags |= SGF_RESOLVED;
3937 sg->sg_Flags &= ~SGF_RESOLVING;
3941 * Figure out how much temporary space we need to be able to execute
3942 * statements and expressions. Temporary space, like the main
3943 * procedural space, must be inherited from and consolidated into
3944 * the top-level SemGroup
3947 offset = sg->sg_TmpBytes;
3949 goffset = sg->sg_GlobalTmpBytes;
3953 * Root ST_Import. avoid compiler warnings
3963 if (st->st_ImportStmt.es_DLL) {
3964 void (*func)(void) = dlsym(st->st_ImportStmt.es_DLL,
3975 resolveStorageDeclExp(st->st_TypedefStmt.es_Decl,
3976 &noffset, &ngoffset);
3981 * Temporary space for declarations are handled here.
3987 d = st->st_DeclStmt.es_Decl;
3988 for (i = 0; i < st->st_DeclStmt.es_DeclCount; ++i) {
3989 runesize_t xoffset = offset;
3990 runesize_t xgoffset = goffset;
3992 resolveStorageDeclExp(d, &xoffset, &xgoffset);
3994 if (noffset < xoffset)
3996 if (ngoffset < xgoffset)
3997 ngoffset = xgoffset;
3998 d = getSucc(&d->d_MyGroup->sg_DeclList,
4013 if (st->st_LoopStmt.es_BCond) {
4015 resolveStorageExp(st->st_LoopStmt.es_BCond,
4017 if (noffset < xoffset)
4020 if (st->st_LoopStmt.es_ACond) {
4022 resolveStorageExp(st->st_LoopStmt.es_ACond,
4024 if (noffset < xoffset)
4027 if (st->st_LoopStmt.es_AExp) {
4029 resolveStorageExp(st->st_LoopStmt.es_AExp,
4031 if (noffset < xoffset)
4041 resolveStorageExp(st->st_IfStmt.es_Exp, &noffset);
4044 if (st->st_RetStmt.es_Exp)
4045 resolveStorageExp(st->st_RetStmt.es_Exp, &noffset);
4048 if (st->st_ResStmt.es_Exp)
4049 resolveStorageExp(st->st_ResStmt.es_Exp, &noffset);
4053 * The switch expression's temporary data must be saved while
4054 * we are executing the sub-statements (the cases).
4056 resolveStorageExp(st->st_SwStmt.es_Exp, &noffset);
4061 if (st->st_CaseStmt.es_Exp)
4062 resolveStorageExp(st->st_CaseStmt.es_Exp, &noffset);
4065 resolveStorageExp(st->st_ExpStmt.es_Exp, &noffset);
4067 case ST_ThreadSched:
4070 dassert_stmt(st, 0);
4074 * Calculate storage requirements for substatements. offset
4075 * acts as our base. We union the storage for the substatements
4076 * together. Note that often scan->sg_MyGroup == sg.
4082 scan = getHead(&st->st_List);
4084 scan = getSucc(&st->st_List, &scan->st_Node)
4086 if (scan->st_Op == ST_Class) {
4087 ResolveStorage(scan);
4088 } else if (scan->st_Op == ST_Proc &&
4089 scan->st_ProcStmt.es_Decl->d_ProcDecl.ed_OrigBody == scan
4091 /* Do not resolve template procedures! */
4092 } else if (scan->st_Flags & STF_SEMTOP) {
4093 assert(scan->st_MyGroup != sg);
4094 ResolveStorage(scan);
4097 * This is a bit of a mess. The baseline
4098 * sg_TmpBytes needs to be set so calculated
4099 * temporary offsets are relative to it, and
4100 * then restored. Otherwise we might blow
4101 * away the SGF_TMPRESOLVED SemGroup
4105 runesize_t save_offset;
4106 runesize_t save_goffset;
4107 save_offset = scan->st_MyGroup->sg_TmpBytes;
4108 save_goffset = scan->st_MyGroup->sg_GlobalTmpBytes;
4109 scan->st_MyGroup->sg_TmpBytes = offset;
4110 scan->st_MyGroup->sg_GlobalTmpBytes = goffset;
4111 ResolveStorage(scan);
4113 if (scan->st_MyGroup->sg_TmpBytes < save_offset)
4114 scan->st_MyGroup->sg_TmpBytes = save_offset;
4115 if (scan->st_MyGroup->sg_GlobalTmpBytes < save_goffset) {
4116 scan->st_MyGroup->sg_GlobalTmpBytes = save_goffset;
4118 if (noffset < scan->st_MyGroup->sg_TmpBytes)
4119 noffset = scan->st_MyGroup->sg_TmpBytes;
4120 if (ngoffset < scan->st_MyGroup->sg_GlobalTmpBytes)
4121 ngoffset = scan->st_MyGroup->sg_GlobalTmpBytes;
4127 * If this is a new semantic level call resolveStorageSemGroup() to
4128 * do the final cleanup of SemGroup issues. This will redundantly
4129 * calculate temporary space requirements. Also, due to type/class
4130 * references the temporary space for a class may have already been
4131 * resolved. Since a class can only contain declarations it had
4132 * better match what we calculate here.
4134 * Note that for non-Class executable SemGroup's TmpBytes is
4135 * incorporated in a downward fashion while sg_Bytes is incorporated
4136 * in an upward fashion. It can become quite confusing. Don't ask
4137 * me why I did it that way.
4139 if (st->st_Flags & STF_SEMANTIC) {
4140 if ((sg->sg_Flags & SGF_TMPRESOLVED) == 0) {
4141 resolveStorageSemGroup(sg, noffset, ngoffset);
4143 dassert(sg->sg_TmpBytes == noffset &&
4144 sg->sg_GlobalTmpBytes == ngoffset);
4147 sg->sg_TmpBytes = noffset;
4148 sg->sg_GlobalTmpBytes = ngoffset;
4149 } /* else this is the Root st_Import */
4151 if ((st->st_Flags & (STF_SEMANTIC|STF_SEMTOP)) == STF_SEMANTIC) {
4152 sg->sg_Parent->sg_Bytes = sg->sg_Bytes;
4153 if (sg->sg_Parent->sg_AlignMask < sg->sg_AlignMask)
4154 sg->sg_Parent->sg_AlignMask = sg->sg_AlignMask;
4159 * resolveStorageDeclExp() - resolve the storage reservation required to
4160 * process an expression.
4162 * This is an expression tree traversal storage resolution procedure.
4163 * We have to traverse through declarations to get to default assignments
4166 * If a declaration has no assign default the underlying type may itself
4167 * have an assigned default which must be dealt with.
4170 resolveStorageDeclExp(Declaration *d, runesize_t *offset, runesize_t *goffset)
4174 /* recursion already dealt with */
4176 case DOP_ARGS_STORAGE:
4177 case DOP_STACK_STORAGE:
4178 case DOP_GROUP_STORAGE:
4180 Type *type = d->d_StorDecl.ed_Type;
4182 resolveStorageType(type);
4183 if (d->d_StorDecl.ed_AssExp) {
4184 resolveStorageExp(d->d_StorDecl.ed_AssExp,
4189 case DOP_GLOBAL_STORAGE:
4191 Type *type = d->d_StorDecl.ed_Type;
4193 resolveStorageType(type);
4194 if (d->d_StorDecl.ed_AssExp) {
4195 resolveStorageExp(d->d_StorDecl.ed_AssExp,
4202 * Never try to resolve storage considerations for an
4203 * alias's assignment in the declaration itself. The
4204 * run-time context depends on who and how many other
4205 * parts of the program reference the alias and the expression
4206 * tree will be duplicated for each.
4209 if (d->d_ScopeFlags & SCOPE_GLOBAL)
4210 resolveStorageExp(d->d_AliasDecl.ed_AssExp, NULL);
4212 resolveStorageExp(d->d_AliasDecl.ed_AssExp, NULL);
4216 /* XXX what about ty_AssExp ? should be in global space */
4219 /* recursion already dealt with */
4229 * resolveStorageExp() - resolve the temporary storage required to
4230 * support the expression, if any.
4232 * We do not need to assign storage for expressions which return
4233 * lvalues, because they will simply return a pointer into
4234 * non-temporary storage.
4237 resolveStorageExpOnly(Exp *exp, runesize_t *offset)
4242 * Stop if the expression resolves to a type rather then a value,
4243 * e.g. when you do something like switch (typeof(int)) { ... }
4245 if (exp->ex_Flags & EXF_RET_TYPE)
4249 * Assign temporary offset. This offset does not overlap temporary
4250 * space reserved for sub-expressions.
4252 * We must have an assigned type. Expression sequences like:
4253 * 'module.blah' are collapsed into 'blah' long before we get
4254 * here, or they should be. We should not encounter any
4255 * TOK_TCMV_ID expression tokens. Structural id's (the right hand
4256 * side of X.Y) are resolved by their parent expression node and
4257 * no typing or temporary space is required.
4259 * Expressions that return lvalues do not need temporary space.
4261 type = exp->ex_Type;
4263 switch(exp->ex_Token) {
4268 printf("EXP %p %04x %p\n",
4269 exp, exp->ex_Token, exp->ex_Decl);
4270 dassert_exp(exp, 0);
4273 } else if (type->ty_SQFlags & SF_LVALUE) {
4275 * Expressive elements which return lvalues do not get
4276 * temporary space. Note that this also prevents lvalues
4277 * such as large arrays (int ary[999999999]) from reserving
4278 * unnecessary stack space.
4280 * NOTE: SF_LVALUE is unrelated to SCOPE_LVALUE. SCOPE_LVALUE
4281 * applies to SemGroup storage (LValueStor). SF_LVALUE
4282 * merely flags the type for an expression as expecting
4283 * or not expecting an lvalue.
4287 * XXX removeme, LValueStor only applies to semgroups
4289 runesize_t lvmask = sizeof(LValueStor) - 1;
4290 *offset = (*offset + lvmask) & ~lvmask;
4291 exp->ex_TmpOffset = *offset;
4292 *offset = *offset + (lvmask + 1);
4294 exp->ex_TmpOffset = -1;
4297 * Reserve temporary space for potential intermediate
4300 *offset = (*offset + type->ty_AlignMask) & ~type->ty_AlignMask;
4301 exp->ex_TmpOffset = *offset;
4302 *offset = *offset + type->ty_Bytes;
4308 resolveStorageExpSub(Exp *exp, runesize_t *offset)
4313 if (exp->ex_Flags & EXF_RET_TYPE)
4317 * Calculate the overlapping temporary space for sub-trees.
4319 if (exp->ex_Flags & EXF_BINARY) {
4321 * Ensure lhs's temporary storage on-return does not intefere
4322 * with rhs's or vise-versa. To do this we need to calculate
4323 * the initial storage for both sides first.
4330 resolveStorageExp(exp->ex_Lhs, &xoffset);
4331 if (*offset < xoffset)
4334 resolveStorageExp(exp->ex_Rhs, &xoffset);
4335 if (*offset < xoffset)
4337 } else if (exp->ex_Flags & EXF_UNARY) {
4338 resolveStorageExp(exp->ex_Lhs, offset);
4339 dassert_exp(exp, exp->ex_Lhs->ex_Next == NULL);
4340 } else if (exp->ex_Flags & EXF_COMPOUND) {
4342 * each element will be copied into the compound storage
4343 * in turn, so we can union the temporary storage required
4347 runesize_t noffset = *offset;
4349 for (scan = exp->ex_Lhs; scan; scan = scan->ex_Next) {
4350 runesize_t xoffset = *offset;
4352 dassert_exp(scan, scan->ex_Type != NULL);
4354 resolveStorageExp(scan, &xoffset);
4355 if (noffset < xoffset)
4362 /* XXX what about alias assign-expressions */
4363 else if (exp->ex_Flags & EXF_ALIAS) {
4365 dassert_decl(exp->ex_Decl,
4366 (exp->ex_Decl->d_ScopeFlags & SCOPE_GLOBAL) == 0);
4368 resolveStorageExp(exp->ex_Decl->d_AliasDecl.ed_AssExp, offset);
4374 resolveStorageExp(Exp *exp, runesize_t *offset)
4380 noffset = resolveStorageExpOnly(exp, &xoffset);
4382 resolveStorageExpSub(exp, &xoffset);
4383 if (*offset < xoffset)
4388 * resolveStorageType() - temporary space required to initialize type defaults
4390 * Figure out the temporary space required to initialize a type's
4391 * defaults. Note that the space will be figured independantly
4392 * for any SemGroup's.
4396 resolveStorageType(Type *type)
4398 switch(type->ty_Op) {
4400 resolveStorageSemGroup(type->ty_ClassType.et_SemGroup, 0, 0);
4403 resolveStorageType(type->ty_AryType.et_Type);
4406 resolveStorageSemGroup(type->ty_CompType.et_SemGroup, 0, 0);
4409 resolveStorageType(type->ty_ProcType.et_ArgsType);
4410 resolveStorageType(type->ty_ProcType.et_RetType);
4413 resolveStorageSemGroup(type->ty_ImportType.et_SemGroup, 0, 0);
4416 resolveStorageSemGroup(type->ty_ArgsType.et_SemGroup, 0, 0);
4419 resolveStorageSemGroup(type->ty_VarType.et_SemGroup, 0, 0);
4422 resolveStorageType(type->ty_CPtrType.et_Type);
4425 resolveStorageType(type->ty_PtrType.et_Type);
4428 resolveStorageType(type->ty_RefType.et_Type);
4433 * nothing to be done here.
4436 case TY_UNRESOLVED: /* should be no unresolved types at this stage */
4438 dassert_type(type, 0);
4440 if (type->ty_AssExp) {
4441 if ((type->ty_Flags & TF_ASSEXPSTOR) == 0) {
4442 type->ty_Flags |= TF_ASSEXPSTOR;
4443 resolveStorageExp(type->ty_AssExp, &type->ty_TmpBytes);
4449 * This is used to resolve temporary storage requirements for
4450 * SemGroup's related to classes and compound types. Temporary storage
4451 * requirements are calculated on a SemGroup-by-SemGroup basis and not
4452 * aggregated into any parent.
4454 * We also reverse the constructor and destructor lists (sg_CBase and
4455 * sg_DBase), and the pointer/lvalue list (SRBase). These lists were
4456 * originally constructed by prepending and are thus in the wrong order.
4460 resolveStorageSemGroup(SemGroup *sg, runesize_t noffset, runesize_t ngoffset)
4465 if (sg->sg_Flags & SGF_TMPRESOLVED)
4467 sg->sg_Flags |= SGF_TMPRESOLVED;
4470 d = getHead(&sg->sg_DeclList);
4472 d = getSucc(&sg->sg_DeclList, &d->d_Node)
4474 runesize_t offset = 0;
4475 runesize_t goffset = 0;
4477 resolveStorageDeclExp(d, &offset, &goffset);
4478 if (noffset < offset)
4480 if (ngoffset < goffset)
4483 if ((d2 = sg->sg_CBase) != NULL) {
4484 sg->sg_CBase = NULL;
4485 while ((d = d2) != NULL) {
4487 d->d_CNext = sg->sg_CBase;
4491 if ((d2 = sg->sg_DBase) != NULL) {
4492 sg->sg_DBase = NULL;
4493 while ((d = d2) != NULL) {
4495 d->d_DNext = sg->sg_DBase;
4499 if ((d2 = sg->sg_GBase) != NULL) {
4500 sg->sg_GBase = NULL;
4501 while ((d = d2) != NULL) {
4503 d->d_GNext = sg->sg_GBase;
4507 if ((d2 = sg->sg_SRBase) != NULL) {
4508 sg->sg_SRBase = NULL;
4509 while ((d = d2) != NULL) {
4511 d->d_SRNext = sg->sg_SRBase;
4515 sg->sg_TmpBytes = noffset;
4516 sg->sg_GlobalTmpBytes = ngoffset;