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, int flags);
19 static void ResolveAlignment(Stmt *st, int flags);
20 static void ResolveStorage(Stmt *st, int flags);
21 static void errorDottedId(string_t *ary, const char *ctl, ...);
23 static void resolveStmt(SemGroup *isg, Stmt *st, int flags);
24 static Type *resolveReturnType(SemGroup *sg, int flags);
25 static Type *resolveArgsType(SemGroup *sg, int flags);
26 static void resolveDecl(Declaration *d, int flags);
27 static Exp *resolveExp(SemGroup *isg, SemGroup *sg,
28 Exp *exp, Type *itype, int flags);
29 static Exp *resolveConstExp(SemGroup *isg, SemGroup *sg, Exp *exp, int flags);
30 static Exp *resolveConstExpBool(SemGroup *isg, SemGroup *sg, Exp *exp, int flags, RunTmpStor *ts);
31 static int64_t resolveGetConstExpInt64(Exp *exp);
32 static Exp *resolveCompoundExp(SemGroup *isg, SemGroup *sg,
33 Exp *exp, Type *itype, int flags);
34 static Exp *resolveExpCast(SemGroup *isg, SemGroup *sg,
35 Exp *exp, Type *ltype, int flags);
36 static Exp *resolveExpOper(SemGroup *isg, SemGroup *sg,
37 Exp *exp, Type *itype, int flags);
38 static int resolveSemGroup1(SemGroup *sg, int flags);
39 static int resolveSemGroup2(SemGroup *sg, int flags);
40 static void resolveSemGroup3(SemGroup *sg, int flags);
41 static Type *resolveSuperClass(Type *super);
43 static void resolveStorageDeclExpAlign(Declaration *d, runesize_t *expalignp);
44 static void resolveStorageExpAlign(Exp *exp, runesize_t *expalignp);
45 static void resolveStorageTypeExpAlign(Type *type, runesize_t *expalignp);
46 static void resolveStorageSemGroupAlign(SemGroup *sg);
48 static void resolveStorageDeclExp(Declaration *d,
49 runesize_t *offset, runesize_t *goffset);
50 static runesize_t resolveStorageExpOnly(Exp *exp, runesize_t *offset);
51 static void resolveStorageExpSub(Exp *exp, runesize_t *offset);
52 static void resolveStorageExp(Exp *exp, runesize_t *offset);
54 static Declaration *findOper(Type *btype, string_t id,
55 Type *ltype, Type *rtype, int flags);
56 static Declaration *findExpOper(Exp *exp, int flags);
57 static Declaration *findCast(Type *btype, Type *ltype, Type *rtype, int flags);
58 static void loadExpCopy(Exp *copy, Exp *exp);
59 static void saveExpCopy(Exp *copy, Exp *exp);
60 static Exp *dupExpCopy(Exp *copy, Exp *exp);
61 static void resolveStorageType(Type *type, runesize_t *offset, int isglob);
62 static void resolveStorageSemGroup(SemGroup *sg,
63 runesize_t noffset, runesize_t ngoffset);
64 static int methodProcThisIsPointer(Type *type);
66 static SemGroup *resolvePushSGDepend(SemGroup *sg);
67 static void resolvePopSGDepend(SemGroup *last);
69 #define exLhs copy.ex_Lhs
70 #define exRhs copy.ex_Rhs
71 #define exFlags copy.ex_Flags
72 #define exType copy.ex_Type
73 #define exToken copy.ex_Token
74 #define exDecl copy.ex_Decl
75 #define exVisibility copy.ex_Visibility
76 #define exId copy.ex_Id
77 #define exArgId copy.ex_ArgId
79 #define ADD_LVALUE(type) \
80 resolveType(AddTypeQual((type), SF_LVALUE), NULL, flags)
81 #define DEL_LVALUE(type) \
82 resolveType(DelTypeQual((type), SF_LVALUE), NULL, flags)
83 #define RESOLVETYPE(type) \
84 resolveType((type), NULL, flags)
85 #define RESOLVETYPEADJ(type, adjtype) \
86 resolveType((type), adjtype, flags)
88 #define RESOLVE_AUTOCAST 0x0001 /* autocast to expected type */
89 #define RESOLVE_CONSTEXP 0x0002 /* resolve for const interpretation */
92 ResolveProject(Parse *p, Stmt *st)
96 dassert_stmt(st, st->st_Op == ST_Import);
101 ResolveClasses(st, 0);
102 resolveStmt(st->st_MyGroup, st, 0);
103 ResolveAlignment(st, 0);
104 ResolveStorage(st, 0);
107 * Interpreter or Generator may reference our global internal types
108 * directly, so make sure they are all resolved.
110 for (i = 0; BaseTypeAry[i]; ++i)
111 resolveType(BaseTypeAry[i], NULL, 0);
114 * Resolve all types registered by DLLs
119 RUNE_FOREACH(tr, &TypeRegList, tr_Node)
120 resolveType(tr->tr_Type, NULL, 0);
124 p->p_Format = PFMT_RESOLVED;
130 * ResolveClasses() - Resolve superclasses and do class merge
132 * This code implements the most complex feature of the language:
133 * subclassing and refinement.
135 * The hardest thing we have to do is 'dup' declarations and code in
136 * order to implement subclassing and refinement. For example, a
137 * procedure defined in Integer must be dup'd for each subclass of
138 * Integer. We have to do this because storage requirements will
139 * change due to both subclassing and refinement. Even auto variables
140 * may wind up with different types between superclass and subclass.
142 * We must scan ST_Import and ST_Class statements.
145 ResolveClasses(Stmt *st, int flags)
147 SemGroup *sg = st->st_MyGroup;
150 * Resolver interlock. Assert that we aren't looping. A loop can
151 * occur if class A embeds class B and class B embeds class A
152 * (verses a pointer to A).
154 dassert_stmt(st, (st->st_Flags & STF_RESOLVING) == 0);
155 if (st->st_Flags & STF_RESOLVED)
157 st->st_Flags |= STF_RESOLVING;
160 * If this is a subclass, integrate the superclass into it
162 if (st->st_Op == ST_Class && st->st_ClassStmt.es_Super) {
163 Type *super = st->st_ClassStmt.es_Super;
170 * Locate the superclass. 'super' does not appear in any
171 * other list.. this is a unique Type structure.
173 dassert_stmt(st, super->ty_Op == TY_UNRESOLVED);
175 super = resolveSuperClass(super);
178 "Unable to resolve superclass of %s\n",
179 st->st_ClassStmt.es_Decl->d_Id);
182 } while (super->ty_Op == TY_UNRESOLVED);
184 dassert_stmt(st, super->ty_Op == TY_CLASS);
187 * Cleanup (XXX free qualified segments??)
189 st->st_ClassStmt.es_Super = super;
190 st->st_ClassStmt.es_Decl->d_ClassDecl.ed_Super = super;
193 * Inherit internal unsigned integer and floating point flags
196 sg->sg_Flags |= super->ty_ClassType.et_SemGroup->sg_Flags &
197 (SGF_ISINTEGER | SGF_ISUNSIGNED |
198 SGF_ISFLOATING | SGF_ISBOOL |
199 SGF_HASASS | SGF_GHASASS |
200 SGF_HASLVPTR | SGF_GHASLVPTR);
203 * Locate the class statement associated with the superclass
206 sst = super->ty_ClassType.et_SemGroup->sg_Stmt;
207 dassert_stmt(st, sst != NULL);
208 dassert_stmt(st, sst->st_Op == ST_Class);
210 ResolveClasses(sst, flags);
213 * Assign the sg_Level for the subclass. This is used
214 * for semantic searches when a subclass is passed to a
215 * procedure expecting the superclass.
217 sg->sg_Level = sst->st_MyGroup->sg_Level + 1;
220 * First move all the declarations from sg to tsg so we
221 * can merge the superclass properly (keep all the d_Index's
222 * correct). Note that tsg is not 100% integrated so we can
223 * only use it for search purposes. We absolutely CANNOT
224 * DupDeclaration() into tsg!
226 tsg = AllocSemGroup(SG_CLASS, sg->sg_Parse, NULL, sg->sg_Stmt);
227 while ((d = RUNE_FIRST(&sg->sg_DeclList)) != NULL) {
230 sg->sg_DeclCount = 0; /* reset */
233 * Merge the superclass into this class, in sequence.
234 * Iterate through declarations in the superclass and pull
235 * them into the subclass. Figure out compatibility between
236 * super and subclasses.
238 RUNE_FOREACH(d, &sst->st_MyGroup->sg_DeclList, d_Node) {
242 dassert(d->d_Level != NULL &&
243 d->d_Level->sg_Level < sg->sg_Level);
246 * See if the superclass decl conflicts with a
247 * subclass decl. If there is no conflict pull it
248 * into the subclass and adjust the visibility.
249 * Note that the superclass may have duplicate ids,
250 * but they will be at different levels if so.
252 * The super linkage is required when findDecl()
253 * checks visibility of a declaration hidden relative
254 * to our subclass, but not necessarily hidden
255 * relative to the superclass.
259 rd = FindDeclId(tsg, d->d_Id, &eno);
261 nd = DupDeclaration(sg, d);
262 dassert(d->d_Index == nd->d_Index);
263 nd->d_ScopeFlags &= ~SCOPE_ALL_VISIBLE |
264 super->ty_Visibility;
265 nd->d_ScopeFlags &= ~SCOPE_REFINE;
270 * If there is a conflict and we are not refining
271 * the superclass entity, then pull in the superclass
272 * entity and make it invisible to sg_Level searches.
273 * This could bring in multiple levels of the same id.
275 * Note that this may result in multiple ids, but
276 * they will be at different levels. In this case
277 * rd will be at the current level and nd will be
278 * at some prior level.
280 * Order is important here.
282 if ((rd->d_ScopeFlags & SCOPE_REFINE) == 0) {
283 nd = DupDeclaration(sg, d);
284 dassert(d->d_Index == nd->d_Index);
285 nd->d_ScopeFlags &= ~(SCOPE_ALL_VISIBLE |
288 printf(" conflict, not refined, overload\n");
294 * Ok, we need to refine. But the superclass may
295 * contain multiple levels of the same id. We only
296 * refine the one that is visible to us. None of
297 * these other declarations will be at the same level.
299 if ((d->d_ScopeFlags & SCOPE_ALL_VISIBLE) == 0) {
300 nd = DupDeclaration(sg, d);
301 dassert(d->d_Index == nd->d_Index);
302 nd->d_ScopeFlags &= ~(SCOPE_ALL_VISIBLE |
305 printf(" conflict, refined (skip this one)\n");
311 * Whew! Finally, we found the superclass decl
312 * that we wish to refine. We had better not have
313 * already refined it or there's something wrong
314 * with the algorithm.
316 * Since we inherit the superclass method's level
317 * our method will run in the superclass instead
318 * of the original, but d_Super still must be set
319 * for findDecl() to track down visibility relative
320 * to the superclass methods.
323 dassert_decl(rd, rd->d_Super == NULL);
324 dassert(d->d_Index == rd->d_Index);
325 rd->d_Level = d->d_Level;
329 * This is for the superclass method access special
332 if (d->d_Op == DOP_PROC) {
333 d->d_Flags |= DF_SUPERCOPY;
338 * Deal with any remaining elements in tsg. These are
339 * 'extensions' to the superclass. There may also be
340 * invisible DOP_PROC's to handle the special superclass
341 * method call case descibed above.
343 while ((rd = RUNE_FIRST(&tsg->sg_DeclList)) != NULL) {
344 if (rd->d_ScopeFlags & SCOPE_REFINE) {
345 if (rd->d_Super == NULL) {
347 "Unable to refine %s, it "
360 * We have to special case super.method() for a refined method.
361 * Normally this makes the original method inaccessible (for
362 * storage), but we want it to work for a procedure so we make
363 * a copy in tsg. (we can't dup it directly into sg because it
364 * will screw up the d_Index).
366 * We must not only clear the scope visibility and the
367 * temporary refine flag, we also have to clear
368 * constructor/destructor scope in the copy so only the
369 * refined constructor/destructor is called, not both the
370 * refined and the superclass constructor/destructor.
372 RUNE_FOREACH(d, &sst->st_MyGroup->sg_DeclList, d_Node) {
375 if (d->d_Flags & DF_SUPERCOPY) {
376 d->d_Flags &= ~DF_SUPERCOPY;
377 nd = DupDeclaration(sg, d);
378 nd->d_ScopeFlags &= ~(SCOPE_ALL_VISIBLE |
384 } else if (st->st_Op == ST_Class) {
388 st->st_Flags &= ~STF_RESOLVING;
389 st->st_Flags |= STF_RESOLVED;
392 * If this is an ST_Import we must recurse through it. The only
393 * statements under an Import should be Modules. Well, really just
394 * one module. And under that module we only care about ST_Import
395 * and ST_Class statements.
397 * If this is a shared import the statement list will be empty (later
398 * it may be used for import refinement, I dunno). This is what we
399 * want since we should only resolve a shared import once.
401 if (st->st_Op == ST_Import) {
404 RUNE_FOREACH(scan, &st->st_List, st_Node) {
407 dassert_stmt(scan, scan->st_Op == ST_Module);
408 RUNE_FOREACH(scan2, &scan->st_List, st_Node) {
409 if (scan2->st_Op == ST_Import ||
410 scan2->st_Op == ST_Class) {
411 ResolveClasses(scan2, flags);
415 if (st->st_ImportStmt.es_DLL) {
416 void (*func)(void) = dlsym(st->st_ImportStmt.es_DLL,
425 * resolveStmt() - Resolve all types, declarations, and semantic refs
427 * Resolves all types, declarations, and identifiers. Additionally
428 * this function resolves intermediate types for expressions. Storage
429 * sizes are resolved but offsets are not assigned to declarations.
432 resolveStmt(SemGroup *isg, Stmt *st, int flags)
434 SemGroup *dep = NULL;
437 * Deal with unresolved types here
439 if (st->st_Flags & STF_SEMANTIC) {
440 SemGroup *sg = st->st_MyGroup;
443 dep = resolvePushSGDepend(sg);
445 RUNE_FOREACH(type, &sg->sg_ClassList, ty_Node) {
446 if (type->ty_Op == TY_UNRESOLVED) {
447 if (resolveSuperClass(type) == NULL) {
449 type->ty_UnresType.et_DottedId,
450 "Unable to resolve class");
458 * Resolve statements. Don't worry about declarations, those are
459 * handled after this switch.
464 * This will just flag the import declaration as resolved
465 * so the code generator dives it for generation.
467 if (st->st_ImportStmt.es_Decl)
468 resolveDecl(st->st_ImportStmt.es_Decl, flags);
472 * Recursively resolve contents
477 RUNE_FOREACH(scan, &st->st_List, st_Node) {
479 * XXX pass isg for import, st_MyGroup for
482 resolveStmt(st->st_MyGroup, scan, flags);
484 if (st->st_Op == ST_Import &&
485 st->st_ImportStmt.es_DLL) {
487 dlsym(st->st_ImportStmt.es_DLL,
495 resolveDecl(st->st_ClassStmt.es_Decl, flags);
498 resolveDecl(st->st_TypedefStmt.es_Decl, flags);
502 * Resolve declarations, skipping any whos context was
503 * moved to a class (e.g. a declaration at the top level
504 * of a file like Fd.setfd(...) also exists in the Fd class).
507 Declaration *d = st->st_DeclStmt.es_Decl;
510 for (i = 0; i < st->st_DeclStmt.es_DeclCount; ++i) {
511 if (st->st_MyGroup != d->d_MyGroup)
512 /*printf("SKIPA %s\n", d->d_Id)*/;
514 resolveDecl(d, flags);
515 d = RUNE_NEXT(d, d_Node);
523 RUNE_FOREACH(scan, &st->st_List, st_Node) {
524 resolveStmt(isg, scan, flags);
531 if (st->st_LoopStmt.es_Init)
532 resolveStmt(isg, st->st_LoopStmt.es_Init, flags);
533 if (st->st_LoopStmt.es_BCond) {
535 * NOTE: BoolType global implies an rvalue.
537 st->st_LoopStmt.es_BCond =
538 resolveExp(isg, st->st_MyGroup,
539 st->st_LoopStmt.es_BCond,
540 &BoolType, RESOLVE_AUTOCAST);
542 if (st->st_LoopStmt.es_ACond) {
544 * NOTE: BoolType global implies an rvalue.
546 st->st_LoopStmt.es_ACond =
547 resolveExp(isg, st->st_MyGroup,
548 st->st_LoopStmt.es_ACond,
549 &BoolType, RESOLVE_AUTOCAST);
551 if (st->st_LoopStmt.es_AExp) {
553 * NOTE: VoidType global implies an rvalue.
555 st->st_LoopStmt.es_AExp =
556 resolveExp(isg, st->st_MyGroup,
557 st->st_LoopStmt.es_AExp,
558 &VoidType, RESOLVE_AUTOCAST);
560 if (st->st_LoopStmt.es_Body) {
561 resolveStmt(isg, st->st_LoopStmt.es_Body, flags);
563 /* remove handled in resolveDecl DOP_PROC */
564 if ((st->st_LoopStmt.es_Body->st_Flags &
565 STF_RESOLVED) == 0) {
566 ResolveAlignment(st->st_LoopStmt.es_Body,
568 ResolveStorage(st->st_LoopStmt.es_Body, flags);
579 * NOTE: BoolType global implies an rvalue.
581 st->st_IfStmt.es_Exp = resolveExp(isg, st->st_MyGroup,
582 st->st_IfStmt.es_Exp,
583 &BoolType, RESOLVE_AUTOCAST);
584 resolveStmt(isg, st->st_IfStmt.es_TrueStmt, flags);
585 if (st->st_IfStmt.es_FalseStmt)
586 resolveStmt(isg, st->st_IfStmt.es_FalseStmt, flags);
590 * NOTE: lvalue/rvalue depends on return type.
592 st->st_RetStmt.es_ProcRetType =
593 resolveReturnType(st->st_MyGroup, flags);
594 if (st->st_RetStmt.es_Exp) {
595 st->st_RetStmt.es_Exp =
596 resolveExp(isg, st->st_MyGroup,
597 st->st_RetStmt.es_Exp,
598 st->st_RetStmt.es_ProcRetType,
604 * NOTE: lvalue/rvalue depends on return type.
606 st->st_ResStmt.es_ProcRetType =
607 resolveReturnType(st->st_MyGroup, flags);
608 if (st->st_ResStmt.es_Exp) {
609 st->st_ResStmt.es_Exp =
610 resolveExp(isg, st->st_MyGroup,
611 st->st_ResStmt.es_Exp,
612 st->st_ResStmt.es_ProcRetType,
618 * NOTE: Switch type must be an rvalue.
620 * NOTE: It is possible to switch on a type. See ST_Case
621 * below for more detail.
623 st->st_SwStmt.es_Exp->ex_Flags |= EXF_REQ_TYPE;
624 st->st_SwStmt.es_Exp = resolveExp(isg, st->st_MyGroup,
625 st->st_SwStmt.es_Exp,
629 * Switch-on-expression() expects an rvalue.
631 if ((st->st_SwStmt.es_Exp->ex_Flags & EXF_RET_TYPE) == 0) {
632 st->st_SwStmt.es_Exp->ex_Type =
633 DEL_LVALUE(st->st_SwStmt.es_Exp->ex_Type);
638 RUNE_FOREACH(scan, &st->st_List, st_Node) {
639 resolveStmt(isg, scan, flags);
645 * Handle a case/default. Note that when switching on a type,
646 * each case expression must return a type.
648 * NOTE: Case type must be an rvalue. We use the switch type
649 * to cast, so it will be.
657 * Set type to cast cases to if we are switching on
658 * an expression, otherwise we are switching on a
659 * type and should not try to coerce the cases (it
660 * doesn't make sense to).
662 dassert_stmt(st, st->st_Parent->st_Op == ST_Switch);
663 if (st->st_Parent->st_SwStmt.es_Exp->ex_Flags & EXF_RET_TYPE)
666 type = st->st_Parent->st_SwStmt.es_Exp->ex_Type;
669 * case: (if es_Exp is NULL, this is a default: )
671 if ((exp = st->st_CaseStmt.es_Exp) != NULL) {
673 exp->ex_Flags |= EXF_REQ_TYPE;
674 exp = resolveExp(isg, st->st_MyGroup,
675 exp, type, RESOLVE_AUTOCAST);
677 dassert(exp->ex_Flags & EXF_RET_TYPE);
678 st->st_CaseStmt.es_Exp = exp;
682 * Elements of the case/default
684 RUNE_FOREACH(scan, &st->st_List, st_Node) {
685 resolveStmt(isg, scan, flags);
691 * NOTE: VoidType global implies an rvalue.
693 * NOTE: If resolveExp() doesn't cast to void for
694 * us, we will do it here.
699 exp = resolveExp(isg, st->st_MyGroup,
700 st->st_ExpStmt.es_Exp,
701 &VoidType, RESOLVE_AUTOCAST);
702 if (exp->ex_Type != &VoidType) {
703 exp = resolveExpCast(isg, st->st_MyGroup,
704 exp, &VoidType, flags);
706 st->st_ExpStmt.es_Exp = exp;
713 RUNE_FOREACH(scan, &st->st_List, st_Node) {
714 resolveStmt(isg, scan, flags);
723 if (st->st_Flags & STF_SEMANTIC)
724 resolvePopSGDepend(dep);
728 * Locate the ST_Proc statement and resolve & return its return type
732 resolveReturnType(SemGroup *sg, int flags __unused)
739 * Locate the ST_Proc statement
741 while (sg && (sg->sg_Stmt == NULL || sg->sg_Stmt->st_Op != ST_Proc))
745 d = st->st_ProcStmt.es_Decl; /* decl is already resolved */
746 dassert_decl(d, d->d_Op == DOP_PROC);
747 dassert_decl(d, d->d_Flags & (DF_RESOLVING|DF_RESOLVED));
748 type = d->d_ProcDecl.ed_Type;
749 dassert_decl(d, type->ty_Op == TY_PROC);
750 return(type->ty_ProcType.et_RetType);
754 resolveArgsType(SemGroup *sg, int flags __unused)
761 * Locate the ST_Proc statement
763 while (sg && (sg->sg_Stmt == NULL || sg->sg_Stmt->st_Op != ST_Proc))
767 d = st->st_ProcStmt.es_Decl; /* decl is already resolved */
768 dassert_decl(d, d->d_Op == DOP_PROC);
769 dassert_decl(d, d->d_Flags & (DF_RESOLVING|DF_RESOLVED));
770 type = d->d_ProcDecl.ed_Type;
771 dassert_decl(d, type->ty_Op == TY_PROC);
772 return(type->ty_ProcType.et_ArgsType);
776 * resolveDecl() - resolve a declaration
778 * Note: we do not resolve d_Offset here.
780 * If the declaration represents a procedure argument, special
781 * processing of LVALUE scope is required to pass the declaration
782 * by reference instead of by value. Note that the size of the
783 * underlying type DOES NOT CHANGE... it may be much larger.
786 resolveDecl(Declaration *d, int flags)
792 if (d->d_Flags & DF_RESOLVED)
794 dassert_decl(d, (d->d_Flags & DF_RESOLVING) == 0);
795 d->d_Flags |= DF_RESOLVING;
799 if (d->d_ClassDecl.ed_Super) {
800 d->d_ClassDecl.ed_Super =
801 RESOLVETYPE(d->d_ClassDecl.ed_Super);
803 sg = d->d_ClassDecl.ed_SemGroup;
804 if (resolveSemGroup1(sg, flags) && resolveSemGroup2(sg, flags))
805 resolveSemGroup3(sg, flags);
806 d->d_Bytes = d->d_ClassDecl.ed_SemGroup->sg_Bytes;
807 d->d_AlignMask = d->d_ClassDecl.ed_SemGroup->sg_AlignMask;
811 * Alias access is a barrier and always returns an rvalue.
813 type = d->d_AliasDecl.ed_Type =
814 RESOLVETYPE(d->d_AliasDecl.ed_Type);
815 if (d->d_AliasDecl.ed_AssExp) {
816 d->d_AliasDecl.ed_AssExp =
817 resolveExp(d->d_ImportSemGroup, d->d_MyGroup,
818 d->d_AliasDecl.ed_AssExp,
820 flags | RESOLVE_AUTOCAST);
822 /* handled in DOT and STRIND resolver */
823 SetDupExp(NULL, d->d_AliasDecl.ed_AssExp);
826 d->d_Flags |= DF_RESOLVED;
827 type = RESOLVETYPE(d->d_TypedefDecl.ed_Type);
828 d->d_Flags &= ~DF_RESOLVED;
829 d->d_TypedefDecl.ed_Type = type;
833 * This only occurs when resolving an import's semantic group.
834 * Since we are scanning statements in that context we do not
835 * have to recurse here, resolveStmt() will do it for us.
840 * XXX global procedure, later on, make the argument a
841 * type instead of storage?
843 d->d_ProcDecl.ed_Type = RESOLVETYPE(d->d_ProcDecl.ed_Type);
846 * Deal with constructor/destructor chaining. The chaining
847 * winds up being reversed and will be corrected by the caller.
849 if (d->d_ScopeFlags & SCOPE_GLOBAL) {
850 if (d->d_ScopeFlags & (SCOPE_CONSTRUCTOR |
852 d->d_GNext = d->d_MyGroup->sg_GBase;
853 d->d_MyGroup->sg_GBase = d;
856 if (d->d_ScopeFlags & SCOPE_CONSTRUCTOR) {
857 d->d_CNext = d->d_MyGroup->sg_CBase;
858 d->d_MyGroup->sg_CBase = d;
860 if (d->d_ScopeFlags & SCOPE_DESTRUCTOR) {
861 d->d_DNext = d->d_MyGroup->sg_DBase;
862 d->d_MyGroup->sg_DBase = d;
867 * If this procedure is bound to a DLL we have to resolve
870 if (d->d_ScopeFlags & SCOPE_CLANG) {
871 d->d_ProcDecl.ed_DLLFunc =
872 FindDLLSymbol(NULL, d->d_ImportSemGroup,
876 case DOP_ARGS_STORAGE:
877 case DOP_STACK_STORAGE:
878 case DOP_GLOBAL_STORAGE:
879 case DOP_GROUP_STORAGE:
880 type = RESOLVETYPE(d->d_StorDecl.ed_Type);
881 d->d_StorDecl.ed_Type = type;
884 * Promote the lvalue storage qualifier (e.g. from a typedef)
885 * into the declaration's scope. This is what ultimately
886 * controls lvalue vs rvalue arguments to procedures and such.
888 if ((type->ty_SQFlags & SF_LVALUE) &&
889 (d->d_ScopeFlags & SCOPE_LVALUE) == 0
891 d->d_ScopeFlags |= SCOPE_LVALUE;
895 * Default assignment handling expects an rvalue.
897 if (d->d_StorDecl.ed_AssExp) {
898 d->d_StorDecl.ed_AssExp =
899 resolveExp(d->d_ImportSemGroup, d->d_MyGroup,
900 d->d_StorDecl.ed_AssExp,
902 flags | RESOLVE_AUTOCAST);
904 if (d->d_ScopeFlags & SCOPE_LVALUE) {
906 * Object is passed as a LValueStor structure. Note
907 * that d_Bytes is going to be different then the
908 * underlying type (which represents the actual
911 d->d_Bytes = sizeof(LValueStor);
912 d->d_AlignMask = LVALUE_ALIGN;
915 * Object is passed by value.
917 d->d_AlignMask = type->ty_AlignMask;
918 d->d_Bytes = type->ty_Bytes;
922 * If the declaration represents or contains an
923 * argument-lvalue or a pointer we have to add it to
924 * the SemGroup's SRBase list to properly reference or
925 * dereference the elements. XXX only do this for non-global
928 * If the declaration has LVALUE scope we must do the same
929 * because the ref is tracked.
931 if (d->d_Op != DOP_GLOBAL_STORAGE &&
932 (type->ty_Flags & TF_HASLVPTR)) {
933 d->d_SRNext = d->d_MyGroup->sg_SRBase;
934 d->d_MyGroup->sg_SRBase = d;
935 } else if (d->d_ScopeFlags & SCOPE_LVALUE) {
936 d->d_SRNext = d->d_MyGroup->sg_SRBase;
937 d->d_MyGroup->sg_SRBase = d;
941 * Deal with constructor/destructor chaining. The chaining
942 * winds up being reversed and will be corrected by the
945 if (type->ty_Flags & TF_HASCONSTRUCT) {
946 d->d_CNext = d->d_MyGroup->sg_CBase;
947 d->d_MyGroup->sg_CBase = d;
949 if (type->ty_Flags & TF_HASDESTRUCT) {
950 d->d_DNext = d->d_MyGroup->sg_DBase;
951 d->d_MyGroup->sg_DBase = d;
953 if (type->ty_Flags & (TF_HASGCONSTRUCT|TF_HASGDESTRUCT)) {
954 d->d_GNext = d->d_MyGroup->sg_GBase;
955 d->d_MyGroup->sg_GBase = d;
959 * Automatic content-locking is only applicable to objects
960 * that are or contain lvalues, pointers, or references.
961 * Setting UNLOCKED relaxes requirements on taking the
962 * address of the object.
964 * Automatic content-locking is not performed on class objects
965 * or arrays. We can set those to unlocked as well also
968 if ((d->d_Op & DOPF_STORAGE) &&
969 (d->d_Scope.s_Flags & SCOPE_LVALUE) == 0) {
970 if ((type->ty_Flags & TF_HASLVPTR) == 0 ||
971 type->ty_Op == TY_CLASS ||
972 type->ty_Op == TY_ARYOF) {
973 d->d_ScopeFlags |= SCOPE_UNLOCKED;
981 d->d_Flags &= ~DF_RESOLVING;
982 d->d_Flags |= DF_RESOLVED;
985 * Post resolution flag resolving (to handle recursion)
990 * Create copies of procedures as they are needed (thus
991 * avoiding an XxY matrix effect).
993 if ((st = d->d_ProcDecl.ed_OrigBody) == NULL) {
994 Declaration *super = d->d_Super;
995 while (super && super->d_ProcDecl.ed_OrigBody == NULL) {
996 super = super->d_Super;
999 st = super->d_ProcDecl.ed_OrigBody;
1000 if (super->d_MyGroup->sg_Stmt->st_Op == ST_Class) {
1002 * Copy-down a procedure from a
1003 * superclass. The procedure must
1004 * still be linked into its superclass
1005 * for semantic searches to work as
1006 * expected, hence the use of super->
1007 * d_MyGroup and st->st_Parent.
1009 * Note that this code is not reached
1010 * in the case of a nested procedure,
1011 * since nested procedures are copied
1014 st = DupStmt(super->d_MyGroup,
1018 * Copy-down a nested procedure.
1019 * The procedure must be linked
1020 * into the copy of the parent
1021 * prodedure, not the original
1022 * parent procedure, or it will
1023 * never be resolved.
1025 st = DupStmt(d->d_Stmt->st_MyGroup,
1030 * Internal procedure (we do not need to do
1031 * anything), there is no statement body
1037 * Procedure is being used in the primary class it
1040 st = DupStmt(d->d_MyGroup, st->st_Parent, st);
1044 * Link the procedure body to the declaration and
1045 * resolve the procedure body.
1047 dassert_stmt(st, d->d_ProcDecl.ed_ProcBody == NULL);
1049 d->d_ProcDecl.ed_ProcBody = st;
1050 st->st_ProcStmt.es_Decl = d;
1051 st->st_ProcStmt.es_Scope = d->d_Scope;
1052 resolveStmt(d->d_ImportSemGroup, st, flags);
1054 ResolveAlignment(st, flags);
1055 ResolveStorage(st, flags);
1064 * __align(%d) scope qualifier, override the type's alignment
1066 if ((d->d_Scope.s_Flags & SCOPE_ALIGN) && d->d_Scope.s_AlignOverride)
1067 d->d_AlignMask = d->d_Scope.s_AlignOverride - 1;
1071 * resolveExp() - resolve expression
1073 * Resolve an expression. We are expected to resolve all ex_Type's
1074 * for the expression tree as well as expected to track down
1075 * operators and base identifiers.
1077 * itype is a type hint. If non-NULL, the caller would like our
1078 * expression to return the specified type. There are a few special
1081 * EXF_REQ_ARRAY - when OBRACKET requests an arry optimization it
1082 * passes a post-array-indexed typehint (as if
1083 * you had done the optimization). You must ignore
1084 * itype if you are unable to do the optimization.
1086 * NOTE: Even rvalues may have refstor side-effects at run-time.
1089 resolveExp(SemGroup *isg, SemGroup *sg, Exp *exp, Type *itype, int flags)
1094 loadExpCopy(©, exp);
1098 * Must resolve cast target type hint.
1101 itype = RESOLVETYPE(itype);
1104 * note: certain cases below call other resolver functions and assume
1105 * that ex* variables are unchanged.
1107 dassert((exFlags & EXF_DUPEXP) || (exFlags & EXF_RESOLVED) == 0);
1112 * An assignment. Note that we optimize void returns
1113 * (such as when an assignment is a statement like 'a = 4;'
1114 * ... the result of the assignment is cast to void.
1116 * NOTE: Left-hand-side must be an LVALUE, return type
1117 * inherits this feature unless the parent turns off
1118 * the bit so the TOK_ASS run-time must deal with that.
1120 exLhs = resolveExp(isg, sg, exLhs, NULL,
1121 flags & ~RESOLVE_AUTOCAST);
1122 dassert_exp(exLhs, exLhs->ex_Type->ty_SQFlags & SF_LVALUE);
1123 exRhs = resolveExp(isg, sg, exRhs,
1124 DEL_LVALUE(exLhs->ex_Type),
1125 flags | RESOLVE_AUTOCAST);
1127 /* AssExp handles this optimization */
1128 if (itype == &VoidType) {
1130 exFlags |= EXF_RET_VOID;
1132 exType = exLhs->ex_Type;
1137 * Check @ref assignment compatibility.
1139 if (exLhs->ex_Type->ty_Op == TY_REFTO) {
1140 switch(MatchType(exLhs->ex_Type, exRhs->ex_Type)) {
1141 case SG_COMPAT_FULL:
1142 printf("assign %s compatibility FULL\n",
1145 case SG_COMPAT_PART:
1146 printf("assign %s compatibility PART\n",
1149 case SG_COMPAT_SUBCLASS:
1150 printf("assign %s compatibility SUBCL\n",
1153 case SG_COMPAT_FAIL:
1154 printf("assign %s compatibility FAIL\n",
1163 * NOTE: BoolType global implies an rvalue.
1166 exLhs = resolveExp(isg, sg, exLhs, &BoolType,
1167 flags | RESOLVE_AUTOCAST);
1170 * If left-side can terminate the operation, mark the
1171 * expression as PROBCONST for the interpreter and code
1172 * generator (allowing the rhs to not be a constant).
1174 if (exLhs->ex_Flags & (EXF_CONST | EXF_PROBCONST)) {
1177 exLhs = resolveConstExpBool(isg, sg, exLhs, flags, &ts);
1178 if (ts.ts_Bool == 0)
1179 exFlags |= EXF_PROBCONST;
1181 exRhs = resolveExp(isg, sg, exRhs, &BoolType,
1182 flags | RESOLVE_AUTOCAST);
1187 * NOTE: BoolType global implies an rvalue.
1190 exLhs = resolveExp(isg, sg, exLhs, &BoolType,
1191 flags | RESOLVE_AUTOCAST);
1194 * If left-side can terminate the operation, mark the
1195 * expression as PROBCONST for the interpreter and code
1196 * generator (allowing the rhs to not be a constant).
1198 if (exLhs->ex_Flags & (EXF_CONST | EXF_PROBCONST)) {
1201 exLhs = resolveConstExpBool(isg, sg, exLhs, flags, &ts);
1203 exFlags |= EXF_PROBCONST;
1205 exRhs = resolveExp(isg, sg, exRhs, &BoolType,
1206 flags | RESOLVE_AUTOCAST);
1211 * This synthesized token occurs when we are able to collapse
1212 * a structural indirection or dotted element into a
1213 * declaration. For example, 'module.routine'.
1215 /* XXX couldconst? */
1220 * Structual field access. The left hand side may be an object
1221 * (class or compound), a class type, or a compound type.
1223 * A dotted access requires an lvalue on the left hand side
1224 * if the left hand side represents storage.
1226 * The result will be an lvalue if the right hand side
1227 * represents storage. We only loop if the right hand side
1228 * is an alias replacement.
1239 int procedureOnly = 0;
1240 int eno = TOK_ERR_ID_NOT_FOUND;
1243 * NOTE: Hint must 'always happen' since we may be
1244 * modifying an expression that will later be
1247 * NOTE: Lhs is always an lvalue for TOK_DOT, but
1248 * does not have to be for TOK_STRIND.
1250 exLhs->ex_Flags |= EXF_REQ_TYPE;
1251 if (exToken == TOK_DOT && (exFlags & EXF_REQ_ADDROF))
1252 exLhs->ex_Flags |= EXF_REQ_ADDROF;
1253 exLhs = resolveExp(isg, sg, exLhs, NULL,
1254 flags & ~RESOLVE_AUTOCAST);
1257 * The RHS may have been turned into a TOK_SEMGRP_ID
1258 * in a previous duplicate. The change is considered
1261 if (exRhs->ex_Token != TOK_SEMGRP_ID) {
1263 exRhs->ex_Token == TOK_STRUCT_ID);
1264 exRhs = resolveExp(isg, sg, exRhs, NULL,
1265 flags & ~RESOLVE_AUTOCAST);
1268 type = exLhs->ex_Type;
1271 * Calculate scope and SemGroup to search. Note
1272 * that it is legal to do a structural '.' selection
1273 * on a pointer, but it works differently then
1274 * indirecting through a pointer via '->'. In the
1275 * case of '.' on a pointer, we first search the
1276 * system Pointer class.
1278 if (exLhs->ex_Flags & EXF_RET_TYPE) {
1283 * Figure out the base type used to look-up the
1284 * identifier. An identifier that resolves into a
1285 * procedure winds up only being a hint for a
1288 if (exToken == TOK_STRIND) {
1289 switch(type->ty_Op) {
1291 type = type->ty_CPtrType.et_Type;
1294 type = type->ty_PtrType.et_Type;
1297 type = type->ty_RefType.et_Type;
1301 dassert_exp(exp, 0);
1307 switch(type->ty_Op) {
1309 sg2 = type->ty_ClassType.et_SemGroup;
1312 sg2 = type->ty_CompType.et_SemGroup;
1315 sg2 = type->ty_ArgsType.et_SemGroup;
1318 sg2 = type->ty_VarType.et_SemGroup;
1321 sg2 = type->ty_ImportType.et_SemGroup;
1325 dassert_exp(exp, PointerType.ty_Op == TY_CLASS);
1326 sg2 = PointerType.ty_ClassType.et_SemGroup;
1329 dassert_exp(exp, PointerType.ty_Op == TY_CLASS);
1330 sg2 = PointerType.ty_ClassType.et_SemGroup;
1334 dassert_exp(exp, PointerType.ty_Op == TY_CLASS);
1335 sg2 = PointerType.ty_ClassType.et_SemGroup;
1339 * Possibly a pointer, aka ptr.NULL
1343 visibility = exLhs->ex_Visibility;
1346 * Locate the identifier normally, via its type.
1347 * ty_TypeVisbility is the initial visibility (scope)
1348 * that the semantic search should use in locating
1352 string_t ary[2] = { id, NULL };
1355 if (exLhs->ex_Token == TOK_ID ||
1356 exLhs->ex_Token == TOK_DECL) {
1357 if (exLhs->ex_Decl->d_Search) {
1358 level = exLhs->ex_Decl->
1361 level = sg2->sg_Level;
1367 if (exLhs->ex_Flags & EXF_SUPER) {
1369 fprintf(stderr, "Can't super with reference type\n");
1370 dassert_exp(exp, 0);
1373 fprintf(stderr, "No superclass available\n");
1374 dassert_exp(exp, 0);
1379 level = sg2->sg_Level; /* may be -1 */
1381 visibility &= type->ty_Visibility;
1382 d = FindDeclPath(&exp->ex_LexRef, NULL,
1385 &visibility, level, &eno);
1387 * XXX more hack. If the super is visible
1388 * and a procedure we just found our own
1389 * refinement, not the superclass method.
1390 * This is because there is no 'superclass
1391 * method' per say, refinements *REPLACE*
1392 * superclass declarations and inherit the
1393 * superclass's level. However, we still
1394 * want to be able to chain method calls so
1395 * what we do instead is go through and find
1396 * the procedure that we smacked when we did
1397 * the refinement. This procedure has
1398 * already been conveniently brought into
1399 * the subclass context as an 'invisible'
1400 * entity at the same d_Level.
1402 if ((exLhs->ex_Flags & EXF_SUPER) &&
1404 d->d_Op == DOP_PROC &&
1405 (d->d_ScopeFlags & SCOPE_ALL_VISIBLE)
1407 string_t id2 = d->d_Id;
1408 SemGroup *olevel = d->d_Level;
1410 dassert_exp(exp, isRefTo == 0);
1412 while ((d = RUNE_NEXT(d, d_Node)) != NULL) {
1413 if (d->d_Id == id2 &&
1414 d->d_Level == olevel &&
1415 d->d_Op == DOP_PROC) {
1424 if (d && procedureOnly && d->d_Op != DOP_PROC) {
1426 "PTR.ELEMENT may be used for special "
1427 "pointer method calls, but not to "
1428 "access storage elements. "
1429 "Use PTR->ELEMENT instead\n");
1430 dassert_exp(exp, 0);
1434 * If referencing actual storage the storage must be
1437 if (d && globalOnly && (d->d_Op & DOPF_STORAGE) &&
1438 (d->d_ScopeFlags & SCOPE_GLOBAL) == 0
1441 "%s is not global. Only globals "
1442 "can be accessed through a type\n",
1444 dassert_exp(exp, 0);
1449 * Identifier found. Note that if we are
1450 * going through a reference type the
1451 * declaration is not the actual one we
1452 * use at run time. It's just a template.
1454 resolveDecl(d, flags);
1456 exVisibility = visibility;
1459 * XXX this is in wrong place
1461 * ADDROF content-locked storage is not
1462 * allowed, except for the SCOPE_LVALUE case
1463 * if the underlying type is acceptable.
1465 * If we are running through an LValueStor
1466 * UNLOCKED applies to it and not its contents.
1467 * Check to see if the contents are acceptable.
1469 if ((exFlags & EXF_REQ_ADDROF) &&
1470 (d->d_Op & DOPF_STORAGE) &&
1471 (d->d_Scope.s_Flags & SCOPE_UNLOCKED) == 0) {
1472 type = d->d_StorDecl.ed_Type;
1473 if ((type->ty_Flags & TF_HASLVPTR) &&
1474 type->ty_Op != TY_CLASS &&
1475 type->ty_Op != TY_ARYOF) {
1477 TOK_ERR_ILLEGAL_ADDRLOCKED);
1478 dassert_exp(exp, 0);
1487 exType = d->d_ProcDecl.ed_Type;
1488 if (d->d_ProcDecl.ed_Type->ty_SQFlags & SF_METHOD) {
1490 * Method call, do not
1491 * collapse the expression into
1492 * a direct declaration because
1493 * the object is needed later.
1495 if (exLhs->ex_Flags & EXF_RET_TYPE)
1496 ExpPrintError(exLhs, TOK_ERR_METHOD_REQUIRES_OBJ);
1497 dassert((exLhs->ex_Flags & EXF_RET_TYPE) == 0);
1498 } else if (isRefTo) {
1500 * Call via reference. The
1501 * lhs is required to evaluate
1502 * the actual method call at
1507 * Global method call or normal
1508 * call. For the global method
1509 * case the lhs is not needed
1510 * because the parser entered
1511 * the first argument as a
1514 * Degenerate into a TOK_DECL.
1515 * We depend on this later.
1517 exFlags &= ~EXF_BINARY;
1524 exType = DEL_LVALUE(d->d_AliasDecl.ed_Type);
1525 dassert_decl(d, d->d_AliasDecl.ed_AssExp != NULL);
1527 * NOTE: exLhs must be NULL if exp is
1528 * unresolved. exp tree duplications
1529 * do not duplicate the alias's exLHS
1530 * even though UNARY is set.
1532 dassert_exp(exp, exRhs->ex_Lhs == NULL);
1533 exRhs->ex_Flags |= EXF_ALIAS | EXF_UNARY;
1534 exRhs->ex_Lhs = DupExp(sg2,
1535 d->d_AliasDecl.ed_AssExp);
1536 exRhs->ex_Lhs = resolveExp(isg, sg2,
1539 flags | RESOLVE_AUTOCAST);
1541 case DOP_ARGS_STORAGE:
1542 case DOP_STACK_STORAGE:
1543 case DOP_GLOBAL_STORAGE:
1544 case DOP_GROUP_STORAGE:
1546 * Set type. The Rhs is a STRUCT_ID
1547 * and does not require a type to be
1550 * Return type is always an LVALUE,
1551 * parent may adjust.
1553 exType = ADD_LVALUE(d->d_StorDecl.ed_Type);
1557 * XXX make sure this is only used
1558 * in the lhs of a structural
1561 * XXX what if we went through a
1562 * TY_RETO type? This type will
1565 * collapse the exp node.
1567 exType = d->d_TypedefDecl.ed_Type;
1569 exFlags &= ~EXF_BINARY;
1573 * Do not collapse an import, we
1574 * require more resolution. e.g.
1575 * import.<blah> will be collapsed,
1576 * but 'import' cannot be.
1578 if (exFlags & EXF_REQ_TYPE) {
1581 &d->d_ImportDecl.ed_SemGroup->sg_ClassList,
1582 d->d_ImportDecl.ed_SemGroup,
1584 exFlags |= EXF_RET_TYPE;
1590 * Do not collapse a class, we require
1591 * more resolution. e.g. class.<blah>
1592 * will be collapsed, but 'class'
1595 if (exFlags & EXF_REQ_TYPE) {
1598 &d->d_ClassDecl.ed_SemGroup->sg_ClassList,
1599 d->d_ClassDecl.ed_Super,
1600 d->d_ClassDecl.ed_SemGroup,
1602 exFlags |= EXF_RET_TYPE;
1607 dassert_exp(exp, 0);
1610 if (d->d_Op == DOP_PROC) {
1611 if (d->d_ScopeFlags & SCOPE_PURE)
1613 } else if (exType->ty_SQFlags & SF_CONST) {
1617 } else if ((s = StrTableSpecial(id)) &
1618 SPECIALF_SEMGROUP) {
1620 * Identifier not found, check for a special
1623 exRhs->ex_Token = TOK_SEMGRP_ID;
1624 exRhs->ex_Int32 = s;
1629 dassert(type->ty_Op == TY_PTRTO ||
1630 type->ty_Op == TY_REFTO ||
1631 type->ty_Op == TY_CPTRTO);
1632 /* NULL is not an lvalue */
1633 exType = DEL_LVALUE(type);
1634 exFlags |= EXF_NULL;
1637 dassert(type->ty_Op != TY_PTRTO &&
1638 type->ty_Op != TY_REFTO &&
1639 type->ty_Op != TY_CPTRTO);
1640 exType = &Int32Type;
1644 * typeof(self.__data[]) vs
1645 * (cast)self.__data[]
1647 dassert(type->ty_Op != TY_PTRTO &&
1648 type->ty_Op != TY_REFTO &&
1649 type->ty_Op != TY_CPTRTO);
1650 dassert(exFlags & EXF_REQ_ARRAY);
1651 exFlags |= EXF_RET_ARRAY;
1652 if (exFlags & EXF_REQ_TYPE) {
1653 exFlags |= EXF_RET_TYPE;
1654 exType = &DynamicLValueType;
1659 * dynamic data must be cast
1661 dassert_exp(exp, 0);
1662 exType = &DynamicLValueType;
1665 case SPECIAL_VAR_COUNT:
1666 dassert(type->ty_Op != TY_PTRTO &&
1667 type->ty_Op != TY_REFTO &&
1668 type->ty_Op != TY_CPTRTO);
1669 exType = &Int32Type;
1671 case SPECIAL_VAR_DATA:
1673 * typeof(self.__vardata[]) vs
1674 * (cast)self.__vardata[]
1676 dassert(type->ty_Op != TY_PTRTO &&
1677 type->ty_Op != TY_REFTO &&
1678 type->ty_Op != TY_CPTRTO);
1679 dassert(exFlags & EXF_REQ_ARRAY);
1680 exFlags |= EXF_RET_ARRAY;
1681 if (exFlags & EXF_REQ_TYPE) {
1682 exFlags |= EXF_RET_TYPE;
1683 exType = &DynamicLValueType;
1688 * dynamic data must be cast
1690 dassert_exp(exp, 0);
1691 exType = &DynamicLValueType;
1694 case SPECIAL_TYPEID:
1695 exType = &Int32Type;
1697 case SPECIAL_TYPESTR:
1701 dassert_exp(exRhs, 0);
1706 * This is nasty, I admit. If we have a
1707 * pointer or reference type try again.
1710 if (type->ty_Op == TY_PTRTO) {
1711 type = type->ty_PtrType.et_Type;
1715 if (type->ty_Op == TY_REFTO) {
1716 type = type->ty_RefType.et_Type;
1720 if (type->ty_Op == TY_CPTRTO) {
1721 type = type->ty_CPtrType.et_Type;
1725 ExpPrintError(exRhs, eno);
1730 dassert_exp(exp, exType != NULL);
1734 * NOTE: unresolved identifiers should not have alias
1735 * expression sub-tree duplications attached to them.
1738 dassert_exp(exp, exLhs == NULL);
1742 * NOTE: LVALUE/RVALUE for elements and return type depends
1743 * on the operator. Operator functions normally
1744 * self-optimize the cases at run-time.
1747 saveExpCopy(©, exp);
1748 exp = resolveExpOper(isg, sg, exp, itype,
1749 flags & ~RESOLVE_AUTOCAST);
1750 loadExpCopy(©, exp);
1754 * Indirect through an expression.
1756 * Return type is typically an LVALUE (if representing
1757 * storage). Exp parent might turn it off so run-time
1758 * must test. Lhs may or may not be.
1763 exLhs = resolveExp(isg, sg, exLhs, NULL,
1764 flags & ~RESOLVE_AUTOCAST);
1765 type = exLhs->ex_Type;
1767 switch(type->ty_Op) {
1769 if ((exFlags & EXF_INDREF) == 0) {
1770 fprintf(stderr, "You cannot use '*' on a reference type\n");
1771 dassert_exp(exLhs, 0);
1773 exType = ADD_LVALUE(type->ty_RefType.et_Type);
1776 exType = ADD_LVALUE(type->ty_PtrType.et_Type);
1779 exType = ADD_LVALUE(type->ty_CPtrType.et_Type);
1782 dassert_exp(exLhs, 0);
1789 * Take the address of an (LVALUE) expression. Returns an
1790 * RVALUE. Allow for a short-cut optimization which replaces
1791 * the TOK_ADDR sequence with its argument in the &ary[n]
1798 * note: hint must 'always happen' since we may be
1799 * modifying an expression that will later be Dup'd.
1801 exLhs->ex_Flags |= EXF_REQ_ADDROF;
1802 exLhs->ex_Flags |= EXF_ADDRUSED;
1803 exLhs = resolveExp(isg, sg, exLhs, NULL,
1804 flags & ~RESOLVE_AUTOCAST);
1805 if (exLhs->ex_Flags & EXF_RET_ADDROF) {
1807 loadExpCopy(©, exp);
1809 type = exLhs->ex_Type;
1811 type->ty_SQFlags & SF_LVALUE);
1812 exType = RESOLVETYPE(TypeToPtrType(type));
1813 /* DEL_LVALUE() not needed here */
1819 * Array index, takes an RVALUE, returns an LVALUE.
1821 * Note: we have to convert the special __data[exp] case.
1823 * Note: ex_Flags hints must 'always happen' since we may be
1824 * modifying an expression that will later be Dup'd.
1826 exRhs = resolveExp(isg, sg, exRhs, NULL,
1827 flags & ~RESOLVE_AUTOCAST);
1828 exLhs->ex_Flags |= EXF_REQ_ARRAY | (exFlags & EXF_REQ_TYPE);
1829 exLhs->ex_Flags |= EXF_ADDRUSED;
1830 exLhs->ex_AuxExp = exRhs;
1831 exLhs = resolveExp(isg, sg, exLhs, itype,
1832 flags & ~RESOLVE_AUTOCAST);
1834 if (MatchType(&IntegralType, exRhs->ex_Type) <= SG_COMPAT_PART) {
1835 ExpPrintError(exRhs, TOK_ERR_EXPECTED_INTEGRAL_TYPE);
1836 dassert_exp(exp, 0);
1839 if (exLhs->ex_Flags & EXF_RET_ARRAY) {
1841 * __data and __vardata specials
1843 exp->ex_Token = TOK_ERR_EXP_REMOVED;
1845 } else if (exFlags & EXF_REQ_ADDROF) {
1847 * &ary[i] optimization - allows us to create
1848 * a bounded pointer (returns an RVALUE).
1852 exFlags |= EXF_RET_ADDROF;
1854 dassert((exLhs->ex_Flags & EXF_RET_TYPE) == 0);
1856 exLhs->ex_AuxExp = NULL;
1857 type = exLhs->ex_Type;
1858 switch(type->ty_Op) {
1860 type = type->ty_AryType.et_Type;
1863 type = type->ty_CPtrType.et_Type;
1866 type = type->ty_PtrType.et_Type;
1869 /* Cannot take address of a reference type */
1870 dassert_exp(exp, 0);
1873 exType = RESOLVETYPE(TypeToPtrType(type));
1874 /* returns an RVALUE */
1877 * Unoptimized array lookup, returns an lvalue
1881 dassert((exLhs->ex_Flags & EXF_RET_TYPE) == 0);
1883 exLhs->ex_AuxExp = NULL;
1884 type = exLhs->ex_Type;
1885 switch(type->ty_Op) {
1887 type = type->ty_AryType.et_Type;
1890 type = type->ty_CPtrType.et_Type;
1893 type = type->ty_PtrType.et_Type;
1897 "Cannot index a reference type\n");
1898 dassert_exp(exp, 0);
1901 exType = ADD_LVALUE(type);
1902 /* returns an LVALUE */
1906 dassert_exp(exp, 0); /* XXX */
1911 * XXX we should return a bounded pointer here.
1914 exId = StrTableEscapeQuotedString(exId, strlen(exId), 1);
1915 ReplaceStrTable(&exp->ex_Id, exId);
1919 exFlags |= EXF_CONST;
1920 exType = &UInt8Type; /* XXX make wide? */
1921 exId = StrTableEscapeQuotedString(exId, strlen(exId), 0);
1922 dassert(StrTableLen(exId) == 1);
1923 ReplaceStrTable(&exp->ex_Id, exId);
1931 strtol(exp->ex_Id, &ptr, 0);
1944 size = (size & ~0xFFF) | 1;
1948 size = (size & ~0xFFF) | 2;
1952 size = (size & ~0xFFF) | 4;
1956 size = (size & ~0xFFF) | 8;
1960 size = (size & ~0xFFF) | 16;
1963 dassert_exp(exp, 0);
1972 exType = &Int16Type;
1975 exType = &Int32Type;
1978 exType = &Int64Type;
1981 exType = &Int128Type;
1984 exType = &UInt8Type;
1987 exType = &UInt16Type;
1990 exType = &UInt32Type;
1993 exType = &UInt64Type;
1996 exType = &UInt128Type;
1999 exType = &Int32Type;
2003 exFlags |= EXF_CONST;
2010 exType = &Float64Type;
2012 strtod(exp->ex_Id, &ptr);
2017 exType = &Float32Type;
2021 exType = &Float64Type;
2025 exType = &Float128Type;
2031 exFlags |= EXF_CONST;
2038 * The self identifier represents the current procedure's
2039 * arguments. A varargs procedure will actually be called
2040 * with an extended version of this type, but for resolution
2041 * purposes we can use this time.
2043 * This is an LVALUE to support things like self.new() XXX.
2045 exType = ADD_LVALUE(resolveArgsType(sg, flags));
2049 * The '$' identifier represents the current procedure's
2052 exType = ADD_LVALUE(resolveReturnType(sg, flags));
2057 * Lookup the identifier. The returned declaration could
2058 * represent a class, typedef, module, or storage, but for
2059 * this case we only allow storage or a constant. Since
2060 * we are starting from our own semantic group, visibility
2061 * is initially ALL (private, library, and public).
2063 * The identifier might represent something at a higher scoping
2064 * layer. For example, a nested procedure accessing a variable
2065 * in the parent procedure or a method procedure in a class
2066 * accessing an element of the object.
2068 * It is also possible for the current execution scoping layer
2069 * (sg) to have a secondary contextual layer from which global
2070 * constants can be accessed. This is typically set when
2071 * resolving procedure arguments for procedures called through
2072 * objects or types. Only type globals can be accesed via
2075 * This returns an LVALUE if the id represents storage.
2079 int eno = TOK_ERR_ID_NOT_FOUND;
2084 * Special case 'super'. XXX TY_REFTO
2086 * Make an in-place change to the expression
2087 * structure. 'super' is actually 'this' with the
2088 * EXF_SUPER flag set.
2090 if (exId == String_Super) {
2092 ReplaceStrTable(&exp->ex_Id, exId);
2093 exFlags |= EXF_SUPER;
2095 ary[0] = exp->ex_Id;
2098 exDecl = FindDeclPath(&exp->ex_LexRef, isg, sg,
2100 FDC_NULL, &exVisibility,
2102 if (exDecl == NULL) {
2103 exDecl = FindDeclPathAltContext(
2104 &exp->ex_LexRef, isg, sg,
2106 FDC_NULL, &exVisibility,
2109 if (exDecl == NULL) {
2110 ExpPrintError(exp, eno);
2111 dassert_exp(exp, 0);
2115 * Set by TOK_ADDR, possibly propagated down via
2118 if (exFlags & EXF_REQ_ADDROF)
2119 exDecl->d_MyGroup->sg_Flags |= SGF_ADDRUSED;
2122 * Try to delay resolving the procedure declaration
2123 * (which will resolve the procedure body). We cannot
2124 * delay the resolution if resolving a constant
2125 * that the resolver needs immediately.
2127 if (flags & RESOLVE_CONSTEXP) {
2128 resolveDecl(exDecl, flags);
2133 * Taking the address of content-locked storage is illegal.
2135 * If we are running through an LValueStor
2136 * UNLOCKED applies to it and not its contents.
2137 * Check to see if the contents are acceptable.
2139 if ((exFlags & EXF_REQ_ADDROF) &&
2140 (exDecl->d_Scope.s_Flags & SCOPE_UNLOCKED) == 0) {
2141 Type *type = exDecl->d_StorDecl.ed_Type;
2142 if ((type->ty_Flags & TF_HASLVPTR) &&
2143 type->ty_Op != TY_CLASS &&
2144 type->ty_Op != TY_ARYOF) {
2146 TOK_ERR_ILLEGAL_ADDRLOCKED);
2147 dassert_exp(exp, 0);
2151 switch(exDecl->d_Op) {
2152 case DOP_ARGS_STORAGE:
2153 case DOP_STACK_STORAGE:
2154 case DOP_GLOBAL_STORAGE:
2155 case DOP_GROUP_STORAGE:
2157 * Storage identifiers are lvalues.
2159 * Try to delay this step, giving the language more
2160 * flexibility in avoiding resolver loops from
2161 * interdependencies that can cause it to fail.
2163 * We can't delay this step when resolving an
2164 * expression that the resolver needs an actual
2165 * constant result for.
2167 exType = ADD_LVALUE(exDecl->d_StorDecl.ed_Type);
2168 if (exDecl->d_Op == DOP_STACK_STORAGE &&
2169 (exFlags & EXF_ADDRUSED)) {
2170 exDecl->d_Flags |= DF_ADDRUSED;
2172 if (exType->ty_SQFlags & SF_CONST)
2174 if (flags & RESOLVE_CONSTEXP) {
2175 Exp **asexpp = &exDecl->d_StorDecl.ed_AssExp;
2177 *asexpp = DupExp(sg, *asexpp);
2178 *asexpp = resolveExp(isg, sg, *asexpp,
2180 flags | RESOLVE_AUTOCAST);
2181 *asexpp = SetDupExp(sg, *asexpp);
2187 * Aliases are rvalues (even if they could be lvalues).
2189 exType = DEL_LVALUE(exDecl->d_AliasDecl.ed_Type);
2190 exFlags |= EXF_ALIAS | EXF_UNARY;
2193 * NOTE: exLhs must be NULL if exp is unresolved.
2194 * exp tree duplications do not duplicate
2195 * the alias's exLHS even though UNARY is set.
2197 dassert_exp(exp, exLhs == NULL);
2198 exLhs = DupExp(sg, exDecl->d_AliasDecl.ed_AssExp);
2199 exLhs = resolveExp(isg, sg, exLhs, exType,
2200 flags | RESOLVE_AUTOCAST);
2203 * Inherit EXF_NULL (NULL pointer special) through
2204 * the alias, otherwise it will not be assignable
2205 * to arbitrary pointers.
2207 exFlags |= exLhs->ex_Flags & EXF_NULL;
2212 * A procedural identifier.
2214 * Note: procedural pointers cannot be changed so
2215 * they are not lvalues.
2217 dassert_exp(exp, (exFlags & EXF_REQ_PROC));
2218 exType = exDecl->d_ProcDecl.ed_Type;
2219 if (exDecl->d_ScopeFlags & SCOPE_PURE)
2223 if (exFlags & EXF_REQ_TYPE) {
2224 exType = exDecl->d_TypedefDecl.ed_Type;
2225 exFlags |= EXF_RET_TYPE;
2228 dassert_exp(exp, 0);
2231 if (exFlags & EXF_REQ_TYPE) {
2234 &exDecl->d_ClassDecl.ed_SemGroup->sg_ClassList,
2235 exDecl->d_ClassDecl.ed_Super,
2236 exDecl->d_ClassDecl.ed_SemGroup,
2238 exFlags |= EXF_RET_TYPE;
2241 dassert_exp(exp, 0);
2244 if (exFlags & EXF_REQ_TYPE) {
2247 &exDecl->d_ImportDecl.ed_SemGroup->sg_ClassList,
2248 exDecl->d_ImportDecl.ed_SemGroup,
2250 exFlags |= EXF_RET_TYPE;
2253 dassert_exp(exp, 0);
2256 dassert_exp(exp, 0);
2261 * NOTE: BoolType global implies an rvalue.
2264 exLhs = resolveExp(isg, sg, exLhs, &BoolType,
2265 flags | RESOLVE_AUTOCAST);
2268 if (exFlags & EXF_REQ_TYPE) {
2269 exType = RESOLVETYPE(exType);
2270 exFlags |= EXF_RET_TYPE;
2272 dassert_exp(exp, 0);
2277 * User cast (or maybe the parser inserted it). Try to
2278 * resolve the expression with the requested type hint
2279 * but tell resolveExp() not to force the cast.
2281 * Then check the result. If resolveExp() was not able to
2282 * optimize the requested cast then resolve the cast.
2284 * If the types are compatible we still keep the TOK_CAST
2285 * node in place for the moment. XXX we really need to
2286 * formalized how ex_Type is set Similar vs Exact.
2288 * NOTE: Cast results are always an RVALUE. XXX validate here.
2291 if ((exFlags & EXF_PARSE_TYPE) == 0) {
2292 exRhs->ex_Flags |= EXF_REQ_TYPE;
2293 exRhs = resolveExp(isg, sg, exRhs, NULL,
2294 flags & ~RESOLVE_AUTOCAST);
2295 exType = exRhs->ex_Type;
2297 exLhs = resolveExp(isg, sg, exLhs, exType,
2298 flags & ~RESOLVE_AUTOCAST);
2299 if (SimilarType(exType, exLhs->ex_Type) == 0) {
2300 saveExpCopy(©, exp);
2301 exp = resolveExpCast(isg, sg, exLhs, exType, flags);
2302 loadExpCopy(©, exp);
2305 /* propagate NULL flag to allow cast to any pointer type */
2306 if (exLhs->ex_Flags & EXF_NULL)
2307 printf("LHS NULL\n");
2308 exp->ex_Flags |= exLhs->ex_Flags & EXF_NULL;
2313 * Calls require the RHS to be a compound expression
2314 * representing the procedure arguments.
2316 * XXX deal with pointer-to-function verses function
2317 * XXX the lhs must at the moment resolve to the procedure
2320 * In regards to procedure pointers, the declaration
2321 * will require a pointer to the procedure's statement
2322 * body. XXX this pointer can be the physical storage
2323 * associated with the lhs data but thus requires the
2324 * type to be a pointer. We do not support the 'C'
2325 * (*ptr_to_func)(...) form. You have to use ptr_to_func(...).
2329 Type *atype; /* type for alt context */
2330 SemGroup *save_asg; /* save old alt context */
2332 dassert_exp(exRhs, exRhs->ex_Token == TOK_COMPOUND);
2335 * Note: ex_Flags hints must 'always happen' since
2336 * we may be modifying an expression that will later
2339 exLhs->ex_Flags |= EXF_REQ_PROC;
2340 exLhs = resolveExp(isg, sg, exLhs, NULL,
2341 flags & ~RESOLVE_AUTOCAST);
2342 ltype = exLhs->ex_Type;
2344 if (ltype->ty_Op == TY_PTRTO)
2345 ltype = type->ty_PtrType.et_Type; /* XXX */
2348 dassert_exp(exLhs, exLhs->ex_Token == TOK_DECL ||
2349 exLhs->ex_Token == TOK_ID);
2351 dassert_exp(exLhs, ltype != NULL &&
2352 ltype->ty_Op == TY_PROC);
2353 dassert_exp(exLhs, exLhs->ex_Decl != NULL);
2354 dassert_exp(exRhs, exRhs->ex_Token == TOK_COMPOUND);
2357 * If the lhs type indicates a method procedure, then
2358 * it's lhs is the object we wish to pass as the
2359 * first argument to the method. We move the lhs lhs
2360 * exp. For a STRIND TY_PTRTO method call we
2361 * indirect the element and convert it to a TOK_DOT
2362 * lvalue argument of the underlying object.
2364 * A method call via a reference object is a very
2367 * Since the method called through an object winds up
2368 * being a method taylored for that object, and we
2369 * are calling through a reference to an object,
2370 * the actual method will be looked up at run time
2371 * and will match the object. Thus we can safely
2372 * indirect through the reference object for this
2373 * one case. Since (*ref_obj) is not normally
2374 * allowed this will be special-cased at
2377 * Note that this occurs before we evaluate the
2378 * compound expression on the right hand side. Also
2379 * note that since the resolver can be called multiple
2380 * times on a shared expression, we have to be
2381 * careful to shift the arguments around only once.
2383 if ((ltype->ty_SQFlags & SF_METHOD) &&
2384 (exRhs->ex_Flags & EXF_CALL_CONV) == 0
2388 exRhs->ex_Flags |= EXF_CALL_CONV;
2390 switch(exLhs->ex_Token) {
2391 case TOK_STRIND: /* indirect */
2392 obj = exLhs->ex_Lhs;
2393 if (methodProcThisIsPointer(ltype)) {
2395 } else if (obj->ex_Type->ty_Op ==
2397 Exp *nexp = AllocExp(NULL);
2400 nexp->ex_Token = TOK_PTRIND;
2401 nexp->ex_Type = ADD_LVALUE(obj->ex_Type->ty_PtrType.et_Type);
2402 nexp->ex_Flags |= EXF_RESOLVED |
2404 LexDupRef(&obj->ex_LexRef,
2406 exLhs->ex_Token = TOK_DOT;
2408 } else if (obj->ex_Type->ty_Op ==
2410 Exp *nexp = AllocExp(NULL);
2413 nexp->ex_Token = TOK_PTRIND;
2414 nexp->ex_Type = ADD_LVALUE(obj->ex_Type->ty_CPtrType.et_Type);
2415 nexp->ex_Flags |= EXF_RESOLVED |
2417 LexDupRef(&obj->ex_LexRef,
2419 exLhs->ex_Token = TOK_DOT;
2421 } else if (obj->ex_Type->ty_Op ==
2423 Exp *nexp = AllocExp(NULL);
2426 nexp->ex_Token = TOK_PTRIND;
2427 nexp->ex_Type = ADD_LVALUE(obj->ex_Type->ty_RefType.et_Type);
2428 nexp->ex_Flags |= EXF_RESOLVED |
2431 LexDupRef(&obj->ex_LexRef,
2435 dassert_exp(obj, 0);
2440 * Pass directly as an lvalue. If this
2441 * is a pointer or reference only the
2442 * builtin methods for the Pointer
2443 * class are possible. These methods
2444 * require a content-locked pointer.
2446 obj = exLhs->ex_Lhs;
2447 if (obj->ex_Type->ty_Op != TY_PTRTO &&
2448 obj->ex_Type->ty_Op != TY_REFTO) {
2452 if (obj->ex_Decl == NULL ||
2453 (obj->ex_Decl->d_Scope.s_Flags & SCOPE_UNLOCKED)) {
2454 exFlags |= EXF_UNLOCKEDMTH;
2458 dassert_exp(exp, 0);
2464 * Leave the lhs intact, but set the
2465 * duplication flag in case things get
2468 exLhs->ex_Lhs = SetDupExp(sg, exLhs->ex_Lhs);
2469 obj->ex_Next = exRhs->ex_Lhs;
2470 exRhs->ex_Lhs = obj;
2472 atype = obj->ex_Type;
2478 * Try to set an alternative search context during
2479 * resolution of the procedure arguments. This context
2480 * is only searched if an identifier cannot be found
2481 * through normal means so local variables and such
2482 * will override it as the programmer should expect.
2483 * Since the local semantic stack is under the
2484 * programmer's control, unexpected collisions should
2485 * either not occur or be easily fixed.
2488 switch(atype->ty_Op) {
2490 atype = atype->ty_PtrType.et_Type;
2493 atype = atype->ty_PtrType.et_Type;
2496 if (atype->ty_Op != TY_CLASS)
2500 save_asg = sg->sg_AltContext;
2501 sg->sg_AltContext = atype->ty_ClassType.et_SemGroup;
2507 * Resolve the right hand side, which are the
2508 * procedure arguments as a compound type. This
2509 * can get tricky. XXX
2511 * NOTE: We inherit the SF_LVALUE flag from the
2512 * return type. Parent might turn it off.
2514 /*d = exLhs->ex_Decl;*/
2515 exRhs = resolveExp(isg, sg, exRhs,
2516 ltype->ty_ProcType.et_ArgsType,
2517 flags | RESOLVE_AUTOCAST);
2518 exType = ltype->ty_ProcType.et_RetType;
2521 * Restore AltContext after resolving rhs.
2523 sg->sg_AltContext = save_asg;
2524 } else if ((exRhs->ex_Flags & (EXF_CONST |
2526 (exLhs->ex_Decl->d_ScopeFlags & SCOPE_PURE)) {
2528 * atype NULL (not method call, which requires
2529 * an object), arguments can become constants,
2530 * pure function, so result can become a
2533 exFlags |= EXF_PROBCONST;
2539 * (NOTE EARLY RETURN)
2541 * A compound expression should always be an RVALUE, but
2542 * might contain LVALUEs (XXX).
2545 exp = resolveCompoundExp(isg, sg, exp, itype, flags);
2550 * The caller must be able to handle a type return when
2553 dassert_exp(exp, exFlags & EXF_REQ_TYPE);
2558 * If an expression was supplied, convert it to a type.
2560 * NOTE: ex_Flags hints must 'always happen' since we may be
2561 * modifying an expression that will later be Dup'd.
2564 if ((exFlags & EXF_RET_TYPE) == 0) {
2565 dassert(exLhs != NULL);
2566 exLhs->ex_Flags |= EXF_REQ_TYPE;
2567 exLhs = resolveExp(isg, sg, exLhs, NULL,
2568 flags & ~RESOLVE_AUTOCAST);
2569 exType = exLhs->ex_Type;
2571 /* do not clear EXF_UNARY, messes up tmp exp storage */
2572 /* exFlags &= ~EXF_UNARY; */
2574 exFlags |= EXF_RET_TYPE;
2575 /* XXX delete the lhs */
2577 exType = RESOLVETYPE(exType);
2581 exId = StrTableInt(exType->ty_Bytes);
2582 exp->ex_Token = exToken = TOK_INTEGER;
2584 exFlags &= ~EXF_RET_TYPE;
2585 exFlags |= EXF_CONST;
2588 dassert_exp(exp, exType->ty_Op == TY_ARYOF);
2589 if (exType->ty_AryType.et_Type->ty_Bytes) {
2590 exId = StrTableInt(exType->ty_Bytes /
2591 exType->ty_AryType.et_Type->ty_Bytes);
2593 exId = StrTableInt(0);
2595 exp->ex_Token = exToken = TOK_INTEGER;
2597 exFlags &= ~EXF_RET_TYPE;
2598 exFlags |= EXF_CONST;
2601 /* type is returned */
2606 dassert_exp(exp, 0);
2611 * Resolve the type and cast-to-type.
2614 exType = RESOLVETYPE(exType);
2615 /* XXX exType was ex_Type */
2618 * Special-case compound compatibility issues so the
2619 * interpreter and code generator do not have to deal with
2622 if ((flags & RESOLVE_AUTOCAST) && itype &&
2623 itype->ty_Op == TY_COMPOUND &&
2624 exType->ty_Op != TY_COMPOUND) {
2626 * The expression parser might have optimized-out
2627 * the TOK_COMPOUND wrapper around single-element
2628 * parenthesized expressions. Add it back in if
2629 * the cast target expects a compound expression.
2631 * XXX Currently hack a SetDupExp() to avoid
2632 * re-resolving the already-resolved component.
2635 saveExpCopy(©, exp);
2636 exp = ExpToCompoundExp(exp, TOK_COMPOUND);
2637 exp = resolveCompoundExp(isg, sg, exp, itype, flags);
2638 loadExpCopy(©, exp);
2640 if ((flags & RESOLVE_AUTOCAST) && itype &&
2641 itype->ty_Op == TY_CLASS &&
2642 exType->ty_Op == TY_CLASS &&
2643 itype != &VoidType &&
2644 (itype->ty_Flags & (TF_ISBOOL | TF_ISINTEGER |
2645 TF_ISFLOATING)) == 0 &&
2646 (exType->ty_Flags & (TF_ISBOOL | TF_ISINTEGER |
2649 * The expression parser might have optimized-out
2650 * the TOK_COMPOUND wrapper around single-element
2651 * parenthesized expressions used in a class iterator
2652 * (in an assignment). Add it back in if the
2653 * itype is a non-core class and exType is a core
2656 * XXX Currently hack a SetDupExp() to avoid
2657 * re-resolving the already-resolved component.
2660 saveExpCopy(©, exp);
2661 exp = ExpToCompoundExp(exp, TOK_COMPOUND);
2662 exp = resolveCompoundExp(isg, sg, exp, itype, flags);
2663 loadExpCopy(©, exp);
2667 * If the type hint did not succeed we may have to cast the
2668 * expression to the requested type. Note that if the itype
2669 * was set as part of an array optimization request which could
2670 * not be handled, we must ignore itype.
2672 * Note that SimilarType() will allow exp->ex_Type to be a
2673 * var-args TY_ARGS, and since the original Rhs of a call
2674 * is set to the procedure arguments type, VarType.et_Type
2675 * should match exactly.
2678 (exFlags & (EXF_REQ_ARRAY|EXF_RET_ARRAY)) != EXF_REQ_ARRAY
2680 if ((itype->ty_Flags & TF_RESOLVED) == 0)
2681 itype = RESOLVETYPE(itype);
2682 if ((itype->ty_SQFlags & SF_LVALUE) &&
2683 (exType->ty_SQFlags & SF_LVALUE) == 0
2686 fprintf(stderr, "Exp must be an lvalue here\n");
2687 dassert_exp(exp, 0);
2689 if (!SimilarType(itype, exType) &&
2690 (flags & RESOLVE_AUTOCAST)) {
2691 if (exp->ex_Flags & EXF_DUPEXP) {
2692 Exp *nexp = AllocExp(NULL);
2695 LexDupRef(&exp->ex_LexRef,
2698 exFlags &= ~EXF_DUPEXP;
2699 /*exp = DupExp(sg, exp);*/
2701 exFlags |= EXF_RESOLVED;
2702 exp = dupExpCopy(©, exp);
2703 exp = resolveExpCast(isg, sg, exp, itype,
2705 loadExpCopy(©, exp);
2711 * Generic constant evaluation flag. Note that EXF_PROBCONST
2712 * could also be set above (TOK_CALL).
2715 (exLhs == NULL || (exLhs->ex_Flags & (EXF_CONST|EXF_PROBCONST))) &&
2716 (exRhs == NULL || (exRhs->ex_Flags & (EXF_CONST|EXF_PROBCONST)))) {
2717 exFlags |= EXF_PROBCONST;
2720 exFlags |= EXF_RESOLVED;
2721 exp = dupExpCopy(©, exp);
2726 * Resolve an expression for which the resolver needs the result
2730 resolveConstExp(SemGroup *isg, SemGroup *sg, Exp *exp, int flags)
2735 flags &= ~RESOLVE_AUTOCAST;
2737 if ((exp->ex_Flags & EXF_RESOLVED) == 0)
2738 exp = resolveExp(isg, sg, exp, NULL, flags | RESOLVE_CONSTEXP);
2739 if ((exp->ex_Flags & (EXF_CONST | EXF_PROBCONST)) == 0) {
2740 ExpPrintError(exp, TOK_ERR_EXPECTED_INTEGRER_CONST);
2741 dassert_exp(exp, 0);
2745 if (exp->ex_Token != TOK_ID)
2748 if ((d->d_StorDecl.ed_Type->ty_SQFlags & SF_CONST) == 0)
2752 case DOP_ARGS_STORAGE:
2753 case DOP_STACK_STORAGE:
2754 case DOP_GLOBAL_STORAGE:
2755 case DOP_GROUP_STORAGE:
2756 exp = d->d_StorDecl.ed_AssExp;
2764 * Special interpreter execution to resolve the expression.
2769 int64_t tmpbuf[128];
2770 float128_t tmpflt[64];
2773 bzero(&ct, sizeof(ct));
2774 ct.ct_Flags |= CTF_RESOLVING;
2775 if (sg->sg_TmpBytes < (runesize_t)sizeof(u.tmpbuf) &&
2776 sg->sg_TmpAlignMask < (runesize_t)sizeof(float128_t))
2777 ct.ct_TmpData = (char *)u.tmpbuf;
2779 posix_memalign((void *)&ct.ct_TmpData,
2780 sg->sg_TmpAlignMask + 1,
2783 ct.ct_TmpBytes = sg->sg_TmpBytes;
2784 ct.ct_CtxRefStor.rs_Refs = 1;
2785 (void)exp->ex_Run(&ct, exp);
2787 if ((exp->ex_Flags & EXF_CONST) == 0) {
2788 ExpPrintError(exp, TOK_ERR_EXPECTED_INTEGRER_CONST);
2789 dassert_exp(exp, 0);
2791 if (ct.ct_TmpData != (char *)u.tmpbuf)
2792 free(ct.ct_TmpData);
2798 resolveConstExpBool(SemGroup *isg, SemGroup *sg, Exp *exp, int flags,
2801 runesize_t tmpbytes;
2805 flags &= ~RESOLVE_AUTOCAST;
2808 if ((exp->ex_Flags & EXF_RESOLVED) == 0) {
2809 exp = resolveExp(isg, sg, exp, NULL, flags | RESOLVE_CONSTEXP);
2813 * [re]-resolve the storage from 0 so we can execute the expression.
2815 oflags = exp->ex_Flags;
2816 ooffset = exp->ex_TmpOffset;
2817 resolveStorageExp(exp, &tmpbytes);
2818 if ((exp->ex_Flags & (EXF_CONST | EXF_PROBCONST)) == 0) {
2819 ExpPrintError(exp, TOK_ERR_EXPECTED_INTEGRER_CONST);
2820 dassert_exp(exp, 0);
2824 * Special interpreter execution to resolve the expression.
2830 int64_t tmpbuf[128];
2831 float128_t tmpflt[64];
2834 bzero(&ct, sizeof(ct));
2835 ct.ct_Flags |= CTF_RESOLVING;
2840 if (tmpbytes < (runesize_t)sizeof(u.tmpbuf))
2841 ct.ct_TmpData = (char *)u.tmpbuf;
2843 posix_memalign((void *)&ct.ct_TmpData, 16, tmpbytes);
2844 ct.ct_TmpBytes = tmpbytes;
2845 ct.ct_CtxRefStor.rs_Refs = 1;
2846 rts = exp->ex_Run(&ct, exp).data;
2848 if ((exp->ex_Flags & EXF_CONST) == 0) {
2849 ExpPrintError(exp, TOK_ERR_EXPECTED_INTEGRER_CONST);
2850 dassert_exp(exp, 0);
2852 ts->ts_Bool = rts->ts_Bool;
2853 if (ct.ct_TmpData != (char *)u.tmpbuf)
2854 free(ct.ct_TmpData);
2858 * exp is now a constant, restore the original ex_TmpOffset
2859 * for normal execution/operation (the storage may be needed for
2862 if (oflags & EXF_TMPRESOLVED) {
2863 exp->ex_TmpOffset = ooffset;
2864 resolveStorageExp(exp, &tmpbytes);
2866 exp->ex_TmpOffset = -1;
2873 * Extract constant from already-constant-resolved expression.
2874 * resolveConstExp() must have previously been called on exp.
2876 * Expression must have already been constant-optimized, meaning
2877 * that we should be able to execute it without a context to access
2878 * the cached results in exp->u.
2882 resolveGetConstExpInt64(Exp *exp)
2887 dassert_exp(exp, exp->ex_Token == TOK_INTEGER ||
2888 (exp->ex_Flags & EXF_CONST));
2889 data = exp->ex_Run(NULL, exp);
2891 if (exp->ex_Type->ty_Flags & TF_ISUNSIGNED) {
2892 switch(exp->ex_Type->ty_Bytes) {
2894 value = *(uint8_t *)data.data;
2897 value = *(uint16_t *)data.data;
2900 value = *(uint32_t *)data.data;
2903 value = *(uint64_t *)data.data;
2907 dassert_exp(exp, 0);
2911 switch(exp->ex_Type->ty_Bytes) {
2913 value = *(int8_t *)data.data;
2916 value = *(int16_t *)data.data;
2919 value = *(int32_t *)data.data;
2922 value = *(int64_t *)data.data;
2926 dassert_exp(exp, 0);
2934 * resolveCompoundExp() - resolve a compound expression (called from
2935 * resolveExp() and resolveExpOper()).
2937 * Resolve a compound expression. Compound expressions require
2938 * a compound type to normalize against. This will work for
2939 * direct assignments, return values, casts, and procedure arguments
2942 * NOTE: We can't use itype if EXF_REQ_ARRAY is specified because
2943 * its hinting for the array optimization case, which we cannot do.
2945 * Compound expressions may be used in conjuction with types
2946 * reprsenting classes, compound types, and procedure arguments. The
2947 * compound expression may contain subclasses of the superclasses expected
2948 * by itype. This is only allowed if the procedure's body has not yet been
2949 * generated (for example, a method call in a subclass).
2951 * Partially resolved operators are typically converted into procedure calls
2952 * and method calls are also partially resolved, so some elements may already
2955 * XXX named initialization, missing elements (structural
2956 * initialization), and so forth needs to be dealt with.
2959 resolveCompoundExp(SemGroup *isg, SemGroup *sg, Exp *exp,
2960 Type *itype, int flags)
2970 flags &= ~RESOLVE_AUTOCAST; /* not applicable to this function */
2973 * Expression dup()ing
2975 if (exp->ex_Flags & EXF_DUPEXP) {
2977 static int count; fprintf(stderr, "DUPEXPC %d\n", ++count);
2979 exp = DupExp(sg, exp);
2982 if (itype && (exp->ex_Flags & EXF_REQ_ARRAY) == 0)
2983 exp->ex_Type = itype;
2986 * If we don't have a SemGroup to normalize against, XXX how should
2987 * we normalize the compound expression?
2989 if (exp->ex_Type == NULL) {
2990 dassert_exp(exp, 0);
2994 * Normalize the compound expression based on the
2995 * argument types expected by the procedure. We have
2996 * to resolve the type before we start the scan in order
2997 * to ensure that d_Offset is properly assigned.
2999 * Use the declarations found in the compound type
3000 * semantic group to coerce the procedure arguments to
3001 * generate the correct compound type. Note that resolveExp()
3002 * recursion must still use the SemGroup that was passed to us.
3004 * XXX deal with defaults and pre-resolved arguments. XXX
3006 type = exp->ex_Type = RESOLVETYPE(exp->ex_Type);
3008 switch(type->ty_Op) {
3010 sg2 = type->ty_ArgsType.et_SemGroup;
3013 sg2 = type->ty_VarType.et_SemGroup;
3016 sg2 = type->ty_CompType.et_SemGroup;
3019 sg2 = type->ty_ClassType.et_SemGroup;
3022 dassert_exp(exp, 0);
3023 sg2 = NULL; /* NOT REACHED */
3026 pscan = &exp->ex_Lhs;
3029 * Scan the compound expression and match it up against the compound
3032 d = RUNE_FIRST(&sg2->sg_DeclList);
3033 while ((scan = *pscan) != NULL) {
3034 if (scan->ex_ArgId != NULL) {
3036 * Named argument, find it
3038 * (Overloading not allowed)
3040 int eno = TOK_ERR_ID_NOT_FOUND;
3043 nd = FindDeclId(sg2, scan->ex_ArgId, &eno);
3045 ExpPrintError(scan, eno);
3051 * XXX for now, punt on setting EXF_PROBCONST
3052 * if the named argument skips a declaration.
3054 if (nd != d && nd != RUNE_NEXT(d, d_Node)) {
3060 * Unnamed argument, run through sequentially. Skip
3061 * any non-storage or global storage.
3063 while (d && d->d_Op != DOP_ARGS_STORAGE &&
3064 d->d_Op != DOP_STACK_STORAGE &&
3065 d->d_Op != DOP_GROUP_STORAGE
3067 d = RUNE_NEXT(d, d_Node);
3071 * Ran out of storage declarations. If this is a
3072 * var-args SemGroup then we actually create a new
3073 * SemGroup (and eventually a new type) to represent
3076 * We then extend the varargs SemGroup. This isn't
3081 (sg2->sg_Flags & SGF_VARARGS)) {
3082 sg2 = DupSemGroup(sg2->sg_Parent, NULL, sg2, 1);
3084 if (resolveSemGroup1(sg3, flags) &&
3085 resolveSemGroup2(sg3, flags))
3086 resolveSemGroup3(sg3, flags);
3093 "Too many arguments in "
3095 dassert_exp(scan, 0);
3101 * Unlink the expression from the compound list temporarily
3102 * so we can safely resolve it. Either cast the expression
3103 * to the compound element, or create a compound element
3104 * (e.g. varargs call) to match the expression.
3106 * Due to the resolver moving things around, the elements of
3107 * a compound expression are sometimes resolved multiple times.
3109 *pscan = scan->ex_Next;
3110 scan->ex_Next = NULL;
3112 Type *stype = d->d_StorDecl.ed_Type;
3118 if (SimilarType(stype, &PointerType) &&
3119 (stype->ty_SQFlags & SF_LVALUE) == SF_LVALUE
3122 sflags = flags & ~RESOLVE_AUTOCAST;
3124 sflags = flags | RESOLVE_AUTOCAST;
3126 if (d->d_ScopeFlags & SCOPE_LVALUE)
3127 scan->ex_Flags |= EXF_ADDRUSED;
3129 if ((scan->ex_Flags & EXF_RESOLVED) == 0) {
3130 scan = resolveExp(isg, sg, scan,
3134 * Since we have already resolved the
3135 * expression we need to do the same sanity
3136 * checking that it would do to cast.
3139 (stype->ty_SQFlags & SF_LVALUE) == 0 ||
3140 (scan->ex_Type->ty_SQFlags & SF_LVALUE));
3141 if (!SimilarType(stype, scan->ex_Type)) {
3142 scan = resolveExpCast(isg, sg, scan,
3147 Scope tscope = INIT_SCOPE(0);
3149 if ((scan->ex_Flags & EXF_RESOLVED) == 0)
3150 scan = resolveExp(isg, sg, scan, NULL,
3151 flags & ~RESOLVE_AUTOCAST);
3152 dassert(varargs != 0);
3153 d = AllocDeclaration(sg2, DOP_ARGS_STORAGE, &tscope);
3154 d->d_StorDecl.ed_Type = DEL_LVALUE(scan->ex_Type);
3156 d->d_Bytes = scan->ex_Type->ty_Bytes;
3157 d->d_AlignMask = scan->ex_Type->ty_AlignMask;
3160 * __align(%d) scope qualifier, override the type's
3163 if ((d->d_Scope.s_Flags & SCOPE_ALIGN) &&
3164 d->d_Scope.s_AlignOverride) {
3165 d->d_AlignMask = d->d_Scope.s_AlignOverride - 1;
3169 sg2->sg_Bytes = (sg2->sg_Bytes + d->d_AlignMask) &
3172 d->d_Offset = sg2->sg_Bytes;
3174 sg2->sg_Bytes += d->d_Bytes;
3175 if (sg2->sg_AlignMask < d->d_AlignMask)
3176 sg2->sg_AlignMask = d->d_AlignMask;
3181 * Relink and check if constant
3183 scan->ex_Next = *pscan;
3185 if ((scan->ex_Flags & (EXF_CONST | EXF_PROBCONST)) == 0)
3189 * If the declaration requires an LVALUE, assert that
3190 * we have an lvalue. Otherwise set the direct-store
3191 * request (also see InterpCompoundExp).
3193 if (d->d_ScopeFlags & SCOPE_LVALUE) {
3194 if ((scan->ex_Type->ty_SQFlags & SF_LVALUE) == 0)
3195 fprintf(stderr, "argument must be an lvalue\n");
3197 scan->ex_Type->ty_SQFlags & SF_LVALUE);
3203 d = RUNE_NEXT(d, d_Node);
3204 pscan = &scan->ex_Next;
3208 * Make sure the caller knows its a var-args function even if
3209 * we didn't supply any additional args. Otherwise the backend
3210 * may not generate the correct form for calls to the target.
3213 (sg2->sg_Flags & SGF_VARARGS)) {
3214 sg2 = DupSemGroup(sg2->sg_Parent, NULL, sg2, 1);
3219 * Resolve the varargs sg2 after building it.
3222 if (resolveSemGroup1(sg2, flags) &&
3223 resolveSemGroup2(sg2, flags)) {
3224 resolveSemGroup3(sg2, flags);
3226 /* resolveStorageSemGroupAlign(sg2); */
3227 /*resolveStorageSemGroup(sg2, 0, 0);*/
3231 * If we made a var-args call, adjust the expression's type
3234 dassert(type->ty_Op == TY_ARGS);
3235 exp->ex_Type = RESOLVETYPE(TypeToVarType(type, sg2));
3238 exp->ex_Flags |= EXF_PROBCONST;
3240 exp->ex_Flags |= EXF_RESOLVED;
3245 * resolveExpCast() - Cast the expression to the specified type and return
3246 * the cast expression.
3248 * Note that expression nodes depend on their ex_Type being correct,
3249 * and also expressions may be shared, so be careful not to modify the
3250 * ex_Type (or anything else) in the existing expression.
3252 * This code is somewhat different then resolveExpOper() and friends.
3253 * The Exp argument has already been resolved so do not resolve it
3254 * again, and the cast type already has SF_LVALUE set or cleared as
3255 * appropriate (had better be cleared!)
3257 * As with operators we have to locate the cast declaration matching
3258 * the cast we want to do.
3261 resolveExpCast(SemGroup *isg, SemGroup *sg, Exp *exp, Type *ltype, int flags)
3266 flags &= ~RESOLVE_AUTOCAST; /* not applicable to this function */
3268 rtype = exp->ex_Type;
3269 dassert(rtype && ltype);
3271 * XXX attempt to cast from subclass to superclass?
3275 * XXX look in our local semantic hierarchy for a compatible cast ?
3279 * Look in the right hand (source) type for the cast
3281 d = findCast(rtype, ltype, rtype, flags);
3284 * If that fails then look in the left hand (destination) type for
3288 d = findCast(ltype, ltype, rtype, flags);
3291 if (d == NULL && (rtype->ty_Op == TY_PTRTO ||
3292 rtype->ty_Op == TY_REFTO ||
3293 rtype->ty_Op == TY_CPTRTO)) {
3294 d = findCast(&PointerType, ltype, rtype, flags);
3300 * We could not find a specific cast operator. There are
3301 * some inherent casts that we can do. We run through these
3302 * in attempt to come up with matching types.
3304 if (ltype->ty_Op != rtype->ty_Op &&
3305 (ltype->ty_Op == TY_PTRTO || ltype->ty_Op == TY_CPTRTO ||
3306 ltype->ty_Op == TY_ARYOF) &&
3307 (rtype->ty_Op == TY_PTRTO || rtype->ty_Op == TY_CPTRTO ||
3308 rtype->ty_Op == TY_ARYOF)) {
3310 * Pointers, C pointers, or arrays can be cast to
3311 * pointers, C pointers, or arrays of the same type.
3313 * Cast the right hand type to an equivalent
3314 * pointer/cpointer/array of the right hand type
3315 * and re-resolve the cast.
3317 exp = ExpToCastExp(exp,
3318 RESOLVETYPE(ChangeType(rtype, ltype->ty_Op)));
3319 return(resolveExpCast(isg, sg, exp, ltype, flags));
3320 } else if (MatchType(ltype, rtype) <= SG_COMPAT_PART) {
3322 * If the types are compatible (casting rtype->ltype),
3323 * we can cast trivially.
3325 exp = ExpToCastExp(exp, ltype);
3326 } else if (MatchType(&NumericType, ltype) <= SG_COMPAT_PART &&
3327 MatchType(&NumericType, rtype) <= SG_COMPAT_PART) {
3329 * Casting from one numeric type to another must be
3330 * supported by the interpreter/compiler.
3332 exp = ExpToCastExp(exp, ltype);
3333 } else if (SimilarType(&VoidType, ltype)) {
3335 * Casting anything to void is allowed (throwing the
3336 * object away). E.g. statement-expressions.
3338 exp = ExpToCastExp(exp, ltype);
3339 } else if (SimilarType(&VoidPtrType, ltype)) {
3341 * Casting a pointer to a (void *) is trivial, but is
3342 * only allowed if the underlying structure does not
3343 * contain any pointers.
3345 * NOTE: Generally only used when a pointer is being
3346 * cast to an integer. Rune does not allow
3347 * casting back to other pointer types.
3349 * XXX validate integral # of objects fit in pointer
3352 dassert_exp(exp, (rtype->ty_PtrType.et_Type->ty_Flags & TF_HASLVPTR) == 0);
3353 exp = ExpToCastExp(exp, ltype);
3354 } else if (SimilarType(&VoidRefType, ltype)) {
3356 * Casting a pointer to a (void @) is trivial.
3358 * NOTE: Generally only used when a pointer is being
3359 * cast to an integer. Rune does not allow
3360 * casting back to other pointer types.
3362 * XXX validate integral # of objects fit in pointer
3365 dassert_exp(exp, (rtype->ty_RefType.et_Type->ty_Flags & TF_HASLVPTR) == 0);
3366 exp = ExpToCastExp(exp, ltype);
3367 } else if (SimilarType(rtype, &VoidPtrType)) {
3369 * Casting from a void pointer may not be trivial
3370 * but we leave it up to the interpreter/compiler.
3372 * Only allow if the target does not contain any
3373 * pointers or if the right-hand-side is NULL.
3375 * XXX validate integral # of objects fit in pointer
3378 switch(ltype->ty_Op) {
3380 if ((exp->ex_Flags & EXF_NULL) == 0)
3381 dassert_exp(exp, (ltype->ty_RefType.et_Type->ty_Flags & TF_HASLVPTR) == 0);
3384 if ((exp->ex_Flags & EXF_NULL) == 0)
3385 dassert_exp(exp, (ltype->ty_PtrType.et_Type->ty_Flags & TF_HASLVPTR) == 0);
3390 exp = ExpToCastExp(exp, ltype);
3391 } else if (SimilarType(rtype, &CVoidPtrType)) {
3392 switch(ltype->ty_Op) {
3394 if ((exp->ex_Flags & EXF_NULL) == 0)
3395 dassert_exp(exp, (ltype->ty_PtrType.et_Type->ty_Flags & TF_HASLVPTR) == 0);
3400 } else if (SimilarType(ltype, &BoolType) &&
3401 (rtype->ty_Op == TY_PTRTO ||
3402 rtype->ty_Op == TY_REFTO ||
3403 rtype->ty_Op == TY_CPTRTO)) {
3405 * Any pointer can be cast to a boolean, which
3406 * tests against NULL.
3408 exp = ExpToCastExp(exp, ltype);
3409 } else if (ltype->ty_Op == rtype->ty_Op &&
3410 (ltype->ty_Op == TY_PTRTO ||
3411 ltype->ty_Op == TY_CPTRTO ||
3412 ltype->ty_Op == TY_ARYOF)) {
3414 * We allow casts of pointers to similar numeric
3415 * types if they are the same size, though this is
3416 * really rather a hack. This is mainly to handle
3417 * the signed<->unsigned cast case. XXX
3421 switch(ltype->ty_Op) {
3423 if (MatchType(&NumericType,
3424 ltype->ty_PtrType.et_Type) <=
3425 SG_COMPAT_SUBCLASS &&
3426 MatchType(&NumericType,
3427 rtype->ty_PtrType.et_Type) <=
3428 SG_COMPAT_SUBCLASS &&
3429 ltype->ty_Bytes == rtype->ty_Bytes
3431 exp = ExpToCastExp(exp, ltype);
3436 if (MatchType(&NumericType,
3437 ltype->ty_CPtrType.et_Type) <=
3438 SG_COMPAT_SUBCLASS &&
3439 MatchType(&NumericType,
3440 rtype->ty_CPtrType.et_Type) <=
3441 SG_COMPAT_SUBCLASS &&
3442 ltype->ty_Bytes == rtype->ty_Bytes
3444 exp = ExpToCastExp(exp, ltype);
3449 if (MatchType(&NumericType,
3450 ltype->ty_AryType.et_Type) <=
3451 SG_COMPAT_SUBCLASS &&
3452 MatchType(&NumericType,
3453 rtype->ty_AryType.et_Type) <=
3454 SG_COMPAT_SUBCLASS &&
3455 ltype->ty_Bytes == rtype->ty_Bytes
3457 exp = ExpToCastExp(exp, ltype);
3464 "Unable to resolve cast from pointers "
3465 "to dissimilar numeric types "
3467 TypeToStr(rtype, NULL),
3468 TypeToStr(ltype, NULL));
3469 dassert_exp(exp, 0);
3473 "Unable to resolve cast from %s to %s\n",
3474 TypeToStr(rtype, NULL),
3475 TypeToStr(ltype, NULL));
3476 dassert_exp(exp, 0);
3478 } else if (d->d_ScopeFlags & SCOPE_INTERNAL) {
3480 * We found a cast operator and it is an internal operator
3482 exp = ExpToCastExp(exp, ltype);
3486 * We found a cast operator and it is a Rune cast procedure. We
3487 * must convert the cast to a procedure call. If we want
3488 * resolveCompoundExp() to be able to generate a compatible
3489 * procedure (in a subclass) we have to tell it about the
3494 sexp = ExpToCompoundExp(exp, TOK_COMPOUND);
3495 if (d->d_ProcDecl.ed_ProcBody == NULL)
3497 sexp = resolveCompoundExp(isg, sg, sexp,
3498 d->d_ProcDecl.ed_Type->ty_ProcType.et_ArgsType,
3500 exp = AllocExp(NULL);
3501 exp->ex_Lhs = AllocExp(NULL);
3502 exp->ex_Lhs->ex_Token = TOK_DECL;
3503 exp->ex_Lhs->ex_Id = d->d_Id;
3504 exp->ex_Lhs->ex_Decl = d;
3505 exp->ex_Lhs->ex_Type = d->d_ProcDecl.ed_Type;
3506 exp->ex_Lhs->ex_Flags |= EXF_RESOLVED;
3508 exp->ex_Flags |= EXF_BINARY;
3509 exp->ex_Token = TOK_CALL;
3510 /* XXX use ltype or procedure's rettype? */
3511 exp->ex_Type = ltype;
3512 LexDupRef(&sexp->ex_LexRef, &exp->ex_LexRef);
3513 LexDupRef(&sexp->ex_LexRef, &exp->ex_Lhs->ex_LexRef);
3515 exp->ex_Flags |= EXF_RESOLVED;
3521 findCast(Type *btype, Type *ltype, Type *rtype, int flags)
3526 flags &= ~RESOLVE_AUTOCAST; /* not applicable to this function */
3529 * Locate the base type. If the base type does not have a SemGroup
3530 * there are no casts. (XXX put system operators here)
3532 sg = BaseType(&btype);
3538 * Look for the cast in the SemGroup
3540 RUNE_FOREACH(d, &sg->sg_DeclList, d_Node) {
3541 if (d->d_Op == DOP_PROC && (d->d_ScopeFlags & SCOPE_CAST)) {
3542 if (MatchCastTypes(d, ltype, rtype))
3548 * Failed. If the base type is a compound type, look for the
3549 * cast in the SemGroup for each element making up the compound
3550 * type. e.g. so (mycustomtype, double) would find the cast
3553 if (btype->ty_Op == TY_COMPOUND) {
3554 RUNE_FOREACH(d, &sg->sg_DeclList, d_Node) {
3556 if (d->d_Op & DOPF_STORAGE) {
3557 d2 = findCast(d->d_StorDecl.ed_Type,
3558 ltype, rtype, flags);
3559 } else if (d->d_Op == DOP_TYPEDEF) {
3560 d2 = findCast(d->d_TypedefDecl.ed_Type,
3561 ltype, rtype, flags);
3574 * resolveExpOper() - resolve an operator
3576 * This is complex enough that it is broken out into its own procedure.
3577 * Normally we just look the operator up but we have to special case
3578 * pointer arithmatic because we do will not know until now that we
3581 * itype is a return-type hint only. resolveExpOper() can ignore it
3582 * if it wishes. We currently use it to detect cast-to-void, such as
3583 * when an expression like "++i" is used in a for() loop or as a
3584 * standalone statement. This allows us to optimize the case.
3587 resolveExpOper(SemGroup *isg, SemGroup *sg, Exp *exp, Type *itype, int flags)
3590 int isPointerOp = 0;
3593 flags &= ~RESOLVE_AUTOCAST; /* not applicable to this function */
3595 loadExpCopy(©, exp);
3596 dassert_exp(exp, exp->ex_Id != NULL);
3597 if (exFlags & EXF_BINARY) {
3598 exLhs = resolveExp(isg, sg, exLhs, NULL, flags);
3599 exRhs = resolveExp(isg, sg, exRhs, NULL, flags);
3600 } else if (exFlags & EXF_UNARY) {
3601 exLhs = resolveExp(isg, sg, exLhs, NULL, flags);
3603 dassert_exp(exp, 0);
3607 * If the lhs is a pointer look the operator up in the Pointer
3608 * class first. Operators in the Pointer class are special-cased.
3609 * A second pointer argument or a pointer return value must match
3612 * If this fails, or if the ltype is not a pointer, then look
3613 * the operator up normally.
3615 if (exLhs->ex_Type->ty_Op == TY_PTRTO ||
3616 exLhs->ex_Type->ty_Op == TY_REFTO ||
3617 exLhs->ex_Type->ty_Op == TY_CPTRTO
3622 if (exFlags & EXF_BINARY) {
3623 rtype = exRhs->ex_Type;
3624 ltype = exLhs->ex_Type;
3626 dassert(exFlags & EXF_UNARY);
3628 ltype = exLhs->ex_Type;
3630 d = findOper(&PointerType, exp->ex_Id, ltype, rtype, flags);
3634 d = findExpOper(©, flags);
3636 d = findExpOper(©, flags);
3640 * Fall through to finish up resolving the operator. We just set
3641 * ex_Decl for internal operators, and construct a call for
3642 * non-internal procedural operators.
3650 dassert_exp(exp, d != NULL);
3651 dassert_exp(exp, d->d_Op == DOP_PROC);
3652 dassert_exp(exp, d->d_ProcDecl.ed_Type->ty_Op == TY_PROC);
3653 type = d->d_ProcDecl.ed_Type;
3654 exType = type->ty_ProcType.et_RetType;
3657 * Special case for internal Pointer ops. The return type is
3658 * the left-hand type (we may still optimize it to void later).
3661 (d->d_ScopeFlags & SCOPE_INTERNAL) &&
3662 SimilarType(&VoidRefType, exType)
3664 if (exType->ty_SQFlags & SF_LVALUE)
3665 exType = ADD_LVALUE(exLhs->ex_Type);
3667 exType = DEL_LVALUE(exLhs->ex_Type);
3670 type = d->d_ProcDecl.ed_Type->ty_ProcType.et_ArgsType;
3671 dassert(type->ty_Op == TY_ARGS);
3672 sg2 = type->ty_ArgsType.et_SemGroup;
3675 * Assert that LVALUE requirements are met. XXX MatchType()
3676 * code should disallow the non-lvalue-cast-to-lvalue case
3677 * so we don't have to do a check here.
3679 RUNE_FOREACH(d2, &sg2->sg_DeclList, d_Node) {
3680 if ((d2->d_Op & DOPF_STORAGE) &&
3681 d2->d_Op != DOP_GLOBAL_STORAGE) {
3683 if ((d2->d_ScopeFlags & SCOPE_LVALUE) &&
3684 (exLhs->ex_Type->ty_SQFlags &
3688 "lhs of exp must be "
3690 dassert_exp(exp, 0);
3692 } else if (count == 1) {
3693 if ((d2->d_ScopeFlags & SCOPE_LVALUE) &&
3694 (exRhs->ex_Type->ty_SQFlags &
3698 "rhs of exp must be "
3700 dassert_exp(exp, 0);
3707 if (d->d_ScopeFlags & SCOPE_INTERNAL) {
3709 * Internal operator. Optimize any cast to void
3710 * by having the internal function deal with it.
3711 * (since we aren't setting exType the optimization
3712 * currently doesn't do anything, see ST_Exp)
3715 if (itype == &VoidType) {
3717 exFlags |= EXF_RET_VOID;
3721 * Normal procedural operator. Convert the left and
3722 * right hand sides to a compound expression and
3723 * convert exp to a TOK_CALL. NOTE! ex_Rhs may be
3726 * The compound expression may need to rewrite a
3727 * subclass procedure, which it can do if the
3728 * procedure's body has not yet been created (or
3729 * duplicated from the superclass). ex_Decl must
3730 * be set in this case.
3732 * Note that the expression structure may be shared.
3733 * The conversion is permanent so that is ok.
3735 * XXX keep the type intact?
3737 exLhs->ex_Next = exRhs;
3739 exRhs = ExpToCompoundExp(exRhs, TOK_COMPOUND);
3740 if (d->d_ProcDecl.ed_ProcBody == NULL)
3742 exRhs = resolveCompoundExp(isg, sg, exRhs, type, flags);
3743 exLhs = AllocExp(NULL);
3744 LexDupRef(&exp->ex_LexRef, &exLhs->ex_LexRef);
3745 exLhs->ex_Token = TOK_ID;
3746 exLhs->ex_Id = d->d_Id;
3748 exLhs->ex_Type = d->d_ProcDecl.ed_Type;
3749 exLhs->ex_Flags |= EXF_RESOLVED;
3750 exToken = exp->ex_Token = TOK_CALL;
3751 exFlags = EXF_BINARY;
3756 "Unable to resolve operator: %s\n", exp->ex_Id);
3757 dassert_exp(exp, 0);
3761 * Flag a pure operator whos arguments are constants as probably
3764 if (d->d_ScopeFlags & SCOPE_PURE) {
3765 if ((exLhs->ex_Flags & (EXF_CONST | EXF_PROBCONST)) &&
3767 (exRhs->ex_Flags & (EXF_CONST | EXF_PROBCONST)))) {
3768 exFlags |= EXF_PROBCONST;
3772 exFlags |= EXF_RESOLVED;
3773 return(dupExpCopy(©, exp));
3777 loadExpCopy(Exp *copy, Exp *exp)
3779 copy->ex_Lhs = exp->ex_Lhs;
3780 copy->ex_Rhs = exp->ex_Rhs;
3781 copy->ex_Flags = exp->ex_Flags;
3782 copy->ex_Type = exp->ex_Type;
3783 copy->ex_Decl = exp->ex_Decl;
3784 copy->ex_Token = exp->ex_Token;
3785 copy->ex_Visibility = exp->ex_Visibility;
3786 copy->ex_Id = exp->ex_Id;
3787 copy->ex_ArgId = exp->ex_ArgId;
3788 copy->ex_AuxExp = exp->ex_AuxExp;
3792 saveExpCopy(Exp *copy, Exp *exp)
3794 exp->ex_Lhs = copy->ex_Lhs;
3795 exp->ex_Rhs = copy->ex_Rhs;
3796 exp->ex_Flags = copy->ex_Flags;
3797 exp->ex_Type = copy->ex_Type;
3798 exp->ex_Decl = copy->ex_Decl;
3799 exp->ex_Token = copy->ex_Token;
3800 exp->ex_Visibility = copy->ex_Visibility;
3801 exp->ex_Id = copy->ex_Id;
3802 exp->ex_ArgId = copy->ex_ArgId;
3803 exp->ex_AuxExp = copy->ex_AuxExp;
3806 #define EXF_DUPSHAREFLAGS -1
3809 dupExpCopy(Exp *copy, Exp *exp)
3813 if ((exp->ex_Flags & EXF_DUPEXP) == 0) {
3814 saveExpCopy(copy, exp);
3819 * We can share the expression or subexpression across duplicated
3820 * elements in distinct subclasses if these conditions are met.
3822 * Note: 0x80000000 for ex_Visibility simply means that the visibility
3823 * was never modified and can be changed for the first time.
3824 * Superclasses are resolved first so we should be ok.
3826 if (exp->ex_Lhs == copy->ex_Lhs &&
3827 exp->ex_Rhs == copy->ex_Rhs &&
3828 ((exp->ex_Flags ^ copy->ex_Flags) & ~EXF_DUPSHAREFLAGS) == 0 &&
3829 (exp->ex_Type == copy->ex_Type || exp->ex_Type == NULL) &&
3830 exp->ex_Token == copy->ex_Token &&
3831 (exp->ex_Decl == copy->ex_Decl || exp->ex_Decl == NULL) &&
3832 (exp->ex_Id == copy->ex_Id || exp->ex_Id == NULL) &&
3833 (exp->ex_ArgId == copy->ex_ArgId || exp->ex_ArgId == NULL) &&
3834 (exp->ex_AuxExp == copy->ex_AuxExp || exp->ex_AuxExp == NULL) &&
3835 (exp->ex_Visibility == copy->ex_Visibility ||
3836 (exp->ex_Visibility & 0x80000000))
3840 fprintf(stderr, "DUPEXPB COMPARE %d %p\n", ++count, exp);
3842 saveExpCopy(copy, exp);
3846 nexp = AllocExp(NULL);
3847 LexDupRef(&exp->ex_LexRef, &nexp->ex_LexRef);
3853 "DUPEXPB %d %p lhs (%p,%p) rhs (%p,%p) "
3854 "flags (%08x,%08x) types (%p, %p) "
3855 "tokens (%04x, %04x), decl (%p, %p) "
3859 exp->ex_Lhs, copy->ex_Lhs,
3860 exp->ex_Rhs, copy->ex_Rhs,
3861 exp->ex_Flags & ~EXF_DUPSHAREFLAGS,
3862 copy->ex_Flags & ~EXF_DUPSHAREFLAGS,
3863 exp->ex_Type, copy->ex_Type,
3864 exp->ex_Token, copy->ex_Token,
3865 exp->ex_Decl, copy->ex_Decl,
3866 exp->ex_Visibility, copy->ex_Visibility
3868 ExpPrintError(exp, 0);
3872 copy->ex_Flags &= ~EXF_DUPEXP;
3873 saveExpCopy(copy, nexp);
3879 * resolveType() - Resolve a type
3881 * This routine is responsible for resolving the size and alignment
3882 * features of a type. Note that we do not special-case LVALUE
3883 * qualified types here.
3885 * This routine is also rsponsible for resolving the visibility of
3886 * a type's elements. Visibility is inherited from sub-types. Base
3887 * classes's visibility should already be set by resolveSuperClass()
3890 resolveType(Type *type, Type *adjtype, int flags)
3892 SemGroup *sg = NULL;
3896 flags &= ~RESOLVE_AUTOCAST; /* not applicable to this function */
3898 if (type->ty_Flags & TF_RESOLVED)
3901 dassert_type(type, (type->ty_Flags & TF_RESOLVING) == 0);
3902 type->ty_Flags |= TF_RESOLVING;
3904 switch(type->ty_Op) {
3907 * NOTE: TF_HASLVPTR inherited as appropriate after switch.
3909 * NOTE: Special case, PointerType fields not in classes XXX
3910 * (force alignment and bytes)?
3912 dassert(type->ty_SQList ==
3913 &type->ty_ClassType.et_SemGroup->sg_ClassList);
3914 sg = type->ty_ClassType.et_SemGroup;
3915 do2 = resolveSemGroup1(sg, flags);
3916 if (type != &PointerType) {
3917 type->ty_Bytes = sg->sg_Bytes;
3918 type->ty_AlignMask = sg->sg_AlignMask;
3920 /* visibility already determined by resolveSuperClass? */
3922 if (type->ty_ClassType.et_Super &&
3923 type->ty_ClassType.et_Super->ty_Op == TY_UNRESOLVED) {
3924 type->ty_ClassType.et_Super =
3925 resolveSuperClass(type->ty_ClassType.et_Super);
3929 * Type inherits ISUNSIGNED from class. This is a special
3930 * flag helper for the interpreter and code generator.
3932 if (sg->sg_Flags & SGF_ISINTEGER)
3933 type->ty_Flags |= TF_ISINTEGER;
3934 if (sg->sg_Flags & SGF_ISUNSIGNED)
3935 type->ty_Flags |= TF_ISUNSIGNED;
3936 if (sg->sg_Flags & SGF_ISFLOATING)
3937 type->ty_Flags |= TF_ISFLOATING;
3938 if (sg->sg_Flags & SGF_ISBOOL)
3939 type->ty_Flags |= TF_ISBOOL;
3940 if (sg->sg_Flags & SGF_HASASS)
3941 type->ty_Flags |= TF_HASASS;
3942 dassert(type->ty_Visibility != 0);
3946 * NOTE: Do not set TF_HASLVPTR, C pointers are not tracked.
3948 type->ty_Bytes = sizeof(void *);
3949 type->ty_AlignMask = POINTER_ALIGN;
3950 type->ty_CPtrType.et_Type =
3951 RESOLVETYPEADJ(type->ty_CPtrType.et_Type, type);
3952 type->ty_Visibility = type->ty_CPtrType.et_Type->ty_Visibility;
3956 * Set TF_HASLVPTR, pointers are tracked.
3958 type->ty_Bytes = sizeof(PointerStor);
3959 type->ty_AlignMask = POINTER_ALIGN;
3960 type->ty_PtrType.et_Type =
3961 RESOLVETYPEADJ(type->ty_PtrType.et_Type, type);
3962 type->ty_Visibility = type->ty_PtrType.et_Type->ty_Visibility;
3963 type->ty_Flags |= TF_HASLVPTR;
3967 * Set TF_HASLVPTR, references are tracked.
3969 type->ty_Bytes = sizeof(PointerStor);
3970 type->ty_AlignMask = POINTER_ALIGN;
3971 type->ty_RefType.et_Type =
3972 RESOLVETYPEADJ(type->ty_RefType.et_Type, type);
3973 type->ty_Visibility = type->ty_RefType.et_Type->ty_Visibility;
3974 type->ty_Flags |= TF_HASLVPTR;
3978 * Inherit TF_HASLVPTR (if array type is or contains something
3979 * which needs to be tracked).
3981 * XXX allow ArySize resolve to local expression?
3982 * XXX use interpreter to resolve constant expression?
3983 * XXX SemGroup passed as NULL.
3985 * XXX hack, ex_ArySize can be shared amoungst qualified
3986 * array types. Only resolve it once. XXX
3988 * YYY hack what is our ImportSemGroup ???
3991 Exp *exp = type->ty_AryType.et_ArySize;
3992 if ((exp->ex_Flags & EXF_RESOLVED) == 0) {
3993 exp = resolveConstExp(NULL,
3994 type->ty_AryType.et_SemGroup,
3997 type->ty_AryType.et_ArySize = exp;
3998 type->ty_AryType.et_Type =
3999 RESOLVETYPEADJ(type->ty_AryType.et_Type, type);
4000 type->ty_AryType.et_Count = resolveGetConstExpInt64(exp);
4001 type->ty_AlignMask =
4002 type->ty_AryType.et_Type->ty_AlignMask;
4004 type->ty_AryType.et_Type->ty_Bytes *
4005 type->ty_AryType.et_Count;
4007 type->ty_Visibility = type->ty_AryType.et_Type->ty_Visibility;
4008 type->ty_Flags |= type->ty_AryType.et_Type->ty_Flags &
4009 (TF_HASLVPTR | TF_HASCONSTRUCT |
4010 TF_HASDESTRUCT | TF_HASGCONSTRUCT |
4011 TF_HASGDESTRUCT | TF_HASASS);
4015 * NOTE: TF_HASLVPTR inherited as appropriate after switch.
4017 sg = type->ty_CompType.et_SemGroup;
4018 do2 = resolveSemGroup1(sg, flags);
4019 type->ty_Bytes = sg->sg_Bytes;
4020 type->ty_AlignMask = sg->sg_AlignMask;
4021 type->ty_Visibility = SCOPE_ALL_VISIBLE;
4025 * NOTE: TF_HASLVPTR inherited as appropriate after switch.
4027 sg = type->ty_VarType.et_SemGroup;
4028 do2 = resolveSemGroup1(sg, flags);
4029 type->ty_Bytes = sg->sg_Bytes;
4030 type->ty_AlignMask = sg->sg_AlignMask;
4031 type->ty_Visibility = SCOPE_ALL_VISIBLE;
4035 * NOTE: TF_HASLVPTR inherited as appropriate after switch.
4037 sg = type->ty_ArgsType.et_SemGroup;
4038 do2 = resolveSemGroup1(sg, flags);
4039 type->ty_Bytes = sg->sg_Bytes;
4040 type->ty_AlignMask = sg->sg_AlignMask;
4041 type->ty_Visibility = SCOPE_ALL_VISIBLE;
4045 * NOTE: Storage not tracked.
4047 type->ty_ProcType.et_ArgsType =
4048 RESOLVETYPE(type->ty_ProcType.et_ArgsType);
4049 type->ty_ProcType.et_RetType =
4050 RESOLVETYPEADJ(type->ty_ProcType.et_RetType, type);
4052 type->ty_AlignMask = 0;
4053 type->ty_Visibility = SCOPE_ALL_VISIBLE;
4057 * NOTE: Base storage is not tracked.
4059 type->ty_Bytes = type->ty_StorType.et_Bytes;
4060 /* XXX check pwr of 2 */
4062 type->ty_AlignMask = type->ty_Bytes - 1;
4063 type->ty_Visibility = SCOPE_ALL_VISIBLE;
4067 * NOTE: Tracking set by resolveType().
4069 type->ty_Flags &= ~TF_RESOLVING;
4070 type = resolveSuperClass(type);
4072 errorDottedId(otype->ty_UnresType.et_DottedId,
4073 "Unable to resolve class");
4077 type = RESOLVETYPE(type);
4078 type->ty_Flags |= TF_RESOLVING;
4079 /* visibility set by resolveSuperClass() */
4083 * NOTE: Tracking unknown (must be handled at run-time).
4085 type->ty_Visibility = SCOPE_ALL_VISIBLE;
4089 * NOTE: Storage is persistent, so wrapper is not tracked.
4091 type->ty_Visibility = SCOPE_ALL_VISIBLE; /* XXX */
4094 dpanic("Unknown type %d (type=%p)", type->ty_Op, type);
4097 type->ty_Flags &= ~TF_RESOLVING;
4098 type->ty_Flags |= TF_RESOLVED;
4100 do2 = resolveSemGroup2(sg, flags);
4102 resolveSemGroup3(sg, flags);
4106 * Resolve tracking flags so the run-time can take appropriate
4110 if (sg->sg_Flags & SGF_HASASS)
4111 type->ty_Flags |= TF_HASASS;
4113 type->ty_Flags |= TF_HASLVPTR;
4114 if (sg->sg_Flags & SGF_VARARGS)
4115 type->ty_Flags |= TF_HASLVPTR; /* XXX TF_VARARGS */
4117 type->ty_Flags |= TF_HASCONSTRUCT;
4119 type->ty_Flags |= TF_HASDESTRUCT;
4121 * Combine constructor/destructor hint flags for globals
4122 * because we have just one linked list for global constructors
4123 * and destructors (no need to optimize heavily).
4126 type->ty_Flags |= TF_HASGCONSTRUCT|TF_HASGDESTRUCT;
4130 * Resolve the default expression for the type, if any.
4132 * XXX qualified types just copy the exp. bad bad YYY
4134 * YYY resolveExp() no ISG (import sem group)
4136 if (type->ty_AssExp) {
4137 if ((type->ty_AssExp->ex_Flags & EXF_RESOLVED) == 0) {
4138 type->ty_AssExp = resolveExp(NULL, sg, type->ty_AssExp,
4140 flags | RESOLVE_AUTOCAST);
4142 type->ty_Flags |= TF_HASASS;
4146 * If adjtype is non-NULL it must be moved to the new type's QList.
4148 if (adjtype && type != otype) {
4149 if (adjtype->ty_SQList)
4150 RUNE_REMOVE(adjtype->ty_SQList, adjtype, ty_Node);
4151 adjtype->ty_SQList = &type->ty_QList;
4152 RUNE_INSERT_TAIL(adjtype->ty_SQList, adjtype, ty_Node);
4158 * resolveSuperClass() - resolve an unresolved dotted id sequence into a class
4160 * Unresolved type identifier sequences must be resolved. We are also
4161 * responsible for setting the visibility of the type's elements.
4164 resolveSuperClass(Type *super)
4169 int visibility = SCOPE_ALL_VISIBLE;
4172 dassert_type(super, super->ty_Op == TY_UNRESOLVED);
4174 dottedId = super->ty_UnresType.et_DottedId;
4175 sg = super->ty_UnresType.et_SemGroup;
4177 d = FindDeclPath(NULL, super->ty_UnresType.et_ImportSemGroup,
4179 dottedId, FDC_NULL, &visibility, -1, &eno);
4184 * Resolve the unresolved type. Note that this occurs during class
4185 * resolution and we can't call resolveType() here without getting into
4186 * a loop, so we do not yet know storage requirements (ty_Bytes and
4191 sg = d->d_ClassDecl.ed_SemGroup;
4192 super->ty_Op = TY_CLASS;
4193 super->ty_ClassType.et_SemGroup = sg;
4194 super->ty_ClassType.et_Super = d->d_ClassDecl.ed_Super;
4195 super->ty_Visibility = visibility;
4196 if (super->ty_SQList)
4197 RUNE_REMOVE(super->ty_SQList, super, ty_Node);
4198 super->ty_SQList = &sg->sg_ClassList;
4199 RUNE_INSERT_TAIL(super->ty_SQList, super, ty_Node);
4200 dassert(visibility);
4202 * XXX should we move the class from the unresolved list to
4203 * the new SemGroup's actual list?
4208 * Adjust super instead of allocating a new super, so all
4209 * other references to super using this class path get
4213 dassert_type(super, d->d_TypedefDecl.ed_Type != super);
4215 d->d_TypedefDecl.ed_Type,
4218 d->d_TypedefDecl.ed_Type->ty_SQFlags,
4222 super->ty_Visibility = visibility;
4225 errorDottedId(dottedId, "identifier is not a class or typedef");
4226 dassert_type(super, 0);
4232 * Resolve the declarations in a semantic group. We have to do this if
4233 * (a) The declaration(s) would not otherwise be resolved by our statement
4234 * scan, or (b) We need definitive size/alignment information now rather
4237 * Also resolve SemGroup global initialization dependencies via SemGroupDepend.
4239 * SemGroup resolution occurs in three stages in order to deal with
4240 * resolver loops. The first stage does just enough to figure out
4241 * how large the non-global part of the SemGroup is (e.g. doesn't run
4242 * through pointers). The second stage handles global elements, and the
4243 * third stage completes the process.
4245 * NOTE! This code does not resolve declarations related to executable
4246 * semantic groups, such as sub-blocks within a procedure, but it does
4247 * have to resolve procedure definitions found in Class's and such.
4249 * NOTE! This code handles the last stage of subclass refinement, by
4250 * checking the validity of the refinement and setting sg_Compat properly.
4254 resolveSemGroup1(SemGroup *sg, int flags)
4260 flags &= ~RESOLVE_AUTOCAST; /* not applicable to this function */
4262 dep = resolvePushSGDepend(sg);
4263 if (sg->sg_Flags & SGF_RESOLVED) {
4264 resolvePopSGDepend(dep);
4267 if (sg->sg_Flags & SGF_RESOLVING) {
4269 "Unable to resolve embedded recursive reference\n");
4270 dassert_semgrp(sg, (sg->sg_Flags & SGF_RESOLVING) == 0);
4272 sg->sg_Flags |= SGF_RESOLVING;
4275 * First pass - resolve storage only. Note that this specifically
4276 * does not try to handle the multiple semantic layers inside a
4277 * procedure. See ResolveStorage() for that.
4279 RUNE_FOREACH(d, &sg->sg_DeclList, d_Node) {
4288 case DOP_STACK_STORAGE:
4290 * can't happen. Stack storage is only used in
4291 * executable contexts.
4294 case DOP_ARGS_STORAGE:
4295 case DOP_GROUP_STORAGE:
4296 type = d->d_StorDecl.ed_Type;
4298 switch(type->ty_Op) {
4300 d->d_Bytes = sizeof(void *);
4301 d->d_AlignMask = POINTER_ALIGN;
4302 if ((d->d_Scope.s_Flags & SCOPE_ALIGN) &&
4303 d->d_Scope.s_AlignOverride) {
4305 d->d_Scope.s_AlignOverride - 1;
4310 if (d->d_ScopeFlags & SCOPE_LVALUE) {
4312 * NOTE: d->d_Bytes is different from
4313 * the size of the underlying
4314 * type that the LValueStor
4317 dassert(d->d_Op == DOP_ARGS_STORAGE);
4318 d->d_Bytes = sizeof(LValueStor);
4319 d->d_AlignMask = LVALUE_ALIGN;
4321 d->d_Bytes = sizeof(PointerStor);
4322 d->d_AlignMask = POINTER_ALIGN;
4324 if ((d->d_Scope.s_Flags & SCOPE_ALIGN) &&
4325 d->d_Scope.s_AlignOverride) {
4327 d->d_Scope.s_AlignOverride - 1;
4331 resolveDecl(d, flags);
4334 if (sg->sg_AlignMask < d->d_AlignMask)
4335 sg->sg_AlignMask = d->d_AlignMask;
4336 sg->sg_Bytes = (sg->sg_Bytes + d->d_AlignMask) &
4338 d->d_Offset = sg->sg_Bytes;
4339 sg->sg_Bytes += d->d_Bytes;
4340 if (d->d_StorDecl.ed_AssExp)
4341 sg->sg_Flags |= SGF_HASASS;
4342 if (type->ty_Flags & TF_HASASS)
4343 sg->sg_Flags |= SGF_HASASS;
4344 if (type->ty_Flags & TF_HASLVPTR)
4345 sg->sg_Flags |= SGF_HASLVPTR;
4347 case DOP_GLOBAL_STORAGE:
4348 /* handled in pass2 */
4351 dassert_semgrp(sg, 0);
4356 * Rollup &obj into a SemGroup flag.
4358 if (d->d_Flags & DF_ADDRUSED) {
4359 sg->sg_Flags |= SGF_ADDRUSED;
4360 fprintf(stderr, "RESOLVER ADDRUSED %s\n", d->d_Id);
4368 sg->sg_Bytes = (sg->sg_Bytes + sg->sg_AlignMask) & ~sg->sg_AlignMask;
4369 sg->sg_Flags |= SGF_RESOLVED;
4370 resolvePopSGDepend(dep);
4376 * Followup - resolve globals
4380 resolveSemGroup2(SemGroup *sg, int flags)
4385 flags &= ~RESOLVE_AUTOCAST; /* not applicable to this function */
4387 if (sg->sg_Flags & SGF_GRESOLVED)
4389 if (sg->sg_Flags & SGF_GRESOLVING) {
4391 "Unable to resolve embedded recursive reference\n");
4392 dassert_semgrp(sg, (sg->sg_Flags & SGF_GRESOLVING) == 0);
4394 sg->sg_Flags |= SGF_GRESOLVING;
4397 * First pass - resolve storage only. Note that this specifically
4398 * does not try to handle the multiple semantic layers inside a
4399 * procedure. See ResolveStorage() for that.
4401 RUNE_FOREACH(d, &sg->sg_DeclList, d_Node) {
4409 case DOP_STACK_STORAGE:
4411 * can't happen. Stack storage is only used in
4412 * executable contexts.
4415 case DOP_ARGS_STORAGE:
4416 case DOP_GROUP_STORAGE:
4418 * Non-globals were handled in pass-1
4421 case DOP_GLOBAL_STORAGE:
4423 * Global storage must be handled in pass-2
4425 type = d->d_StorDecl.ed_Type;
4427 switch(type->ty_Op) {
4429 d->d_Bytes = sizeof(void *);
4430 d->d_AlignMask = POINTER_ALIGN;
4431 if ((d->d_Scope.s_Flags & SCOPE_ALIGN) &&
4432 d->d_Scope.s_AlignOverride) {
4434 d->d_Scope.s_AlignOverride - 1;
4439 d->d_Bytes = sizeof(PointerStor);
4440 d->d_AlignMask = POINTER_ALIGN;
4441 if ((d->d_Scope.s_Flags & SCOPE_ALIGN) &&
4442 d->d_Scope.s_AlignOverride) {
4444 d->d_Scope.s_AlignOverride - 1;
4448 resolveDecl(d, flags);
4451 if (sg->sg_GlobalAlignMask < d->d_AlignMask)
4452 sg->sg_GlobalAlignMask = d->d_AlignMask;
4453 sg->sg_GlobalBytes = (sg->sg_GlobalBytes +
4454 d->d_AlignMask) & ~d->d_AlignMask;
4455 d->d_Offset = sg->sg_GlobalBytes;
4456 sg->sg_GlobalBytes += d->d_Bytes;
4457 if (d->d_StorDecl.ed_AssExp)
4458 sg->sg_Flags |= SGF_GHASASS;
4459 if (type->ty_Flags & TF_HASASS)
4460 sg->sg_Flags |= SGF_GHASASS;
4461 if (type->ty_Flags & TF_HASLVPTR)
4462 sg->sg_Flags |= SGF_GHASLVPTR;
4465 dassert_semgrp(sg, 0);
4473 sg->sg_GlobalBytes = (sg->sg_GlobalBytes + sg->sg_GlobalAlignMask) &
4474 ~sg->sg_GlobalAlignMask;
4475 sg->sg_Flags |= SGF_GRESOLVED;
4481 resolveSemGroup3(SemGroup *sg, int flags)
4486 flags &= ~RESOLVE_AUTOCAST; /* not applicable to this function */
4489 * 0 - reserved for dynamic initialization
4490 * 1 - reserved for dynamic destructor
4495 * Third pass, resolve non-storage entities after setting
4496 * SGF_RESOLVED, these entities may legally embed this class (if
4499 * Resolve pointers that were only partially resolved in the first
4502 * Refinements have been resolved but we have to check them for
4503 * legality and set sg_Compat.
4505 * Note that this is what allows us to typedef a subclass in its
4506 * superclass. The typedef itself is safe.
4508 * Also resolve storage pointer entities that were skipped in the
4509 * first pass. Such pointers could point to ourselves.
4511 * Finally, set SCOPE_UNLOCKED on any entity which does not
4512 * contain any lockable data (like int's).
4514 RUNE_FOREACH(d, &sg->sg_DeclList, d_Node) {
4516 * Final resolution of refinements.
4518 if (d->d_ScopeFlags & SCOPE_REFINE) {
4519 resolveDecl(d->d_Super, flags);
4520 resolveDecl(d, flags);
4521 RefineDeclaration(sg, d->d_Super, d);
4532 resolveDecl(d, flags);
4535 resolveDecl(d, flags);
4538 * For now internal generation does not need a
4539 * dynamic component (and doesn't generate external
4540 * code so the function wouldn't exist anyway).
4542 if (d->d_ScopeFlags & SCOPE_INTERNAL)
4546 * Assign the dynamic index. There may be multiple
4547 * entries for the same d_Id, they are ordered such
4548 * that refinements use the same DynIndex as in
4549 * the superclass which is what allows dynamic method
4550 * calls to work properly. All non-refined subclass
4551 * elements are ordered after all refined/non=refined
4552 * superclass elements (replacing the superclass
4553 * element and using the same DynIndex when refined).
4555 d->d_DynIndex = dyncount;
4558 case DOP_ARGS_STORAGE:
4559 case DOP_GROUP_STORAGE:
4560 /*case DOP_STACK_STORAGE:*/
4561 case DOP_GLOBAL_STORAGE:
4562 switch(d->d_StorDecl.ed_Type->ty_Op) {
4566 resolveDecl(d, flags);
4571 dassert_semgrp(sg, 0);
4577 * If no dynamic methods and no dynamic initialization or destruction
4578 * required, set dyncount to 0.
4580 if (dyncount == 2 &&
4581 (sg->sg_Flags & SGF_HASASS) == 0 &&
4582 sg->sg_SRBase == NULL &&
4583 sg->sg_CBase == NULL &&
4584 sg->sg_DBase == NULL) {
4587 sg->sg_DynCount = dyncount;
4588 sg->sg_Flags &= ~SGF_RESOLVING;
4592 * findExpOper() - Find operator declaration matching expression
4594 * Locate the operator declaration (a DOP_PROCDEF) that matches
4595 * the expression or NULL if no match could be found. The expression's
4596 * left and right hand sides must already be resolved.
4598 * NOTE! A temporary 'copy' Exp may be passed, not all fields are valid.
4602 findExpOper(Exp *exp, int flags)
4608 flags &= ~RESOLVE_AUTOCAST; /* not applicable to this function */
4610 if (exp->ex_Flags & EXF_BINARY) {
4611 rtype = exp->ex_Rhs->ex_Type;
4612 ltype = exp->ex_Lhs->ex_Type;
4614 dassert(exp->ex_Flags & EXF_UNARY);
4616 ltype = exp->ex_Lhs->ex_Type;
4620 * XXX look in our local semantic hierarchy for a compatible operator ?
4624 * Attempt to find a matching operator from the left hand side
4626 d = findOper(ltype, exp->ex_Id, ltype, rtype, flags);
4628 if (d || (exp->ex_Flags & EXF_BINARY) == 0)
4631 d = findOper(rtype, exp->ex_Id, ltype, rtype, flags);
4637 findOper(Type *btype, string_t id, Type *ltype, Type *rtype, int flags)
4641 int args = (rtype != NULL) ? 2 : 1;
4643 flags &= ~RESOLVE_AUTOCAST; /* not applicable to this function */
4646 * Locate the base type. If the base type does not have a SemGroup
4647 * there are no operators. (XXX put system operators here)
4649 sg = BaseType(&btype);
4655 * Look for the operator in the SemGroup
4657 for (d = FindOperId(sg, id, args); d; d = d->d_ONext) {
4658 resolveDecl(d, flags);
4659 if (d->d_MyGroup == sg &&
4660 d->d_Op == DOP_PROC &&
4661 d->d_ProcDecl.ed_OperId == id &&
4662 MatchOperatorTypes(d, ltype, rtype)
4669 * Failed. If the base type is a compound type, look for the
4670 * operator in the SemGroup for each element making up the compound
4671 * type. e.g. so (mycustomtype, double) would find the operator
4674 if (btype->ty_Op == TY_COMPOUND) {
4675 RUNE_FOREACH(d, &sg->sg_DeclList, d_Node) {
4677 if (d->d_Op & DOPF_STORAGE) {
4678 d2 = findOper(d->d_StorDecl.ed_Type, id,
4679 ltype, rtype, flags);
4680 } else if (d->d_Op == DOP_TYPEDEF) {
4681 d2 = findOper(d->d_TypedefDecl.ed_Type, id,
4682 ltype, rtype, flags);
4694 errorDottedId(string_t *ary, const char *ctl, ...)
4700 vfprintf(stderr, ctl, va);
4702 fprintf(stderr, ": %s", ary[0]);
4703 for (i = 1; ary[i]; ++i)
4704 fprintf(stderr, ".%s", ary[i]);
4705 fprintf(stderr, "\n");
4709 * Resolve the alignment requirements for SemGroups related to
4710 * statements, including the alignment requirements needed for
4711 * temporary expression space.
4714 ResolveAlignment(Stmt *st, int flags)
4716 SemGroup *sg = st->st_MyGroup;
4719 if (st->st_Flags & STF_ALIGNRESOLVED)
4721 st->st_Flags |= STF_ALIGNRESOLVED;
4724 * If this is an executable semantic layer or an import layer then
4725 * assign storage to declarations up-front. Of the various
4726 * DOP_*_STORAGE ops, we should only see DOP_STACK_STORAGE and
4727 * DOP_GLOBAL_STORAGE.
4729 * Note: if this is the root ST_Import STF_SEMANTIC is *NOT* set and
4732 if ((st->st_Flags & STF_SEMANTIC) && st->st_Op != ST_Class) {
4736 * Pre-scan for alignment. Don't try to propagate the
4737 * alignment to the parent for now as that would require
4738 * recalculating the parent(s).
4740 RUNE_FOREACH(d, &sg->sg_DeclList, d_Node) {
4742 case DOP_STACK_STORAGE:
4743 case DOP_ARGS_STORAGE:
4744 case DOP_GROUP_STORAGE:
4745 if (sg->sg_AlignMask < d->d_AlignMask)
4746 sg->sg_AlignMask = d->d_AlignMask;
4748 case DOP_GLOBAL_STORAGE:
4749 if (sg->sg_GlobalAlignMask < d->d_AlignMask)
4750 sg->sg_GlobalAlignMask = d->d_AlignMask;
4769 d = st->st_TypedefStmt.es_Decl;
4770 resolveStorageDeclExpAlign(d, &sg->sg_TmpAlignMask);
4775 * NOTE: Don't calculate for declarations that belong in
4776 * a different context.
4782 d = st->st_DeclStmt.es_Decl;
4784 for (i = 0; i < st->st_DeclStmt.es_DeclCount; ++i) {
4785 if (st->st_MyGroup == d->d_MyGroup)
4786 resolveStorageDeclExpAlign(d, &sg->sg_TmpAlignMask);
4787 d = RUNE_NEXT(d, d_Node);
4799 if (st->st_LoopStmt.es_BCond) {
4800 resolveStorageExpAlign(st->st_LoopStmt.es_BCond,
4801 &sg->sg_TmpAlignMask);
4803 if (st->st_LoopStmt.es_ACond) {
4804 resolveStorageExpAlign(st->st_LoopStmt.es_ACond,
4805 &sg->sg_TmpAlignMask);
4807 if (st->st_LoopStmt.es_AExp) {
4808 resolveStorageExpAlign(st->st_LoopStmt.es_AExp,
4809 &sg->sg_TmpAlignMask);
4818 resolveStorageExpAlign(st->st_IfStmt.es_Exp,
4819 &sg->sg_TmpAlignMask);
4822 if (st->st_RetStmt.es_Exp)
4823 resolveStorageExpAlign(st->st_RetStmt.es_Exp,
4824 &sg->sg_TmpAlignMask);
4827 if (st->st_ResStmt.es_Exp)
4828 resolveStorageExpAlign(st->st_ResStmt.es_Exp,
4829 &sg->sg_TmpAlignMask);
4833 * The switch expression's temporary data must be saved while
4834 * we are executing the sub-statements (the cases).
4836 resolveStorageExpAlign(st->st_SwStmt.es_Exp,
4837 &sg->sg_TmpAlignMask);
4840 if (st->st_CaseStmt.es_Exp)
4841 resolveStorageExpAlign(st->st_CaseStmt.es_Exp,
4842 &sg->sg_TmpAlignMask);
4845 resolveStorageExpAlign(st->st_ExpStmt.es_Exp,
4846 &sg->sg_TmpAlignMask);
4848 case ST_ThreadSched:
4851 dassert_stmt(st, 0);
4855 * Calculate storage requirements for substatements. offset
4856 * acts as our base. We union the storage for the substatements
4857 * together. Note that often scan->sg_MyGroup == sg.
4859 RUNE_FOREACH(scan, &st->st_List, st_Node) {
4860 if (scan->st_Op == ST_Class) {
4861 ResolveAlignment(scan, flags);
4862 } else if (scan->st_Op == ST_Decl &&
4863 scan->st_DeclStmt.es_Decl->d_MyGroup !=
4869 } else if (scan->st_Op == ST_Decl &&
4870 (scan->st_DeclStmt.es_Decl->d_Flags & DF_RESOLVED)) {
4872 * See prior comments, skip declarations that
4873 * were moved to another context
4875 * (already resolved so can use junk offsets)
4877 resolveStorageDeclExpAlign(scan->st_DeclStmt.es_Decl,
4878 &sg->sg_TmpAlignMask);
4879 } else if (scan->st_Op == ST_Proc &&
4880 scan->st_ProcStmt.es_Decl->d_ProcDecl.ed_OrigBody == scan
4882 /* Do not resolve template procedures! */
4883 } else if (scan->st_Flags & STF_SEMTOP) {
4884 ResolveAlignment(scan, flags);
4886 ResolveAlignment(scan, flags);
4891 * If this is a new semantic level call resolveStorageSemGroup() to
4892 * do the final cleanup of SemGroup issues. This will redundantly
4893 * calculate temporary space requirements. Also, due to type/class
4894 * references the temporary space for a class may have already been
4895 * resolved. Since a class can only contain declarations it had
4896 * better match what we calculate here.
4898 * Note that for non-Class executable SemGroup's TmpBytes is
4899 * incorporated in a downward fashion while sg_Bytes is incorporated
4900 * in an upward fashion. It can become quite confusing. Don't ask
4901 * me why I did it that way.
4903 if (st->st_Flags & STF_SEMANTIC) {
4904 if ((sg->sg_Flags & SGF_TMPRESOLVED) == 0) {
4905 resolveStorageSemGroupAlign(sg);
4910 * Propagate alignment requirements upward.
4912 if ((st->st_Flags & (STF_SEMANTIC|STF_SEMTOP)) == STF_SEMANTIC) {
4913 if (sg->sg_Parent->sg_AlignMask < sg->sg_AlignMask)
4914 sg->sg_Parent->sg_AlignMask = sg->sg_AlignMask;
4915 if (sg->sg_Parent->sg_TmpAlignMask < sg->sg_TmpAlignMask)
4916 sg->sg_Parent->sg_TmpAlignMask = sg->sg_TmpAlignMask;
4921 * ResolveStorage() - Final storage resolution pass
4923 * This pass carefully scans the SemGroup hierarchy and assigns
4924 * offsets to declarations.
4926 * PROCEDURES - all the various 'executable' semantic layers in
4927 * a procedure are collapsed together for efficiency, so we only
4928 * have to manage one context. This means that the d_Offset
4929 * assigned to declarations in sub-blocks may exceed the sg_ size
4930 * of the sub-block's SemGroup. We do not attempt to resolve
4931 * procedure body templates (d_ProcDecl.ed_OrigBody).
4933 * CLASSES - are given offsets in their SemGroup's relative to 0, if
4934 * not already resolved.
4936 * IMPORTS - are given offsets in their SemGroup's relative to 0
4938 * COMPOUND TYPES - (such as procedure arguments) are given offsets
4939 * in their SemGroup's relative to 0.
4941 * TEMPORARY STORAGE - expressions may require temporary storage
4942 * for intermediate results. That space is reserved here.
4944 * We specifically do not resolve unrelated storage.
4948 ResolveStorage(Stmt *st, int flags)
4953 runesize_t ngoffset;
4954 SemGroup *sg = st->st_MyGroup;
4959 if (st->st_Op != ST_Class) {
4960 dassert((st->st_Flags & STF_RESOLVING) == 0);
4961 if (st->st_Flags & STF_RESOLVED) {
4964 st->st_Flags |= STF_RESOLVING;
4967 dassert(st->st_Flags & STF_ALIGNRESOLVED);
4968 if (st->st_Flags & STF_TMPRESOLVED)
4970 st->st_Flags |= STF_TMPRESOLVED;
4973 * If this is an executable semantic layer or an import layer then
4974 * assign storage to declarations up-front. Of the various
4975 * DOP_*_STORAGE ops, we should only see DOP_STACK_STORAGE and
4976 * DOP_GLOBAL_STORAGE.
4978 * Note: if this is the root ST_Import STF_SEMANTIC is *NOT* set and
4981 if ((st->st_Flags & STF_SEMANTIC) && st->st_Op != ST_Class) {
4984 dassert((sg->sg_Flags & (SGF_FRESOLVED|SGF_FRESOLVING)) == 0);
4986 sg->sg_Flags |= SGF_FRESOLVING;
4989 * The base offset for sub-semantic-blocks must match the
4990 * alignment they require in order to allow us to do an
4991 * aligned BZEROing of the space. We do not include the
4992 * temporary space here (it does not need to be BZERO'd).
4994 * NOTE: sg_TmpAlignMask is taken into accoun when the
4995 * top-level frame is allocated.
4997 if (st->st_Flags & STF_SEMTOP) {
4998 dassert(sg->sg_Bytes == 0);
5001 offset = sg->sg_Parent->sg_Bytes;
5002 offset = (offset + sg->sg_AlignMask) &
5006 sg->sg_BlkOffset = offset;
5008 RUNE_FOREACH(d, &sg->sg_DeclList, d_Node) {
5010 case DOP_STACK_STORAGE:
5011 case DOP_ARGS_STORAGE:
5012 case DOP_GROUP_STORAGE:
5013 type = d->d_StorDecl.ed_Type;
5014 offset = (offset + d->d_AlignMask) &
5016 dassert_decl(d, d->d_Offset == (runesize_t)-1);
5017 d->d_Offset = offset;
5018 offset += d->d_Bytes;
5019 if (d->d_StorDecl.ed_AssExp)
5020 sg->sg_Flags |= SGF_HASASS;
5021 if (type->ty_Flags & TF_HASASS)
5022 sg->sg_Flags |= SGF_HASASS;
5023 if (type->ty_Flags & TF_HASLVPTR)
5024 sg->sg_Flags |= SGF_HASLVPTR;
5026 case DOP_GLOBAL_STORAGE:
5027 type = d->d_StorDecl.ed_Type;
5028 sg->sg_GlobalBytes =
5029 (sg->sg_GlobalBytes + d->d_AlignMask) &
5031 dassert_decl(d, d->d_Offset == (runesize_t)-1);
5032 d->d_Offset = sg->sg_GlobalBytes;
5033 sg->sg_GlobalBytes += d->d_Bytes;
5034 if (d->d_StorDecl.ed_AssExp)
5035 sg->sg_Flags |= SGF_GHASASS;
5036 if (type->ty_Flags & TF_HASASS)
5037 sg->sg_Flags |= SGF_GHASASS;
5038 if (type->ty_Flags & TF_HASLVPTR)
5039 sg->sg_Flags |= SGF_GHASLVPTR;
5047 * The byte size of the block does not have to be aligned,
5048 * but aligning it (within reason) might provide a benefit.
5050 sg->sg_Bytes = offset;
5053 if (sg->sg_AlignMask < 256) {
5054 sg->sg_Bytes = (offset + sg->sg_AlignMask) &
5057 if (sg->sg_GlobalAlignMask < 256) {
5058 sg->sg_GlobalBytes =
5059 (sg->sg_GlobalBytes + sg->sg_GlobalAlignMask) &
5060 ~sg->sg_GlobalAlignMask;
5063 sg->sg_BlkBytes = sg->sg_Bytes - sg->sg_BlkOffset;
5064 sg->sg_Flags |= SGF_FRESOLVED;
5065 sg->sg_Flags &= ~SGF_FRESOLVING;
5069 * Figure out how much temporary space we need to be able to execute
5070 * statements and expressions. Temporary space, like the main
5071 * procedural space, must be inherited from and consolidated into
5072 * the top-level SemGroup
5075 offset = sg->sg_TmpBytes;
5077 goffset = sg->sg_GlobalTmpBytes;
5081 * Root ST_Import. avoid compiler warnings
5091 if (st->st_ImportStmt.es_DLL) {
5092 void (*func)(void) = dlsym(st->st_ImportStmt.es_DLL,
5103 resolveStorageDeclExp(st->st_TypedefStmt.es_Decl,
5104 &noffset, &ngoffset);
5109 * Temporary space for declarations are handled here.
5111 * Resolve declarations, skipping any whos context was
5112 * moved to a class (e.g. a declaration at the top level
5113 * of a file like Fd.setfd(...) also exists in the Fd class).
5119 d = st->st_DeclStmt.es_Decl;
5121 if (d->d_Op == DOP_GLOBAL_STORAGE)
5122 st->st_DeclStmt.es_TmpOffset = goffset;
5124 st->st_DeclStmt.es_TmpOffset = offset;
5125 printf("STDECLTMPOFFSET %zd\n", offset);
5126 for (i = 0; i < st->st_DeclStmt.es_DeclCount; ++i) {
5127 runesize_t xoffset = offset;
5128 runesize_t xgoffset = goffset;
5131 if (st->st_MyGroup != d->d_MyGroup) {
5132 /*printf("SKIPB %s\n", d->d_Id)*/;
5133 resolveStorageDeclExp(d, &xoffset, &xgoffset);
5134 } else if (d->d_Flags & DF_RESOLVED) {
5135 resolveStorageDeclExp(d, &xoffset, &xgoffset);
5139 resolveStorageDeclExp(
5144 if (noffset < xoffset)
5146 if (ngoffset < xgoffset)
5147 ngoffset = xgoffset;
5148 d = RUNE_NEXT(d, d_Node);
5162 if (st->st_LoopStmt.es_BCond) {
5164 resolveStorageExp(st->st_LoopStmt.es_BCond,
5166 if (noffset < xoffset)
5169 if (st->st_LoopStmt.es_ACond) {
5171 resolveStorageExp(st->st_LoopStmt.es_ACond,
5173 if (noffset < xoffset)
5176 if (st->st_LoopStmt.es_AExp) {
5178 resolveStorageExp(st->st_LoopStmt.es_AExp,
5180 if (noffset < xoffset)
5190 resolveStorageExp(st->st_IfStmt.es_Exp, &noffset);
5193 if (st->st_RetStmt.es_Exp)
5194 resolveStorageExp(st->st_RetStmt.es_Exp, &noffset);
5197 if (st->st_ResStmt.es_Exp)
5198 resolveStorageExp(st->st_ResStmt.es_Exp, &noffset);
5202 * The switch expression's temporary data must be saved while
5203 * we are executing the sub-statements (the cases).
5205 resolveStorageExp(st->st_SwStmt.es_Exp, &noffset);
5210 if (st->st_CaseStmt.es_Exp)
5211 resolveStorageExp(st->st_CaseStmt.es_Exp, &noffset);
5214 resolveStorageExp(st->st_ExpStmt.es_Exp, &noffset);
5216 case ST_ThreadSched:
5219 dassert_stmt(st, 0);
5223 * Calculate storage requirements for substatements. offset
5224 * acts as our base. We union the storage for the substatements
5225 * together. Note that often scan->sg_MyGroup == sg.
5227 RUNE_FOREACH(scan, &st->st_List, st_Node) {
5228 dassert(scan->st_Op != ST_Proc);
5229 if (scan->st_Op == ST_Class) {
5230 ResolveStorage(scan, flags);
5232 } else if (scan->st_Op == ST_Decl &&
5233 scan->st_DeclStmt.es_Decl->d_MyGroup !=
5236 * See prior comments, skip declarations that
5237 * were moved to another context.
5239 * (does not belong in context so can use
5242 runesize_t junk1 = 0;
5243 runesize_t junk2 = 0;
5245 printf("SKIPC %s\n",
5246 scan->st_DeclStmt.es_Decl->d_Id);
5248 resolveStorageDeclExp(scan->st_DeclStmt.es_Decl,
5250 } else if (scan->st_Op == ST_Decl &&
5251 (scan->st_DeclStmt.es_Decl->d_Flags & DF_RESOLVED)) {
5253 * See prior comments, skip declarations that
5254 * were moved to another context
5256 * (already resolved so can use junk offsets)
5258 runesize_t junk1 = 0;
5259 runesize_t junk2 = 0;
5261 printf("SKIPD %s\n",
5262 scan->st_DeclStmt.es_Decl->d_Id);
5264 runesize_t save_offset;
5265 runesize_t save_goffset;
5266 save_offset = scan->st_MyGroup->sg_TmpBytes;
5267 save_goffset = scan->st_MyGroup->sg_GlobalTmpBytes;
5268 scan->st_MyGroup->sg_TmpBytes = offset;
5269 scan->st_MyGroup->sg_GlobalTmpBytes = goffset;
5270 resolveStorageDeclExp(scan->st_DeclStmt.es_Decl,
5272 if (scan->st_MyGroup->sg_TmpBytes < save_offset)
5273 scan->st_MyGroup->sg_TmpBytes = save_offset;
5274 if (scan->st_MyGroup->sg_GlobalTmpBytes < save_goffset) {
5275 scan->st_MyGroup->sg_GlobalTmpBytes = save_goffset;
5277 if (noffset < scan->st_MyGroup->sg_TmpBytes)
5278 noffset = scan->st_MyGroup->sg_TmpBytes;
5279 if (ngoffset < scan->st_MyGroup->sg_GlobalTmpBytes)
5280 ngoffset = scan->st_MyGroup->sg_GlobalTmpBytes;
5282 } else if (scan->st_Op == ST_Proc) {
5283 /* Do not resolve template procedures! */
5284 fprintf(stderr, "STORAGE %s\n", scan->st_ProcStmt.es_Decl->d_Id);
5285 if (scan->st_ProcStmt.es_Decl->d_ProcDecl.ed_OrigBody == scan) {
5288 } else if (scan->st_Flags & STF_SEMTOP) {
5289 assert(scan->st_MyGroup != sg);
5290 ResolveStorage(scan, flags);
5293 * This is a bit of a mess. The baseline
5294 * sg_TmpBytes needs to be set so calculated
5295 * temporary offsets are relative to it, and
5296 * then restored. Otherwise we might blow
5297 * away the SGF_TMPRESOLVED SemGroup
5301 runesize_t save_offset;
5302 runesize_t save_goffset;
5303 save_offset = scan->st_MyGroup->sg_TmpBytes;
5304 save_goffset = scan->st_MyGroup->sg_GlobalTmpBytes;
5305 scan->st_MyGroup->sg_TmpBytes = offset;
5306 scan->st_MyGroup->sg_GlobalTmpBytes = goffset;
5307 ResolveStorage(scan, flags);
5309 if (scan->st_MyGroup->sg_TmpBytes < save_offset)
5310 scan->st_MyGroup->sg_TmpBytes = save_offset;
5311 if (scan->st_MyGroup->sg_GlobalTmpBytes < save_goffset) {
5312 scan->st_MyGroup->sg_GlobalTmpBytes = save_goffset;
5314 if (noffset < scan->st_MyGroup->sg_TmpBytes)
5315 noffset = scan->st_MyGroup->sg_TmpBytes;
5316 if (ngoffset < scan->st_MyGroup->sg_GlobalTmpBytes)
5317 ngoffset = scan->st_MyGroup->sg_GlobalTmpBytes;
5322 * If this is a new semantic level call resolveStorageSemGroup() to
5323 * do the final cleanup of SemGroup issues. This will redundantly
5324 * calculate temporary space requirements. Also, due to type/class
5325 * references the temporary space for a class may have already been
5326 * resolved. Since a class can only contain declarations it had
5327 * better match what we calculate here.
5329 * Note that for non-Class executable SemGroup's TmpBytes is
5330 * incorporated in a downward fashion while sg_Bytes is incorporated
5331 * in an upward fashion. It can become quite confusing. Don't ask
5332 * me why I did it that way.
5334 if (st->st_Flags & STF_SEMANTIC) {
5335 if ((sg->sg_Flags & SGF_TMPRESOLVED) == 0) {
5336 resolveStorageSemGroup(sg, noffset, ngoffset);
5338 dassert(sg->sg_TmpBytes == noffset &&
5339 sg->sg_GlobalTmpBytes == ngoffset);
5342 sg->sg_TmpBytes = noffset;
5343 sg->sg_GlobalTmpBytes = ngoffset;
5344 } /* else this is the Root st_Import */
5346 if ((st->st_Flags & (STF_SEMANTIC|STF_SEMTOP)) == STF_SEMANTIC) {
5347 sg->sg_Parent->sg_Bytes = sg->sg_Bytes;
5352 * resolveStorageDeclExp() - resolve the storage reservation required to
5353 * process an expression.
5355 * This is an expression tree traversal storage resolution procedure.
5356 * We have to traverse through declarations to get to default assignments
5359 * If a declaration has no assigned default the underlying type may
5360 * itself have an assigned default which must be dealt with.
5363 resolveStorageDeclExpAlign(Declaration *d, runesize_t *expalignp)
5367 /* recursion already dealt with */
5369 case DOP_ARGS_STORAGE:
5370 case DOP_STACK_STORAGE:
5371 case DOP_GROUP_STORAGE:
5373 Type *type = d->d_StorDecl.ed_Type;
5375 resolveStorageTypeExpAlign(type, expalignp);
5376 if (d->d_StorDecl.ed_AssExp) {
5377 resolveStorageExpAlign(d->d_StorDecl.ed_AssExp,
5382 case DOP_GLOBAL_STORAGE:
5384 Type *type = d->d_StorDecl.ed_Type;
5386 resolveStorageTypeExpAlign(type, expalignp);
5387 if (d->d_StorDecl.ed_AssExp) {
5388 resolveStorageExpAlign(d->d_StorDecl.ed_AssExp,
5395 * Never try to resolve storage considerations for an
5396 * alias's assignment in the declaration itself. The
5397 * run-time context depends on who and how many other
5398 * parts of the program reference the alias and the expression
5399 * tree will be duplicated for each.
5402 resolveStorageExpExp(d->d_AliasDecl.ed_AssExp, expalignp);
5406 /* XXX what about ty_AssExp ? should be in global space */
5409 /* recursion already dealt with */
5413 * Resolution of procedure declarations might have been
5414 * deferred (see TOK_ID in resolveExp()).
5420 if ((st = d->d_ProcDecl.ed_ProcBody) != NULL) {
5421 ResolveAlignment(st, 0);
5431 resolveStorageDeclExp(Declaration *d, runesize_t *offset, runesize_t *goffset)
5435 /* recursion already dealt with */
5437 case DOP_ARGS_STORAGE:
5438 case DOP_STACK_STORAGE:
5439 case DOP_GROUP_STORAGE:
5441 Type *type = d->d_StorDecl.ed_Type;
5442 runesize_t save_offset = *offset;
5444 resolveStorageType(type, &save_offset, 0);
5445 if (d->d_StorDecl.ed_AssExp) {
5446 resolveStorageExp(d->d_StorDecl.ed_AssExp,
5449 if (*offset < save_offset)
5450 *offset = save_offset;
5453 case DOP_GLOBAL_STORAGE:
5455 Type *type = d->d_StorDecl.ed_Type;
5456 runesize_t save_offset = *goffset;
5458 resolveStorageType(type, &save_offset, 1);
5459 if (d->d_StorDecl.ed_AssExp) {
5460 resolveStorageExp(d->d_StorDecl.ed_AssExp,
5463 if (*goffset < save_offset)
5464 *goffset = save_offset;
5469 * Never try to resolve storage considerations for an
5470 * alias's assignment in the declaration itself. The
5471 * run-time context depends on who and how many other
5472 * parts of the program reference the alias and the expression
5473 * tree will be duplicated for each.
5476 if (d->d_ScopeFlags & SCOPE_GLOBAL)
5477 resolveStorageExp(d->d_AliasDecl.ed_AssExp, NULL, NULL);
5479 resolveStorageExp(d->d_AliasDecl.ed_AssExp, NULL, NULL);
5483 /* XXX what about ty_AssExp ? should be in global space */
5486 /* recursion already dealt with */
5492 if ((st = d->d_ProcDecl.ed_ProcBody) != NULL) {
5493 ResolveStorage(st, 0);
5503 * resolveStorageExp() - resolve the temporary storage required to
5504 * support the expression, if any.
5506 * We do not need to assign storage for expressions which return
5507 * lvalues, because they will simply return a pointer into
5508 * non-temporary storage.
5511 resolveStorageExpOnly(Exp *exp, runesize_t *offset)
5516 * Stop if the expression resolves to a type rather then a value,
5517 * e.g. when you do something like switch (typeof(int)) { ... }
5518 * Types are handled as thin pointers.
5520 exp->ex_Flags |= EXF_TMPRESOLVED;
5521 if (exp->ex_Flags & EXF_RET_TYPE) {
5522 *offset = (*offset + POINTER_ALIGN - 1) & ~(POINTER_ALIGN - 1);
5523 exp->ex_TmpOffset = *offset;
5524 *offset += sizeof(void *);
5530 * Assign temporary offset. This offset does not overlap temporary
5531 * space reserved for sub-expressions.
5533 * We must have an assigned type. Expression sequences like:
5534 * 'module.blah' are collapsed into 'blah' long before we get
5535 * here, or they should be. We should not encounter any
5536 * TOK_TCMV_ID expression tokens. Structural id's (the right hand
5537 * side of X.Y) are resolved by their parent expression node and
5538 * no typing or temporary space is required.
5540 * Expressions that return lvalues do not need temporary space.
5542 type = exp->ex_Type;
5544 switch(exp->ex_Token) {
5549 printf("EXP %p %04x %p\n",
5550 exp, exp->ex_Token, exp->ex_Decl);
5551 dassert_exp(exp, 0);
5554 exp->ex_TmpOffset = -3;
5555 } else if (type->ty_SQFlags & SF_LVALUE) {
5557 * Expressive elements which return lvalues do not get
5558 * temporary space. Note that this also prevents lvalues
5559 * such as large arrays (int ary[999999999]) from reserving
5560 * unnecessary stack space.
5562 * NOTE: SF_LVALUE is unrelated to SCOPE_LVALUE. SCOPE_LVALUE
5563 * applies to SemGroup storage (LValueStor). SF_LVALUE
5564 * merely flags the type for an expression as expecting
5565 * or not expecting an lvalue.
5569 * XXX removeme, LValueStor only applies to semgroups
5571 runesize_t lvmask = sizeof(LValueStor) - 1;
5572 *offset = (*offset + lvmask) & ~lvmask;
5573 exp->ex_TmpOffset = *offset;
5574 *offset = *offset + (lvmask + 1);
5576 exp->ex_TmpOffset = -2;
5579 * Reserve temporary space for potential intermediate
5582 * Compound expressions may need extra space to default-init
5583 * the compound value, it is expected to be available to the
5584 * generator right after the nominal type in the TmpOffset.
5585 * XXX also make available to the interpreter?
5587 * Procedure calls also may need extra space to default-init
5588 * the return value. XXX also make available to the
5591 *offset = (*offset + type->ty_AlignMask) & ~type->ty_AlignMask;
5592 exp->ex_TmpOffset = *offset;
5593 *offset = *offset + type->ty_Bytes;
5594 if (exp->ex_Token == TOK_COMPOUND) {
5596 * NOTE: type might not yet be changed to compound,
5597 * but single-element compound will use the
5598 * same temporary space.
5600 *offset += type->ty_TmpBytes;
5601 } else if (exp->ex_Token == TOK_CALL) {
5602 *offset += type->ty_TmpBytes;
5605 dassert(exp->ex_TmpOffset != -1);
5610 resolveStorageExpSub(Exp *exp, runesize_t *offset)
5614 * Early term. XXX don't do this. For the moment we have an issue
5615 * with how typeof() processes temporary expression storage. This
5616 * needs to be comprehensively fixed but it can be an issue if the
5617 * content is a dynamic type (via a ref or a var-args element)
5618 * so it is not trivial.
5620 if (exp->ex_Flags & EXF_RET_TYPE)
5624 resolveStorageType(exp->ex_Type, offset, 0);
5627 * Calculate the overlapping temporary space for sub-trees.
5629 if (exp->ex_Flags & EXF_BINARY) {
5631 * Ensure lhs's NON-RECURSIVE temporary storage on-return
5632 * does not intefere with rhs's, or vise-versa.
5634 * To do this offset the rhs storage by the non-recursive
5642 resolveStorageExp(exp->ex_Lhs, &xoffset);
5643 if (*offset < xoffset)
5645 if (exp->ex_Lhs->ex_TmpOffset >= 0) {
5646 xoffset = exp->ex_Lhs->ex_TmpOffset +
5647 exp->ex_Lhs->ex_Type->ty_Bytes;
5651 resolveStorageExp(exp->ex_Rhs, &xoffset);
5652 if (*offset < xoffset)
5654 } else if (exp->ex_Flags & EXF_UNARY) {
5655 resolveStorageExp(exp->ex_Lhs, offset);
5656 dassert_exp(exp, exp->ex_Lhs->ex_Next == NULL);
5657 } else if (exp->ex_Flags & EXF_COMPOUND) {
5659 * each element will be copied into the compound storage
5660 * in turn, so we can union the temporary storage required
5667 for (scan = exp->ex_Lhs; scan; scan = scan->ex_Next) {
5668 runesize_t xoffset = *offset;
5670 dassert_exp(scan, scan->ex_Type != NULL);
5672 resolveStorageExp(scan, &xoffset);
5673 if (noffset < xoffset)
5680 if (exp->ex_Token == TOK_CALL && exp->ex_Lhs->ex_Decl) {
5681 Declaration *d = exp->ex_Lhs->ex_Decl;
5682 fprintf(stderr, "FIXUP CALL %s type %p\n", d->d_Id, d->d_ProcDecl.ed_Type);
5683 dassert(d->d_Op == DOP_PROC);
5684 resolveStorageType(d->d_ProcDecl.ed_Type, offset, 0);
5689 /* XXX what about alias assign-expressions */
5690 else if (exp->ex_Flags & EXF_ALIAS) {
5692 dassert_decl(exp->ex_Decl,
5693 (exp->ex_Decl->d_ScopeFlags & SCOPE_GLOBAL) == 0);
5695 resolveStorageExp(exp->ex_Decl->d_AliasDecl.ed_AssExp, offset);
5701 * [re]resolve temporary storage requirements.
5703 * WARNING! This may be called more than once if an expression requires
5704 * resolve-time interpretation to generate a constant. In this
5705 * ex_TmpOffset for the sub-chain may be regenerated from 0,
5706 * and then just the top-level (post-constant-resolved)
5707 * ex_TmpOffset will be restored by the caller.
5710 resolveStorageExp(Exp *exp, runesize_t *offset)
5716 noffset = resolveStorageExpOnly(exp, &xoffset);
5718 resolveStorageExpSub(exp, &xoffset);
5719 if (*offset < xoffset)
5724 resolveStorageExpAlign(Exp *exp, runesize_t *expalignp)
5728 if (exp->ex_Flags & EXF_RET_TYPE) {
5729 if (*expalignp < POINTER_ALIGN)
5730 *expalignp = POINTER_ALIGN;
5734 resolveDecl(exp->ex_Decl, 0);
5738 type = exp->ex_Type;
5744 if (type->ty_SQFlags & SF_LVALUE) {
5745 if (*expalignp < POINTER_ALIGN)
5746 *expalignp = POINTER_ALIGN;
5748 if (*expalignp < type->ty_AlignMask)
5749 *expalignp = type->ty_AlignMask;
5751 resolveStorageTypeExpAlign(type, expalignp);
5754 if (exp->ex_Flags & EXF_BINARY) {
5755 resolveStorageExpAlign(exp->ex_Lhs, expalignp);
5756 resolveStorageExpAlign(exp->ex_Rhs, expalignp);
5757 } else if (exp->ex_Flags & EXF_UNARY) {
5758 resolveStorageExpAlign(exp->ex_Lhs, expalignp);
5759 } else if (exp->ex_Flags & EXF_COMPOUND) {
5762 for (scan = exp->ex_Lhs; scan; scan = scan->ex_Next) {
5763 resolveStorageExpAlign(scan, expalignp);
5766 } else if (exp->ex_Flags & EXF_ALIAS) {
5767 resolveStorageExpAlign(exp->ex_Decl->d_AliasDecl.ed_AssExp,
5773 if (exp->ex_Token == TOK_CALL && exp->ex_Lhs->ex_Decl) {
5774 Declaration *d = exp->ex_Lhs->ex_Decl;
5775 dassert(d->d_Op == DOP_PROC);
5776 resolveStorageTypeExpAlign(d->d_ProcDecl.ed_Type, expalignp);
5777 if (d->d_ProcDecl.ed_ProcBody)
5778 ResolveAlignment(d->d_ProcDecl.ed_ProcBody, 0);
5784 * resolveStorageType() - temporary space required to initialize type defaults
5786 * Figure out the temporary space required to initialize a type's
5787 * defaults. Note that the space will be figured independantly
5788 * for any SemGroup's.
5792 resolveStorageTypeExpAlign(Type *type, runesize_t *expalignp)
5794 SemGroup *sg = NULL;
5795 Type *subtype1 = NULL;
5796 Type *subtype2 = NULL;
5798 if (type->ty_Flags & TF_ALIGNRESOLVED) {
5799 if (*expalignp < type->ty_TmpAlignMask)
5800 *expalignp = type->ty_TmpAlignMask;
5803 type->ty_Flags |= TF_ALIGNRESOLVED;
5805 switch(type->ty_Op) {
5807 sg = type->ty_ClassType.et_SemGroup;
5810 subtype1 = type->ty_AryType.et_Type;
5813 sg = type->ty_CompType.et_SemGroup;
5816 subtype1 = type->ty_ProcType.et_ArgsType;
5817 subtype2 = type->ty_ProcType.et_RetType;
5820 sg = type->ty_ImportType.et_SemGroup;
5823 sg = type->ty_ArgsType.et_SemGroup;
5826 sg = type->ty_VarType.et_SemGroup;
5829 /* has nothing to do with initializing the pointer */
5830 /* subtype1 = type->ty_CPtrType.et_Type; */
5833 /* has nothing to do with initializing the pointer */
5834 /* subtype1 = type->ty_PtrType.et_Type; */
5837 /* has nothing to do with initializing the pointer */
5838 /* subtype1 = type->ty_RefType.et_Type; */
5843 * nothing to be done here.
5846 case TY_UNRESOLVED: /* should be no unresolved types at this stage */
5848 dassert_type(type, 0);
5852 resolveStorageTypeExpAlign(subtype1, &subtype1->ty_TmpAlignMask);
5853 if (subtype1->ty_AssExp) {
5854 resolveStorageExpAlign(subtype1->ty_AssExp,
5855 &subtype1->ty_TmpAlignMask);
5857 if (type->ty_TmpAlignMask < subtype1->ty_TmpAlignMask)
5858 type->ty_TmpAlignMask = subtype1->ty_TmpAlignMask;
5861 resolveStorageTypeExpAlign(subtype2, &subtype2->ty_TmpAlignMask);
5862 if (subtype2->ty_AssExp) {
5863 resolveStorageExpAlign(subtype2->ty_AssExp,
5864 &subtype2->ty_TmpAlignMask);
5866 if (type->ty_TmpAlignMask < subtype2->ty_TmpAlignMask)
5867 type->ty_TmpAlignMask = subtype2->ty_TmpAlignMask;
5869 if (type->ty_AssExp) {
5870 resolveStorageExpAlign(type->ty_AssExp, &type->ty_TmpAlignMask);
5873 if (resolveSemGroup1(sg, 0) && resolveSemGroup2(sg, 0))
5874 resolveSemGroup3(sg, 0);
5875 resolveStorageSemGroupAlign(sg);
5876 if (type->ty_TmpAlignMask < sg->sg_TmpAlignMask)
5877 type->ty_TmpAlignMask = sg->sg_TmpAlignMask;
5879 if (*expalignp < type->ty_TmpAlignMask)
5880 *expalignp = type->ty_TmpAlignMask;
5885 resolveStorageType(Type *type, runesize_t *offset, int isglob)
5887 SemGroup *sg = NULL;
5888 Type *subtype1 = NULL;
5889 Type *subtype2 = NULL;
5890 runesize_t save_offset1;
5891 runesize_t save_offset2;
5892 runesize_t save_offset3;
5893 runesize_t save_offsetx;
5895 dassert(type->ty_Flags & TF_ALIGNRESOLVED);
5896 if (type->ty_Flags & TF_TMPRESOLVED)
5898 type->ty_Flags |= TF_TMPRESOLVED;
5900 switch(type->ty_Op) {
5902 sg = type->ty_ClassType.et_SemGroup;
5905 subtype1 = type->ty_AryType.et_Type;
5908 sg = type->ty_CompType.et_SemGroup;
5911 subtype1 = type->ty_ProcType.et_ArgsType;
5912 subtype2 = type->ty_ProcType.et_RetType;
5915 sg = type->ty_ImportType.et_SemGroup;
5918 sg = type->ty_ArgsType.et_SemGroup;
5921 sg = type->ty_VarType.et_SemGroup;
5924 /* has nothing to do with initializing the pointer */
5925 /* subtype1 = type->ty_CPtrType.et_Type; */
5928 /* has nothing to do with initializing the pointer */
5929 /* subtype1 = type->ty_PtrType.et_Type; */
5932 /* has nothing to do with initializing the pointer */
5933 /* subtype1 = type->ty_RefType.et_Type; */
5938 * nothing to be done here.
5941 case TY_UNRESOLVED: /* should be no unresolved types at this stage */
5943 dassert_type(type, 0);
5946 save_offset1 = *offset;
5947 save_offset2 = *offset;
5948 save_offset3 = *offset;
5949 save_offsetx = *offset;
5951 /*resolveType(subtype1, NULL, 0);*/
5952 resolveStorageType(subtype1, &subtype1->ty_TmpBytes, 0);
5953 if (subtype1->ty_AssExp) {
5954 resolveStorageExp(subtype1->ty_AssExp,
5955 &subtype1->ty_TmpBytes);
5957 save_offset1 += subtype1->ty_TmpBytes;
5958 if (type->ty_TmpAlignMask < subtype1->ty_TmpAlignMask)
5959 type->ty_TmpAlignMask = subtype1->ty_TmpAlignMask;
5962 /*resolveType(subtype2, NULL, 0);*/
5963 resolveStorageType(subtype2, &subtype2->ty_TmpBytes, 0);
5964 if (subtype2->ty_AssExp) {
5965 resolveStorageExp(subtype2->ty_AssExp,
5966 &subtype2->ty_TmpBytes);
5968 save_offset2 += subtype2->ty_TmpBytes;
5969 if (type->ty_TmpAlignMask < subtype2->ty_TmpAlignMask)
5970 type->ty_TmpAlignMask = subtype2->ty_TmpAlignMask;
5972 if (type->ty_AssExp) {
5973 resolveStorageExp(type->ty_AssExp, &type->ty_TmpBytes);
5976 if (resolveSemGroup1(sg, 0) && resolveSemGroup2(sg, 0))
5977 resolveSemGroup3(sg, 0);
5978 resolveStorageSemGroup(sg, 0, 0);
5980 save_offset3 += sg->sg_GlobalTmpBytes;
5982 save_offset3 += sg->sg_TmpBytes;
5985 if (*offset < save_offset1)
5986 *offset = save_offset1;
5987 if (*offset < save_offset2)
5988 *offset = save_offset2;
5989 if (*offset < save_offset3)
5990 *offset = save_offset3;
5991 type->ty_TmpBytes = *offset - save_offsetx;
5995 * This is used to resolve temporary storage requirements for
5996 * SemGroup's related to classes and compound types. Temporary storage
5997 * requirements are calculated on a SemGroup-by-SemGroup basis and not
5998 * aggregated into any parent.
6000 * In the final pass we also reverse the constructor and destructor lists
6001 * (sg_CBase and sg_DBase), and the pointer/lvalue list (SRBase). These
6002 * lists were originally constructed by prepending and are thus in the
6007 resolveStorageSemGroupAlign(SemGroup *sg)
6011 if (sg->sg_Flags & SGF_ALIGNRESOLVED)
6013 sg->sg_Flags |= SGF_ALIGNRESOLVED;
6016 * SGF_RESOLVED might not be set. This can only happen because we
6017 * allow individual declarations in global SemGroups to be resolved
6018 * without having to resolve the whole group. This allows unused
6019 * declarations to be omitted by the code generator.
6021 if ((sg->sg_Flags & SGF_RESOLVED) == 0)
6022 sg->sg_Flags |= SGF_RESOLVED;
6024 RUNE_FOREACH(d, &sg->sg_DeclList, d_Node) {
6025 resolveStorageDeclExpAlign(d, &sg->sg_TmpAlignMask);
6026 if (d->d_ScopeFlags & SCOPE_GLOBAL) {
6027 if (sg->sg_GlobalAlignMask < d->d_AlignMask)
6028 sg->sg_GlobalAlignMask = d->d_AlignMask;
6030 if (sg->sg_AlignMask < d->d_AlignMask)
6031 sg->sg_AlignMask = d->d_AlignMask;
6038 resolveStorageSemGroup(SemGroup *sg, runesize_t noffset, runesize_t ngoffset)
6044 if ((sg->sg_Flags & SGF_RESOLVED) == 0) {
6045 if (resolveSemGroup1(sg, 0) && resolveSemGroup2(sg, 0))
6046 resolveSemGroup3(sg, 0);
6049 dassert(sg->sg_Flags & SGF_ALIGNRESOLVED);
6050 if (sg->sg_Flags & SGF_TMPRESOLVED)
6052 sg->sg_Flags |= SGF_TMPRESOLVED;
6054 RUNE_FOREACH(d, &sg->sg_DeclList, d_Node) {
6055 runesize_t offset = 0;
6056 runesize_t goffset = 0;
6058 resolveStorageDeclExp(d, &offset, &goffset);
6059 if (noffset < offset)
6061 if (ngoffset < goffset)
6064 if ((d2 = sg->sg_CBase) != NULL) {
6065 sg->sg_CBase = NULL;
6066 while ((d = d2) != NULL) {
6068 d->d_CNext = sg->sg_CBase;
6072 if ((d2 = sg->sg_DBase) != NULL) {
6073 sg->sg_DBase = NULL;
6074 while ((d = d2) != NULL) {
6076 d->d_DNext = sg->sg_DBase;
6080 if ((d2 = sg->sg_GBase) != NULL) {
6081 sg->sg_GBase = NULL;
6082 while ((d = d2) != NULL) {
6084 d->d_GNext = sg->sg_GBase;
6088 if ((d2 = sg->sg_SRBase) != NULL) {
6089 sg->sg_SRBase = NULL;
6090 while ((d = d2) != NULL) {
6092 d->d_SRNext = sg->sg_SRBase;
6096 sg->sg_TmpBytes = noffset;
6097 sg->sg_GlobalTmpBytes = ngoffset;
6101 * Return non-zero if the method procedure wants the 'this' variable
6102 * to be an lvalue-pointer rather than an lvalue-target-object. In this
6103 * situation we do not want to indirect the pointer.
6107 methodProcThisIsPointer(Type *type)
6113 dassert(type->ty_Op == TY_PROC);
6114 dassert(type->ty_ProcType.et_ArgsType->ty_Op == TY_ARGS);
6115 sg = type->ty_ProcType.et_ArgsType->ty_CompType.et_SemGroup;
6116 d = RUNE_FIRST(&sg->sg_DeclList);
6117 dassert(d->d_Id == String_This);
6118 switch (d->d_StorDecl.ed_Type->ty_Op) {
6127 "methodProcThisIsPointer(): method call through "
6128 "C pointer is illegal\n");
6140 * Calculate SG dependencies
6142 #define SGDEP_HSIZE 1024
6143 #define SGDEP_HMASK (SGDEP_HSIZE - 1)
6145 SGDepend *SGDepHash[SGDEP_HSIZE];
6146 SemGroup *SGCurrentDep;
6150 resolveSGDependHash(SemGroup *src, SemGroup *dst)
6154 hv = ((intptr_t)src >> 7) ^ ((intptr_t)dst >> 5);
6156 return (&SGDepHash[hv & SGDEP_HMASK]);
6161 resolvePushSGDepend(SemGroup *sg)
6167 depp = resolveSGDependHash(SGCurrentDep, sg);
6168 for (dep = *depp; dep; dep = dep->hnext) {
6169 if (dep->src == SGCurrentDep && dep->dst == sg)
6173 dep = zalloc(sizeof(SGDepend));
6175 dep->src = SGCurrentDep;
6179 dep->next = SGCurrentDep->sg_DepFirst;
6180 SGCurrentDep->sg_DepFirst = dep;
6183 last = SGCurrentDep;
6191 resolvePopSGDepend(SemGroup *dep)