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_Flags & DF_ONGLIST) == 0 &&
851 (d->d_ScopeFlags & (SCOPE_CONSTRUCTOR |
852 SCOPE_DESTRUCTOR))) {
853 d->d_GNext = d->d_MyGroup->sg_GBase;
854 d->d_MyGroup->sg_GBase = d;
855 d->d_Flags |= DF_ONGLIST;
858 if ((d->d_Flags & DF_ONCLIST) == 0 &&
859 (d->d_ScopeFlags & SCOPE_CONSTRUCTOR)) {
860 d->d_CNext = d->d_MyGroup->sg_CBase;
861 d->d_MyGroup->sg_CBase = d;
862 d->d_Flags |= DF_ONCLIST;
864 if ((d->d_Flags & DF_ONDLIST) == 0 &&
865 (d->d_ScopeFlags & SCOPE_DESTRUCTOR)) {
866 d->d_DNext = d->d_MyGroup->sg_DBase;
867 d->d_MyGroup->sg_DBase = d;
868 d->d_Flags |= DF_ONDLIST;
873 * If this procedure is bound to a DLL we have to resolve
876 if (d->d_ScopeFlags & SCOPE_CLANG) {
877 d->d_ProcDecl.ed_DLLFunc =
878 FindDLLSymbol(NULL, d->d_ImportSemGroup,
882 case DOP_ARGS_STORAGE:
883 case DOP_STACK_STORAGE:
884 case DOP_GLOBAL_STORAGE:
885 case DOP_GROUP_STORAGE:
886 type = RESOLVETYPE(d->d_StorDecl.ed_Type);
887 d->d_StorDecl.ed_Type = type;
890 * Promote the lvalue storage qualifier (e.g. from a typedef)
891 * into the declaration's scope. This is what ultimately
892 * controls lvalue vs rvalue arguments to procedures and such.
894 if ((type->ty_SQFlags & SF_LVALUE) &&
895 (d->d_ScopeFlags & SCOPE_LVALUE) == 0
897 d->d_ScopeFlags |= SCOPE_LVALUE;
901 * Default assignment handling expects an rvalue.
903 if (d->d_StorDecl.ed_AssExp) {
904 d->d_StorDecl.ed_AssExp =
905 resolveExp(d->d_ImportSemGroup, d->d_MyGroup,
906 d->d_StorDecl.ed_AssExp,
908 flags | RESOLVE_AUTOCAST);
910 if (d->d_ScopeFlags & SCOPE_LVALUE) {
912 * Object is passed as a LValueStor structure. Note
913 * that d_Bytes is going to be different then the
914 * underlying type (which represents the actual
917 d->d_Bytes = sizeof(LValueStor);
918 d->d_AlignMask = LVALUE_ALIGN;
921 * Object is passed by value.
923 d->d_AlignMask = type->ty_AlignMask;
924 d->d_Bytes = type->ty_Bytes;
928 * If the declaration represents or contains an
929 * argument-lvalue or a pointer we have to add it to
930 * the SemGroup's SRBase list to properly reference or
931 * dereference the elements. XXX only do this for non-global
934 * If the declaration has LVALUE scope we must do the same
935 * because the ref is tracked.
937 if (d->d_Op != DOP_GLOBAL_STORAGE &&
938 (type->ty_Flags & TF_HASLVPTR)) {
939 d->d_SRNext = d->d_MyGroup->sg_SRBase;
940 d->d_MyGroup->sg_SRBase = d;
941 } else if (d->d_ScopeFlags & SCOPE_LVALUE) {
942 d->d_SRNext = d->d_MyGroup->sg_SRBase;
943 d->d_MyGroup->sg_SRBase = d;
947 * Deal with constructor/destructor chaining. The chaining
948 * winds up being reversed and will be corrected by the
951 if (type->ty_Flags & TF_HASCONSTRUCT) {
952 d->d_CNext = d->d_MyGroup->sg_CBase;
953 d->d_MyGroup->sg_CBase = d;
955 if (type->ty_Flags & TF_HASDESTRUCT) {
956 d->d_DNext = d->d_MyGroup->sg_DBase;
957 d->d_MyGroup->sg_DBase = d;
959 if (type->ty_Flags & (TF_HASGCONSTRUCT|TF_HASGDESTRUCT)) {
960 d->d_GNext = d->d_MyGroup->sg_GBase;
961 d->d_MyGroup->sg_GBase = d;
965 * Automatic content-locking is only applicable to objects
966 * that are or contain lvalues, pointers, or references.
967 * Setting UNLOCKED relaxes requirements on taking the
968 * address of the object.
970 * Automatic content-locking is not performed on class objects
971 * or arrays. We can set those to unlocked as well also
974 if ((d->d_Op & DOPF_STORAGE) &&
975 (d->d_Scope.s_Flags & SCOPE_LVALUE) == 0) {
976 if ((type->ty_Flags & TF_HASLVPTR) == 0 ||
977 type->ty_Op == TY_CLASS ||
978 type->ty_Op == TY_ARYOF) {
979 d->d_ScopeFlags |= SCOPE_UNLOCKED;
987 d->d_Flags &= ~DF_RESOLVING;
988 d->d_Flags |= DF_RESOLVED;
991 * Post resolution flag resolving (to handle recursion)
996 * Create copies of procedures as they are needed (thus
997 * avoiding an XxY matrix effect).
999 if ((st = d->d_ProcDecl.ed_OrigBody) == NULL) {
1000 Declaration *super = d->d_Super;
1001 while (super && super->d_ProcDecl.ed_OrigBody == NULL) {
1002 super = super->d_Super;
1005 st = super->d_ProcDecl.ed_OrigBody;
1006 if (super->d_MyGroup->sg_Stmt->st_Op == ST_Class) {
1008 * Copy-down a procedure from a
1009 * superclass. The procedure must
1010 * still be linked into its superclass
1011 * for semantic searches to work as
1012 * expected, hence the use of super->
1013 * d_MyGroup and st->st_Parent.
1015 * Note that this code is not reached
1016 * in the case of a nested procedure,
1017 * since nested procedures are copied
1020 st = DupStmt(super->d_MyGroup,
1024 * Copy-down a nested procedure.
1025 * The procedure must be linked
1026 * into the copy of the parent
1027 * prodedure, not the original
1028 * parent procedure, or it will
1029 * never be resolved.
1031 st = DupStmt(d->d_Stmt->st_MyGroup,
1036 * Internal procedure (we do not need to do
1037 * anything), there is no statement body
1043 * Procedure is being used in the primary class it
1046 st = DupStmt(d->d_MyGroup, st->st_Parent, st);
1050 * Link the procedure body to the declaration and
1051 * resolve the procedure body.
1053 dassert_stmt(st, d->d_ProcDecl.ed_ProcBody == NULL);
1055 d->d_ProcDecl.ed_ProcBody = st;
1056 st->st_ProcStmt.es_Decl = d;
1057 st->st_ProcStmt.es_Scope = d->d_Scope;
1058 resolveStmt(d->d_ImportSemGroup, st, flags);
1060 ResolveAlignment(st, flags);
1061 ResolveStorage(st, flags);
1070 * __align(%d) scope qualifier, override the type's alignment
1072 if ((d->d_Scope.s_Flags & SCOPE_ALIGN) && d->d_Scope.s_AlignOverride)
1073 d->d_AlignMask = d->d_Scope.s_AlignOverride - 1;
1077 * resolveExp() - resolve expression
1079 * Resolve an expression. We are expected to resolve all ex_Type's
1080 * for the expression tree as well as expected to track down
1081 * operators and base identifiers.
1083 * itype is a type hint. If non-NULL, the caller would like our
1084 * expression to return the specified type. There are a few special
1087 * EXF_REQ_ARRAY - when OBRACKET requests an arry optimization it
1088 * passes a post-array-indexed typehint (as if
1089 * you had done the optimization). You must ignore
1090 * itype if you are unable to do the optimization.
1092 * NOTE: Even rvalues may have refstor side-effects at run-time.
1095 resolveExp(SemGroup *isg, SemGroup *sg, Exp *exp, Type *itype, int flags)
1100 loadExpCopy(©, exp);
1104 * Must resolve cast target type hint.
1107 itype = RESOLVETYPE(itype);
1110 * note: certain cases below call other resolver functions and assume
1111 * that ex* variables are unchanged.
1113 dassert((exFlags & EXF_DUPEXP) || (exFlags & EXF_RESOLVED) == 0);
1118 * An assignment. Note that we optimize void returns
1119 * (such as when an assignment is a statement like 'a = 4;'
1120 * ... the result of the assignment is cast to void.
1122 * NOTE: Left-hand-side must be an LVALUE, return type
1123 * inherits this feature unless the parent turns off
1124 * the bit so the TOK_ASS run-time must deal with that.
1126 exLhs = resolveExp(isg, sg, exLhs, NULL,
1127 flags & ~RESOLVE_AUTOCAST);
1128 dassert_exp(exLhs, exLhs->ex_Type->ty_SQFlags & SF_LVALUE);
1129 exRhs = resolveExp(isg, sg, exRhs,
1130 DEL_LVALUE(exLhs->ex_Type),
1131 flags | RESOLVE_AUTOCAST);
1133 /* AssExp handles this optimization */
1134 if (itype == &VoidType) {
1136 exFlags |= EXF_RET_VOID;
1138 exType = exLhs->ex_Type;
1143 * Check @ref assignment compatibility.
1145 if (exLhs->ex_Type->ty_Op == TY_REFTO) {
1146 switch(MatchType(exLhs->ex_Type, exRhs->ex_Type)) {
1147 case SG_COMPAT_FULL:
1148 printf("assign %s compatibility FULL\n",
1151 case SG_COMPAT_PART:
1152 printf("assign %s compatibility PART\n",
1155 case SG_COMPAT_SUBCLASS:
1156 printf("assign %s compatibility SUBCL\n",
1159 case SG_COMPAT_FAIL:
1160 printf("assign %s compatibility FAIL\n",
1169 * NOTE: BoolType global implies an rvalue.
1172 exLhs = resolveExp(isg, sg, exLhs, &BoolType,
1173 flags | RESOLVE_AUTOCAST);
1176 * If left-side can terminate the operation, mark the
1177 * expression as PROBCONST for the interpreter and code
1178 * generator (allowing the rhs to not be a constant).
1180 if (exLhs->ex_Flags & (EXF_CONST | EXF_PROBCONST)) {
1183 exLhs = resolveConstExpBool(isg, sg, exLhs, flags, &ts);
1184 if (ts.ts_Bool == 0)
1185 exFlags |= EXF_PROBCONST;
1187 exRhs = resolveExp(isg, sg, exRhs, &BoolType,
1188 flags | RESOLVE_AUTOCAST);
1193 * NOTE: BoolType global implies an rvalue.
1196 exLhs = resolveExp(isg, sg, exLhs, &BoolType,
1197 flags | RESOLVE_AUTOCAST);
1200 * If left-side can terminate the operation, mark the
1201 * expression as PROBCONST for the interpreter and code
1202 * generator (allowing the rhs to not be a constant).
1204 if (exLhs->ex_Flags & (EXF_CONST | EXF_PROBCONST)) {
1207 exLhs = resolveConstExpBool(isg, sg, exLhs, flags, &ts);
1209 exFlags |= EXF_PROBCONST;
1211 exRhs = resolveExp(isg, sg, exRhs, &BoolType,
1212 flags | RESOLVE_AUTOCAST);
1217 * This synthesized token occurs when we are able to collapse
1218 * a structural indirection or dotted element into a
1219 * declaration. For example, 'module.routine'.
1221 /* XXX couldconst? */
1226 * Structual field access. The left hand side may be an object
1227 * (class or compound), a class type, or a compound type.
1229 * A dotted access requires an lvalue on the left hand side
1230 * if the left hand side represents storage.
1232 * The result will be an lvalue if the right hand side
1233 * represents storage. We only loop if the right hand side
1234 * is an alias replacement.
1245 int procedureOnly = 0;
1246 int eno = TOK_ERR_ID_NOT_FOUND;
1249 * NOTE: Hint must 'always happen' since we may be
1250 * modifying an expression that will later be
1253 * NOTE: Lhs is always an lvalue for TOK_DOT, but
1254 * does not have to be for TOK_STRIND.
1256 exLhs->ex_Flags |= EXF_REQ_TYPE;
1257 if (exToken == TOK_DOT && (exFlags & EXF_REQ_ADDROF))
1258 exLhs->ex_Flags |= EXF_REQ_ADDROF;
1259 exLhs = resolveExp(isg, sg, exLhs, NULL,
1260 flags & ~RESOLVE_AUTOCAST);
1263 * The RHS may have been turned into a TOK_SEMGRP_ID
1264 * in a previous duplicate. The change is considered
1267 if (exRhs->ex_Token != TOK_SEMGRP_ID) {
1269 exRhs->ex_Token == TOK_STRUCT_ID);
1270 exRhs = resolveExp(isg, sg, exRhs, NULL,
1271 flags & ~RESOLVE_AUTOCAST);
1274 type = exLhs->ex_Type;
1277 * Calculate scope and SemGroup to search. Note
1278 * that it is legal to do a structural '.' selection
1279 * on a pointer, but it works differently then
1280 * indirecting through a pointer via '->'. In the
1281 * case of '.' on a pointer, we first search the
1282 * system Pointer class.
1284 if (exLhs->ex_Flags & EXF_RET_TYPE) {
1289 * Figure out the base type used to look-up the
1290 * identifier. An identifier that resolves into a
1291 * procedure winds up only being a hint for a
1294 if (exToken == TOK_STRIND) {
1295 switch(type->ty_Op) {
1297 type = type->ty_CPtrType.et_Type;
1300 type = type->ty_PtrType.et_Type;
1303 type = type->ty_RefType.et_Type;
1307 dassert_exp(exp, 0);
1313 switch(type->ty_Op) {
1315 sg2 = type->ty_ClassType.et_SemGroup;
1318 sg2 = type->ty_CompType.et_SemGroup;
1321 sg2 = type->ty_ArgsType.et_SemGroup;
1324 sg2 = type->ty_VarType.et_SemGroup;
1327 sg2 = type->ty_ImportType.et_SemGroup;
1331 dassert_exp(exp, PointerType.ty_Op == TY_CLASS);
1332 sg2 = PointerType.ty_ClassType.et_SemGroup;
1335 dassert_exp(exp, PointerType.ty_Op == TY_CLASS);
1336 sg2 = PointerType.ty_ClassType.et_SemGroup;
1340 dassert_exp(exp, PointerType.ty_Op == TY_CLASS);
1341 sg2 = PointerType.ty_ClassType.et_SemGroup;
1345 * Possibly a pointer, aka ptr.NULL
1349 visibility = exLhs->ex_Visibility;
1352 * Locate the identifier normally, via its type.
1353 * ty_TypeVisbility is the initial visibility (scope)
1354 * that the semantic search should use in locating
1358 string_t ary[2] = { id, NULL };
1361 if (exLhs->ex_Token == TOK_ID ||
1362 exLhs->ex_Token == TOK_DECL) {
1363 if (exLhs->ex_Decl->d_Search) {
1364 level = exLhs->ex_Decl->
1367 level = sg2->sg_Level;
1373 if (exLhs->ex_Flags & EXF_SUPER) {
1375 fprintf(stderr, "Can't super with reference type\n");
1376 dassert_exp(exp, 0);
1379 fprintf(stderr, "No superclass available\n");
1380 dassert_exp(exp, 0);
1385 level = sg2->sg_Level; /* may be -1 */
1387 visibility &= type->ty_Visibility;
1388 d = FindDeclPath(&exp->ex_LexRef, NULL,
1391 &visibility, level, &eno);
1393 * XXX more hack. If the super is visible
1394 * and a procedure we just found our own
1395 * refinement, not the superclass method.
1396 * This is because there is no 'superclass
1397 * method' per say, refinements *REPLACE*
1398 * superclass declarations and inherit the
1399 * superclass's level. However, we still
1400 * want to be able to chain method calls so
1401 * what we do instead is go through and find
1402 * the procedure that we smacked when we did
1403 * the refinement. This procedure has
1404 * already been conveniently brought into
1405 * the subclass context as an 'invisible'
1406 * entity at the same d_Level.
1408 if ((exLhs->ex_Flags & EXF_SUPER) &&
1410 d->d_Op == DOP_PROC &&
1411 (d->d_ScopeFlags & SCOPE_ALL_VISIBLE)
1413 string_t id2 = d->d_Id;
1414 SemGroup *olevel = d->d_Level;
1416 dassert_exp(exp, isRefTo == 0);
1418 while ((d = RUNE_NEXT(d, d_Node)) != NULL) {
1419 if (d->d_Id == id2 &&
1420 d->d_Level == olevel &&
1421 d->d_Op == DOP_PROC) {
1430 if (d && procedureOnly && d->d_Op != DOP_PROC) {
1432 "PTR.ELEMENT may be used for special "
1433 "pointer method calls, but not to "
1434 "access storage elements. "
1435 "Use PTR->ELEMENT instead\n");
1436 dassert_exp(exp, 0);
1440 * If referencing actual storage the storage must be
1443 if (d && globalOnly && (d->d_Op & DOPF_STORAGE) &&
1444 (d->d_ScopeFlags & SCOPE_GLOBAL) == 0
1447 "%s is not global. Only globals "
1448 "can be accessed through a type\n",
1450 dassert_exp(exp, 0);
1455 * Identifier found. Note that if we are
1456 * going through a reference type the
1457 * declaration is not the actual one we
1458 * use at run time. It's just a template.
1460 resolveDecl(d, flags);
1462 exVisibility = visibility;
1465 * XXX this is in wrong place
1467 * ADDROF content-locked storage is not
1468 * allowed, except for the SCOPE_LVALUE case
1469 * if the underlying type is acceptable.
1471 * If we are running through an LValueStor
1472 * UNLOCKED applies to it and not its contents.
1473 * Check to see if the contents are acceptable.
1475 if ((exFlags & EXF_REQ_ADDROF) &&
1476 (d->d_Op & DOPF_STORAGE) &&
1477 (d->d_Scope.s_Flags & SCOPE_UNLOCKED) == 0) {
1478 type = d->d_StorDecl.ed_Type;
1479 if ((type->ty_Flags & TF_HASLVPTR) &&
1480 type->ty_Op != TY_CLASS &&
1481 type->ty_Op != TY_ARYOF) {
1483 TOK_ERR_ILLEGAL_ADDRLOCKED);
1484 dassert_exp(exp, 0);
1493 exType = d->d_ProcDecl.ed_Type;
1494 if (d->d_ProcDecl.ed_Type->ty_SQFlags & SF_METHOD) {
1496 * Method call, do not
1497 * collapse the expression into
1498 * a direct declaration because
1499 * the object is needed later.
1501 if (exLhs->ex_Flags & EXF_RET_TYPE)
1502 ExpPrintError(exLhs, TOK_ERR_METHOD_REQUIRES_OBJ);
1503 dassert((exLhs->ex_Flags & EXF_RET_TYPE) == 0);
1504 } else if (isRefTo) {
1506 * Call via reference. The
1507 * lhs is required to evaluate
1508 * the actual method call at
1513 * Global method call or normal
1514 * call. For the global method
1515 * case the lhs is not needed
1516 * because the parser entered
1517 * the first argument as a
1520 * Degenerate into a TOK_DECL.
1521 * We depend on this later.
1523 exFlags &= ~EXF_BINARY;
1530 exType = DEL_LVALUE(d->d_AliasDecl.ed_Type);
1531 dassert_decl(d, d->d_AliasDecl.ed_AssExp != NULL);
1533 * NOTE: exLhs must be NULL if exp is
1534 * unresolved. exp tree duplications
1535 * do not duplicate the alias's exLHS
1536 * even though UNARY is set.
1538 dassert_exp(exp, exRhs->ex_Lhs == NULL);
1539 exRhs->ex_Flags |= EXF_ALIAS | EXF_UNARY;
1540 exRhs->ex_Lhs = DupExp(sg2,
1541 d->d_AliasDecl.ed_AssExp);
1542 exRhs->ex_Lhs = resolveExp(isg, sg2,
1545 flags | RESOLVE_AUTOCAST);
1547 case DOP_ARGS_STORAGE:
1548 case DOP_STACK_STORAGE:
1549 case DOP_GLOBAL_STORAGE:
1550 case DOP_GROUP_STORAGE:
1552 * Set type. The Rhs is a STRUCT_ID
1553 * and does not require a type to be
1556 * Return type is always an LVALUE,
1557 * parent may adjust.
1559 exType = ADD_LVALUE(d->d_StorDecl.ed_Type);
1563 * XXX make sure this is only used
1564 * in the lhs of a structural
1567 * XXX what if we went through a
1568 * TY_RETO type? This type will
1571 * collapse the exp node.
1573 exType = d->d_TypedefDecl.ed_Type;
1575 exFlags &= ~EXF_BINARY;
1579 * Do not collapse an import, we
1580 * require more resolution. e.g.
1581 * import.<blah> will be collapsed,
1582 * but 'import' cannot be.
1584 if (exFlags & EXF_REQ_TYPE) {
1587 &d->d_ImportDecl.ed_SemGroup->sg_ClassList,
1588 d->d_ImportDecl.ed_SemGroup,
1590 exFlags |= EXF_RET_TYPE;
1596 * Do not collapse a class, we require
1597 * more resolution. e.g. class.<blah>
1598 * will be collapsed, but 'class'
1601 if (exFlags & EXF_REQ_TYPE) {
1604 &d->d_ClassDecl.ed_SemGroup->sg_ClassList,
1605 d->d_ClassDecl.ed_Super,
1606 d->d_ClassDecl.ed_SemGroup,
1608 exFlags |= EXF_RET_TYPE;
1613 dassert_exp(exp, 0);
1616 if (d->d_Op == DOP_PROC) {
1617 if (d->d_ScopeFlags & SCOPE_PURE)
1619 } else if (exType->ty_SQFlags & SF_CONST) {
1623 } else if ((s = StrTableSpecial(id)) &
1624 SPECIALF_SEMGROUP) {
1626 * Identifier not found, check for a special
1629 exRhs->ex_Token = TOK_SEMGRP_ID;
1630 exRhs->ex_Int32 = s;
1635 dassert(type->ty_Op == TY_PTRTO ||
1636 type->ty_Op == TY_REFTO ||
1637 type->ty_Op == TY_CPTRTO);
1638 /* NULL is not an lvalue */
1639 exType = DEL_LVALUE(type);
1640 exFlags |= EXF_NULL;
1643 dassert(type->ty_Op != TY_PTRTO &&
1644 type->ty_Op != TY_REFTO &&
1645 type->ty_Op != TY_CPTRTO);
1646 exType = &Int32Type;
1650 * typeof(self.__data[]) vs
1651 * (cast)self.__data[]
1653 dassert(type->ty_Op != TY_PTRTO &&
1654 type->ty_Op != TY_REFTO &&
1655 type->ty_Op != TY_CPTRTO);
1656 dassert(exFlags & EXF_REQ_ARRAY);
1657 exFlags |= EXF_RET_ARRAY;
1658 if (exFlags & EXF_REQ_TYPE) {
1659 exFlags |= EXF_RET_TYPE;
1660 exType = &DynamicLValueType;
1665 * dynamic data must be cast
1667 dassert_exp(exp, 0);
1668 exType = &DynamicLValueType;
1671 case SPECIAL_VAR_COUNT:
1672 dassert(type->ty_Op != TY_PTRTO &&
1673 type->ty_Op != TY_REFTO &&
1674 type->ty_Op != TY_CPTRTO);
1675 exType = &Int32Type;
1677 case SPECIAL_VAR_DATA:
1679 * typeof(self.__vardata[]) vs
1680 * (cast)self.__vardata[]
1682 dassert(type->ty_Op != TY_PTRTO &&
1683 type->ty_Op != TY_REFTO &&
1684 type->ty_Op != TY_CPTRTO);
1685 dassert(exFlags & EXF_REQ_ARRAY);
1686 exFlags |= EXF_RET_ARRAY;
1687 if (exFlags & EXF_REQ_TYPE) {
1688 exFlags |= EXF_RET_TYPE;
1689 exType = &DynamicLValueType;
1694 * dynamic data must be cast
1696 dassert_exp(exp, 0);
1697 exType = &DynamicLValueType;
1700 case SPECIAL_TYPEID:
1701 exType = &Int32Type;
1703 case SPECIAL_TYPESTR:
1707 dassert_exp(exRhs, 0);
1712 * This is nasty, I admit. If we have a
1713 * pointer or reference type try again.
1716 if (type->ty_Op == TY_PTRTO) {
1717 type = type->ty_PtrType.et_Type;
1721 if (type->ty_Op == TY_REFTO) {
1722 type = type->ty_RefType.et_Type;
1726 if (type->ty_Op == TY_CPTRTO) {
1727 type = type->ty_CPtrType.et_Type;
1731 ExpFatalError(exRhs, eno);
1735 dassert_exp(exp, exType != NULL);
1739 * NOTE: unresolved identifiers should not have alias
1740 * expression sub-tree duplications attached to them.
1743 dassert_exp(exp, exLhs == NULL);
1747 * NOTE: LVALUE/RVALUE for elements and return type depends
1748 * on the operator. Operator functions normally
1749 * self-optimize the cases at run-time.
1752 saveExpCopy(©, exp);
1753 exp = resolveExpOper(isg, sg, exp, itype,
1754 flags & ~RESOLVE_AUTOCAST);
1755 loadExpCopy(©, exp);
1759 * Indirect through an expression.
1761 * Return type is typically an LVALUE (if representing
1762 * storage). Exp parent might turn it off so run-time
1763 * must test. Lhs may or may not be.
1768 exLhs = resolveExp(isg, sg, exLhs, NULL,
1769 flags & ~RESOLVE_AUTOCAST);
1770 type = exLhs->ex_Type;
1772 switch(type->ty_Op) {
1774 if ((exFlags & EXF_INDREF) == 0) {
1775 fprintf(stderr, "You cannot use '*' on a reference type\n");
1776 dassert_exp(exLhs, 0);
1778 exType = ADD_LVALUE(type->ty_RefType.et_Type);
1781 exType = ADD_LVALUE(type->ty_PtrType.et_Type);
1784 exType = ADD_LVALUE(type->ty_CPtrType.et_Type);
1787 dassert_exp(exLhs, 0);
1794 * Take the address of an (LVALUE) expression. Returns an
1795 * RVALUE. Allow for a short-cut optimization which replaces
1796 * the TOK_ADDR sequence with its argument in the &ary[n]
1803 * note: hint must 'always happen' since we may be
1804 * modifying an expression that will later be Dup'd.
1806 exLhs->ex_Flags |= EXF_REQ_ADDROF;
1807 exLhs->ex_Flags |= EXF_ADDRUSED;
1808 exLhs = resolveExp(isg, sg, exLhs, NULL,
1809 flags & ~RESOLVE_AUTOCAST);
1810 if (exLhs->ex_Flags & EXF_RET_ADDROF) {
1812 loadExpCopy(©, exp);
1814 type = exLhs->ex_Type;
1816 type->ty_SQFlags & SF_LVALUE);
1817 exType = RESOLVETYPE(TypeToPtrType(type));
1818 /* DEL_LVALUE() not needed here */
1824 * Array index, takes an RVALUE, returns an LVALUE.
1826 * Note: we have to convert the special __data[exp] case.
1828 * Note: ex_Flags hints must 'always happen' since we may be
1829 * modifying an expression that will later be Dup'd.
1831 exRhs = resolveExp(isg, sg, exRhs, NULL,
1832 flags & ~RESOLVE_AUTOCAST);
1833 exLhs->ex_Flags |= EXF_REQ_ARRAY | (exFlags & EXF_REQ_TYPE);
1834 exLhs->ex_Flags |= EXF_ADDRUSED;
1835 exLhs->ex_AuxExp = exRhs;
1836 exLhs = resolveExp(isg, sg, exLhs, itype,
1837 flags & ~RESOLVE_AUTOCAST);
1839 if (MatchType(&IntegralType, exRhs->ex_Type) <= SG_COMPAT_PART) {
1840 ExpPrintError(exRhs, TOK_ERR_EXPECTED_INTEGRAL_TYPE);
1841 dassert_exp(exp, 0);
1844 if (exLhs->ex_Flags & EXF_RET_ARRAY) {
1846 * __data and __vardata specials
1848 exp->ex_Token = TOK_ERR_EXP_REMOVED;
1850 } else if (exFlags & EXF_REQ_ADDROF) {
1852 * &ary[i] optimization - allows us to create
1853 * a bounded pointer (returns an RVALUE).
1857 exFlags |= EXF_RET_ADDROF;
1859 dassert((exLhs->ex_Flags & EXF_RET_TYPE) == 0);
1861 exLhs->ex_AuxExp = NULL;
1862 type = exLhs->ex_Type;
1863 switch(type->ty_Op) {
1865 type = type->ty_AryType.et_Type;
1868 type = type->ty_CPtrType.et_Type;
1871 type = type->ty_PtrType.et_Type;
1874 /* Cannot take address of a reference type */
1875 dassert_exp(exp, 0);
1878 exType = RESOLVETYPE(TypeToPtrType(type));
1879 /* returns an RVALUE */
1882 * Unoptimized array lookup, returns an lvalue
1886 dassert((exLhs->ex_Flags & EXF_RET_TYPE) == 0);
1888 exLhs->ex_AuxExp = NULL;
1889 type = exLhs->ex_Type;
1890 switch(type->ty_Op) {
1892 type = type->ty_AryType.et_Type;
1895 type = type->ty_CPtrType.et_Type;
1898 type = type->ty_PtrType.et_Type;
1902 "Cannot index a reference type\n");
1903 dassert_exp(exp, 0);
1906 exType = ADD_LVALUE(type);
1907 /* returns an LVALUE */
1911 dassert_exp(exp, 0); /* XXX */
1916 * XXX we should return a bounded pointer here.
1919 exId = StrTableEscapeQuotedString(exId, strlen(exId), 1);
1920 ReplaceStrTable(&exp->ex_Id, exId);
1924 exFlags |= EXF_CONST;
1925 exType = &UInt8Type; /* XXX make wide? */
1926 exId = StrTableEscapeQuotedString(exId, strlen(exId), 0);
1927 dassert(StrTableLen(exId) == 1);
1928 ReplaceStrTable(&exp->ex_Id, exId);
1936 strtol(exp->ex_Id, &ptr, 0);
1949 size = (size & ~0xFFF) | 1;
1953 size = (size & ~0xFFF) | 2;
1957 size = (size & ~0xFFF) | 4;
1961 size = (size & ~0xFFF) | 8;
1965 size = (size & ~0xFFF) | 16;
1969 size = (size & ~0xFFF) |
1974 TOK_ERR_ILLEGAL_SUFFIX);
1985 exType = &Int16Type;
1988 exType = &Int32Type;
1991 exType = &Int64Type;
1994 exType = &Int128Type;
1997 exType = &UInt8Type;
2000 exType = &UInt16Type;
2003 exType = &UInt32Type;
2006 exType = &UInt64Type;
2009 exType = &UInt128Type;
2012 exType = &Int32Type;
2016 exFlags |= EXF_CONST;
2023 exType = &Float64Type;
2025 strtod(exp->ex_Id, &ptr);
2030 exType = &Float32Type;
2034 exType = &Float64Type;
2038 exType = &Float128Type;
2044 exFlags |= EXF_CONST;
2051 * The self identifier represents the current procedure's
2052 * arguments. A varargs procedure will actually be called
2053 * with an extended version of this type, but for resolution
2054 * purposes we can use this time.
2056 * This is an LVALUE to support things like self.new() XXX.
2058 exType = ADD_LVALUE(resolveArgsType(sg, flags));
2062 * The '$' identifier represents the current procedure's
2065 exType = ADD_LVALUE(resolveReturnType(sg, flags));
2070 * Lookup the identifier. The returned declaration could
2071 * represent a class, typedef, module, or storage, but for
2072 * this case we only allow storage or a constant. Since
2073 * we are starting from our own semantic group, visibility
2074 * is initially ALL (private, library, and public).
2076 * The identifier might represent something at a higher scoping
2077 * layer. For example, a nested procedure accessing a variable
2078 * in the parent procedure or a method procedure in a class
2079 * accessing an element of the object.
2081 * It is also possible for the current execution scoping layer
2082 * (sg) to have a secondary contextual layer from which global
2083 * constants can be accessed. This is typically set when
2084 * resolving procedure arguments for procedures called through
2085 * objects or types. Only type globals can be accesed via
2088 * This returns an LVALUE if the id represents storage.
2092 int eno = TOK_ERR_ID_NOT_FOUND;
2097 * Special case 'super'. XXX TY_REFTO
2099 * Make an in-place change to the expression
2100 * structure. 'super' is actually 'this' with the
2101 * EXF_SUPER flag set.
2103 if (exId == String_Super) {
2105 ReplaceStrTable(&exp->ex_Id, exId);
2106 exFlags |= EXF_SUPER;
2108 ary[0] = exp->ex_Id;
2111 exDecl = FindDeclPath(&exp->ex_LexRef, isg, sg,
2113 FDC_NULL, &exVisibility,
2115 if (exDecl == NULL) {
2116 exDecl = FindDeclPathAltContext(
2117 &exp->ex_LexRef, isg, sg,
2119 FDC_NULL, &exVisibility,
2122 if (exDecl == NULL) {
2123 ExpPrintError(exp, eno);
2124 dassert_exp(exp, 0);
2128 * The EXF flag is set by TOK_ADDR, possibly
2129 * propagated down via TOK_DOT. Use this to flag
2130 * that the stack context might be used outside of
2131 * its normal life. LValue scoped declarations do
2132 * not count because they have their own RefStor.
2134 * (This code is primarily responsible for causing
2135 * SRSGET and SRSPUT instructions to be emitted).
2137 if ((exFlags & EXF_REQ_ADDROF) &&
2138 (exDecl->d_Scope.s_Flags & SCOPE_LVALUE) == 0) {
2139 exDecl->d_MyGroup->sg_Flags |= SGF_ADDRUSED;
2143 * Try to delay resolving the procedure declaration
2144 * (which will resolve the procedure body). We cannot
2145 * delay the resolution if resolving a constant
2146 * that the resolver needs immediately.
2148 if (flags & RESOLVE_CONSTEXP) {
2149 resolveDecl(exDecl, flags);
2154 * Taking the address of content-locked storage is illegal.
2156 * If we are running through an LValueStor
2157 * UNLOCKED applies to it and not its contents.
2158 * Check to see if the contents are acceptable.
2160 if ((exFlags & EXF_REQ_ADDROF) &&
2161 (exDecl->d_Scope.s_Flags & SCOPE_UNLOCKED) == 0) {
2162 Type *type = exDecl->d_StorDecl.ed_Type;
2163 if ((type->ty_Flags & TF_HASLVPTR) &&
2164 type->ty_Op != TY_CLASS &&
2165 type->ty_Op != TY_ARYOF) {
2167 TOK_ERR_ILLEGAL_ADDRLOCKED);
2168 dassert_exp(exp, 0);
2172 switch(exDecl->d_Op) {
2173 case DOP_ARGS_STORAGE:
2174 case DOP_STACK_STORAGE:
2175 case DOP_GLOBAL_STORAGE:
2176 case DOP_GROUP_STORAGE:
2178 * Storage identifiers are lvalues.
2180 * Try to delay this step, giving the language more
2181 * flexibility in avoiding resolver loops from
2182 * interdependencies that can cause it to fail.
2184 * We can't delay this step when resolving an
2185 * expression that the resolver needs an actual
2186 * constant result for.
2188 exType = ADD_LVALUE(exDecl->d_StorDecl.ed_Type);
2189 if (exDecl->d_Op == DOP_STACK_STORAGE &&
2190 (exFlags & EXF_ADDRUSED)) {
2191 exDecl->d_Flags |= DF_ADDRUSED;
2193 if (exType->ty_SQFlags & SF_CONST)
2195 if (flags & RESOLVE_CONSTEXP) {
2196 Exp **asexpp = &exDecl->d_StorDecl.ed_AssExp;
2198 *asexpp = DupExp(sg, *asexpp);
2199 *asexpp = resolveExp(isg, sg, *asexpp,
2201 flags | RESOLVE_AUTOCAST);
2202 *asexpp = SetDupExp(sg, *asexpp);
2208 * Aliases are rvalues (even if they could be lvalues).
2210 exType = DEL_LVALUE(exDecl->d_AliasDecl.ed_Type);
2211 exFlags |= EXF_ALIAS | EXF_UNARY;
2214 * NOTE: exLhs must be NULL if exp is unresolved.
2215 * exp tree duplications do not duplicate
2216 * the alias's exLHS even though UNARY is set.
2218 dassert_exp(exp, exLhs == NULL);
2219 exLhs = DupExp(sg, exDecl->d_AliasDecl.ed_AssExp);
2220 exLhs = resolveExp(isg, sg, exLhs, exType,
2221 flags | RESOLVE_AUTOCAST);
2224 * Inherit EXF_NULL (NULL pointer special) through
2225 * the alias, otherwise it will not be assignable
2226 * to arbitrary pointers.
2228 exFlags |= exLhs->ex_Flags & EXF_NULL;
2233 * A procedural identifier.
2235 * Note: procedural pointers cannot be changed so
2236 * they are not lvalues.
2238 dassert_exp(exp, (exFlags & EXF_REQ_PROC));
2239 exType = exDecl->d_ProcDecl.ed_Type;
2240 if (exDecl->d_ScopeFlags & SCOPE_PURE)
2244 if (exFlags & EXF_REQ_TYPE) {
2245 exType = exDecl->d_TypedefDecl.ed_Type;
2246 exFlags |= EXF_RET_TYPE;
2249 dassert_exp(exp, 0);
2252 if (exFlags & EXF_REQ_TYPE) {
2255 &exDecl->d_ClassDecl.ed_SemGroup->sg_ClassList,
2256 exDecl->d_ClassDecl.ed_Super,
2257 exDecl->d_ClassDecl.ed_SemGroup,
2259 exFlags |= EXF_RET_TYPE;
2262 dassert_exp(exp, 0);
2265 if (exFlags & EXF_REQ_TYPE) {
2268 &exDecl->d_ImportDecl.ed_SemGroup->sg_ClassList,
2269 exDecl->d_ImportDecl.ed_SemGroup,
2271 exFlags |= EXF_RET_TYPE;
2274 dassert_exp(exp, 0);
2277 dassert_exp(exp, 0);
2282 * NOTE: BoolType global implies an rvalue.
2285 exLhs = resolveExp(isg, sg, exLhs, &BoolType,
2286 flags | RESOLVE_AUTOCAST);
2289 if (exFlags & EXF_REQ_TYPE) {
2290 exType = RESOLVETYPE(exType);
2291 exFlags |= EXF_RET_TYPE;
2293 dassert_exp(exp, 0);
2298 * User cast (or maybe the parser inserted it). Try to
2299 * resolve the expression with the requested type hint
2300 * but tell resolveExp() not to force the cast.
2302 * Then check the result. If resolveExp() was not able to
2303 * optimize the requested cast then resolve the cast.
2305 * If the types are compatible we still keep the TOK_CAST
2306 * node in place for the moment. XXX we really need to
2307 * formalized how ex_Type is set Similar vs Exact.
2309 * NOTE: Cast results are always an RVALUE. XXX validate here.
2312 if ((exFlags & EXF_PARSE_TYPE) == 0) {
2313 exRhs->ex_Flags |= EXF_REQ_TYPE;
2314 exRhs = resolveExp(isg, sg, exRhs, NULL,
2315 flags & ~RESOLVE_AUTOCAST);
2316 exType = exRhs->ex_Type;
2318 exLhs = resolveExp(isg, sg, exLhs, exType,
2319 flags & ~RESOLVE_AUTOCAST);
2320 if (SimilarType(exType, exLhs->ex_Type) == 0) {
2321 saveExpCopy(©, exp);
2322 exp = resolveExpCast(isg, sg, exLhs, exType, flags);
2323 loadExpCopy(©, exp);
2326 /* propagate NULL flag to allow cast to any pointer type */
2327 if (exLhs->ex_Flags & EXF_NULL)
2328 printf("LHS NULL\n");
2329 exp->ex_Flags |= exLhs->ex_Flags & EXF_NULL;
2334 * Calls require the RHS to be a compound expression
2335 * representing the procedure arguments.
2337 * XXX deal with pointer-to-function verses function
2338 * XXX the lhs must at the moment resolve to the procedure
2341 * In regards to procedure pointers, the declaration
2342 * will require a pointer to the procedure's statement
2343 * body. XXX this pointer can be the physical storage
2344 * associated with the lhs data but thus requires the
2345 * type to be a pointer. We do not support the 'C'
2346 * (*ptr_to_func)(...) form. You have to use ptr_to_func(...).
2350 Type *atype; /* type for alt context */
2351 SemGroup *save_asg; /* save old alt context */
2353 dassert_exp(exRhs, exRhs->ex_Token == TOK_COMPOUND);
2356 * Note: ex_Flags hints must 'always happen' since
2357 * we may be modifying an expression that will later
2360 exLhs->ex_Flags |= EXF_REQ_PROC;
2361 exLhs = resolveExp(isg, sg, exLhs, NULL,
2362 flags & ~RESOLVE_AUTOCAST);
2363 ltype = exLhs->ex_Type;
2365 if (ltype->ty_Op == TY_PTRTO)
2366 ltype = type->ty_PtrType.et_Type; /* XXX */
2369 dassert_exp(exLhs, exLhs->ex_Token == TOK_DECL ||
2370 exLhs->ex_Token == TOK_ID);
2372 dassert_exp(exLhs, ltype != NULL &&
2373 ltype->ty_Op == TY_PROC);
2374 dassert_exp(exLhs, exLhs->ex_Decl != NULL);
2375 dassert_exp(exRhs, exRhs->ex_Token == TOK_COMPOUND);
2378 * If the lhs type indicates a method procedure, then
2379 * it's lhs is the object we wish to pass as the
2380 * first argument to the method. We move the lhs lhs
2381 * exp. For a STRIND TY_PTRTO method call we
2382 * indirect the element and convert it to a TOK_DOT
2383 * lvalue argument of the underlying object.
2385 * A method call via a reference object is a very
2388 * Since the method called through an object winds up
2389 * being a method taylored for that object, and we
2390 * are calling through a reference to an object,
2391 * the actual method will be looked up at run time
2392 * and will match the object. Thus we can safely
2393 * indirect through the reference object for this
2394 * one case. Since (*ref_obj) is not normally
2395 * allowed this will be special-cased at
2398 * Note that this occurs before we evaluate the
2399 * compound expression on the right hand side. Also
2400 * note that since the resolver can be called multiple
2401 * times on a shared expression, we have to be
2402 * careful to shift the arguments around only once.
2404 if ((ltype->ty_SQFlags & SF_METHOD) &&
2405 (exRhs->ex_Flags & EXF_CALL_CONV) == 0
2409 exRhs->ex_Flags |= EXF_CALL_CONV;
2411 switch(exLhs->ex_Token) {
2412 case TOK_STRIND: /* indirect */
2413 obj = exLhs->ex_Lhs;
2414 if (methodProcThisIsPointer(ltype)) {
2416 } else if (obj->ex_Type->ty_Op ==
2418 Exp *nexp = AllocExp(NULL);
2421 nexp->ex_Token = TOK_PTRIND;
2422 nexp->ex_Type = ADD_LVALUE(obj->ex_Type->ty_PtrType.et_Type);
2423 nexp->ex_Flags |= EXF_RESOLVED |
2425 LexDupRef(&obj->ex_LexRef,
2427 exLhs->ex_Token = TOK_DOT;
2429 } else if (obj->ex_Type->ty_Op ==
2431 Exp *nexp = AllocExp(NULL);
2434 nexp->ex_Token = TOK_PTRIND;
2435 nexp->ex_Type = ADD_LVALUE(obj->ex_Type->ty_CPtrType.et_Type);
2436 nexp->ex_Flags |= EXF_RESOLVED |
2438 LexDupRef(&obj->ex_LexRef,
2440 exLhs->ex_Token = TOK_DOT;
2442 } else if (obj->ex_Type->ty_Op ==
2444 Exp *nexp = AllocExp(NULL);
2447 nexp->ex_Token = TOK_PTRIND;
2448 nexp->ex_Type = ADD_LVALUE(obj->ex_Type->ty_RefType.et_Type);
2449 nexp->ex_Flags |= EXF_RESOLVED |
2452 LexDupRef(&obj->ex_LexRef,
2456 dassert_exp(obj, 0);
2461 * Pass directly as an lvalue. If this
2462 * is a pointer or reference only the
2463 * builtin methods for the Pointer
2464 * class are possible. These methods
2465 * require a content-locked pointer.
2467 obj = exLhs->ex_Lhs;
2468 if (obj->ex_Type->ty_Op != TY_PTRTO &&
2469 obj->ex_Type->ty_Op != TY_REFTO) {
2473 if (obj->ex_Decl == NULL ||
2474 (obj->ex_Decl->d_Scope.s_Flags & SCOPE_UNLOCKED)) {
2475 exFlags |= EXF_UNLOCKEDMTH;
2479 dassert_exp(exp, 0);
2485 * Leave the lhs intact, but set the
2486 * duplication flag in case things get
2489 exLhs->ex_Lhs = SetDupExp(sg, exLhs->ex_Lhs);
2490 obj->ex_Next = exRhs->ex_Lhs;
2491 exRhs->ex_Lhs = obj;
2493 atype = obj->ex_Type;
2499 * Try to set an alternative search context during
2500 * resolution of the procedure arguments. This context
2501 * is only searched if an identifier cannot be found
2502 * through normal means so local variables and such
2503 * will override it as the programmer should expect.
2504 * Since the local semantic stack is under the
2505 * programmer's control, unexpected collisions should
2506 * either not occur or be easily fixed.
2509 switch(atype->ty_Op) {
2511 atype = atype->ty_PtrType.et_Type;
2514 atype = atype->ty_PtrType.et_Type;
2517 if (atype->ty_Op != TY_CLASS)
2521 save_asg = sg->sg_AltContext;
2522 sg->sg_AltContext = atype->ty_ClassType.et_SemGroup;
2528 * Resolve the right hand side, which are the
2529 * procedure arguments as a compound type. This
2530 * can get tricky. XXX
2532 * NOTE: We inherit the SF_LVALUE flag from the
2533 * return type. Parent might turn it off.
2535 /*d = exLhs->ex_Decl;*/
2536 exRhs = resolveExp(isg, sg, exRhs,
2537 ltype->ty_ProcType.et_ArgsType,
2538 flags | RESOLVE_AUTOCAST);
2539 exType = ltype->ty_ProcType.et_RetType;
2542 * Restore AltContext after resolving rhs.
2544 sg->sg_AltContext = save_asg;
2545 } else if ((exRhs->ex_Flags & (EXF_CONST |
2547 (exLhs->ex_Decl->d_ScopeFlags & SCOPE_PURE)) {
2549 * atype NULL (not method call, which requires
2550 * an object), arguments can become constants,
2551 * pure function, so result can become a
2554 exFlags |= EXF_PROBCONST;
2560 * (NOTE EARLY RETURN)
2562 * A compound expression should always be an RVALUE, but
2563 * might contain LVALUEs (XXX).
2566 exp = resolveCompoundExp(isg, sg, exp, itype, flags);
2571 * The caller must be able to handle a type return when
2574 dassert_exp(exp, exFlags & EXF_REQ_TYPE);
2579 * If an expression was supplied, convert it to a type.
2581 * NOTE: ex_Flags hints must 'always happen' since we may be
2582 * modifying an expression that will later be Dup'd.
2585 if ((exFlags & EXF_RET_TYPE) == 0) {
2586 dassert(exLhs != NULL);
2587 exLhs->ex_Flags |= EXF_REQ_TYPE;
2588 exLhs = resolveExp(isg, sg, exLhs, NULL,
2589 flags & ~RESOLVE_AUTOCAST);
2590 exType = exLhs->ex_Type;
2592 /* do not clear EXF_UNARY, messes up tmp exp storage */
2593 /* exFlags &= ~EXF_UNARY; */
2595 exFlags |= EXF_RET_TYPE;
2596 /* XXX delete the lhs */
2598 exType = RESOLVETYPE(exType);
2602 exId = StrTableInt(exType->ty_Bytes);
2603 exp->ex_Token = exToken = TOK_INTEGER;
2605 exFlags &= ~EXF_RET_TYPE;
2606 exFlags |= EXF_CONST;
2609 dassert_exp(exp, exType->ty_Op == TY_ARYOF);
2610 if (exType->ty_AryType.et_Type->ty_Bytes) {
2611 exId = StrTableInt(exType->ty_Bytes /
2612 exType->ty_AryType.et_Type->ty_Bytes);
2614 exId = StrTableInt(0);
2616 exp->ex_Token = exToken = TOK_INTEGER;
2618 exFlags &= ~EXF_RET_TYPE;
2619 exFlags |= EXF_CONST;
2623 /* type is returned */
2628 dassert_exp(exp, 0);
2633 * Resolve the type and cast-to-type.
2636 exType = RESOLVETYPE(exType);
2637 /* XXX exType was ex_Type */
2640 * Special-case compound compatibility issues so the
2641 * interpreter and code generator do not have to deal with
2644 if ((flags & RESOLVE_AUTOCAST) && itype &&
2645 itype->ty_Op == TY_COMPOUND &&
2646 exType->ty_Op != TY_COMPOUND) {
2648 * The expression parser might have optimized-out
2649 * the TOK_COMPOUND wrapper around single-element
2650 * parenthesized expressions. Add it back in if
2651 * the cast target expects a compound expression.
2653 * XXX Currently hack a SetDupExp() to avoid
2654 * re-resolving the already-resolved component.
2657 saveExpCopy(©, exp);
2658 exp = ExpToCompoundExp(exp, TOK_COMPOUND);
2659 exp = resolveCompoundExp(isg, sg, exp, itype, flags);
2660 loadExpCopy(©, exp);
2662 if ((flags & RESOLVE_AUTOCAST) && itype &&
2663 itype->ty_Op == TY_CLASS &&
2664 exType->ty_Op == TY_CLASS &&
2665 itype != &VoidType &&
2666 (itype->ty_Flags & (TF_ISBOOL | TF_ISINTEGER |
2667 TF_ISFLOATING)) == 0 &&
2668 (exType->ty_Flags & (TF_ISBOOL | TF_ISINTEGER |
2671 * The expression parser might have optimized-out
2672 * the TOK_COMPOUND wrapper around single-element
2673 * parenthesized expressions used in a class iterator
2674 * (in an assignment). Add it back in if the
2675 * itype is a non-core class and exType is a core
2678 * XXX Currently hack a SetDupExp() to avoid
2679 * re-resolving the already-resolved component.
2682 saveExpCopy(©, exp);
2683 exp = ExpToCompoundExp(exp, TOK_COMPOUND);
2684 exp = resolveCompoundExp(isg, sg, exp, itype, flags);
2685 loadExpCopy(©, exp);
2689 * If the type hint did not succeed we may have to cast the
2690 * expression to the requested type. Note that if the itype
2691 * was set as part of an array optimization request which could
2692 * not be handled, we must ignore itype.
2694 * Note that SimilarType() will allow exp->ex_Type to be a
2695 * var-args TY_ARGS, and since the original Rhs of a call
2696 * is set to the procedure arguments type, VarType.et_Type
2697 * should match exactly.
2700 (exFlags & (EXF_REQ_ARRAY|EXF_RET_ARRAY)) != EXF_REQ_ARRAY
2702 if ((itype->ty_Flags & TF_RESOLVED) == 0)
2703 itype = RESOLVETYPE(itype);
2704 if ((itype->ty_SQFlags & SF_LVALUE) &&
2705 (exType->ty_SQFlags & SF_LVALUE) == 0
2708 fprintf(stderr, "Exp must be an lvalue here\n");
2709 dassert_exp(exp, 0);
2711 if (!SimilarType(itype, exType) &&
2712 (flags & RESOLVE_AUTOCAST)) {
2713 if (exp->ex_Flags & EXF_DUPEXP) {
2714 Exp *nexp = AllocExp(NULL);
2717 LexDupRef(&exp->ex_LexRef,
2720 exFlags &= ~EXF_DUPEXP;
2721 /*exp = DupExp(sg, exp);*/
2723 exFlags |= EXF_RESOLVED;
2724 exp = dupExpCopy(©, exp);
2725 exp = resolveExpCast(isg, sg, exp, itype,
2727 loadExpCopy(©, exp);
2733 * Generic constant evaluation flag. Note that EXF_PROBCONST
2734 * could also be set above (TOK_CALL).
2737 (exLhs == NULL || (exLhs->ex_Flags & (EXF_CONST|EXF_PROBCONST))) &&
2738 (exRhs == NULL || (exRhs->ex_Flags & (EXF_CONST|EXF_PROBCONST)))) {
2739 exFlags |= EXF_PROBCONST;
2742 exFlags |= EXF_RESOLVED;
2743 exp = dupExpCopy(©, exp);
2748 * Resolve an expression for which the resolver needs the result
2752 resolveConstExp(SemGroup *isg, SemGroup *sg, Exp *exp, int flags)
2757 flags &= ~RESOLVE_AUTOCAST;
2759 if ((exp->ex_Flags & EXF_RESOLVED) == 0)
2760 exp = resolveExp(isg, sg, exp, NULL, flags | RESOLVE_CONSTEXP);
2761 if ((exp->ex_Flags & (EXF_CONST | EXF_PROBCONST)) == 0) {
2762 ExpPrintError(exp, TOK_ERR_EXPECTED_INTEGRER_CONST);
2763 dassert_exp(exp, 0);
2767 if (exp->ex_Token != TOK_ID)
2770 if ((d->d_StorDecl.ed_Type->ty_SQFlags & SF_CONST) == 0)
2774 case DOP_ARGS_STORAGE:
2775 case DOP_STACK_STORAGE:
2776 case DOP_GLOBAL_STORAGE:
2777 case DOP_GROUP_STORAGE:
2778 exp = d->d_StorDecl.ed_AssExp;
2786 * Special interpreter execution to resolve the expression.
2791 int64_t tmpbuf[128];
2792 float128_t tmpflt[64];
2795 bzero(&ct, sizeof(ct));
2796 ct.ct_Flags |= CTF_RESOLVING;
2797 if (sg->sg_TmpBytes < (runesize_t)sizeof(u.tmpbuf) &&
2798 sg->sg_TmpAlignMask < (runesize_t)sizeof(float128_t))
2799 ct.ct_TmpData = (char *)u.tmpbuf;
2801 posix_memalign((void *)&ct.ct_TmpData,
2802 sg->sg_TmpAlignMask + 1,
2805 ct.ct_TmpBytes = sg->sg_TmpBytes;
2806 ct.ct_CtxRefStor.rs_Refs = 1;
2807 (void)exp->ex_Run(&ct, exp);
2809 if ((exp->ex_Flags & EXF_CONST) == 0) {
2810 ExpPrintError(exp, TOK_ERR_EXPECTED_INTEGRER_CONST);
2811 dassert_exp(exp, 0);
2813 if (ct.ct_TmpData != (char *)u.tmpbuf)
2814 free(ct.ct_TmpData);
2820 resolveConstExpBool(SemGroup *isg, SemGroup *sg, Exp *exp, int flags,
2823 runesize_t tmpbytes;
2827 flags &= ~RESOLVE_AUTOCAST;
2830 if ((exp->ex_Flags & EXF_RESOLVED) == 0) {
2831 exp = resolveExp(isg, sg, exp, NULL, flags | RESOLVE_CONSTEXP);
2835 * [re]-resolve the storage from 0 so we can execute the expression.
2837 oflags = exp->ex_Flags;
2838 ooffset = exp->ex_TmpOffset;
2839 resolveStorageExp(exp, &tmpbytes);
2840 if ((exp->ex_Flags & (EXF_CONST | EXF_PROBCONST)) == 0) {
2841 ExpPrintError(exp, TOK_ERR_EXPECTED_INTEGRER_CONST);
2842 dassert_exp(exp, 0);
2846 * Special interpreter execution to resolve the expression.
2852 int64_t tmpbuf[128];
2853 float128_t tmpflt[64];
2856 bzero(&ct, sizeof(ct));
2857 ct.ct_Flags |= CTF_RESOLVING;
2862 if (tmpbytes < (runesize_t)sizeof(u.tmpbuf))
2863 ct.ct_TmpData = (char *)u.tmpbuf;
2865 posix_memalign((void *)&ct.ct_TmpData, 16, tmpbytes);
2866 ct.ct_TmpBytes = tmpbytes;
2867 ct.ct_CtxRefStor.rs_Refs = 1;
2868 rts = exp->ex_Run(&ct, exp).data;
2870 if ((exp->ex_Flags & EXF_CONST) == 0) {
2871 ExpPrintError(exp, TOK_ERR_EXPECTED_INTEGRER_CONST);
2872 dassert_exp(exp, 0);
2874 ts->ts_Bool = rts->ts_Bool;
2875 if (ct.ct_TmpData != (char *)u.tmpbuf)
2876 free(ct.ct_TmpData);
2880 * exp is now a constant, restore the original ex_TmpOffset
2881 * for normal execution/operation (the storage may be needed for
2884 if (oflags & EXF_TMPRESOLVED) {
2885 exp->ex_TmpOffset = ooffset;
2886 resolveStorageExp(exp, &tmpbytes);
2888 exp->ex_TmpOffset = -1;
2895 * Extract constant from already-constant-resolved expression.
2896 * resolveConstExp() must have previously been called on exp.
2898 * Expression must have already been constant-optimized, meaning
2899 * that we should be able to execute it without a context to access
2900 * the cached results in exp->u.
2904 resolveGetConstExpInt64(Exp *exp)
2909 dassert_exp(exp, exp->ex_Token == TOK_INTEGER ||
2910 (exp->ex_Flags & EXF_CONST));
2911 data = exp->ex_Run(NULL, exp);
2913 if (exp->ex_Type->ty_Flags & TF_ISUNSIGNED) {
2914 switch(exp->ex_Type->ty_Bytes) {
2916 value = *(uint8_t *)data.data;
2919 value = *(uint16_t *)data.data;
2922 value = *(uint32_t *)data.data;
2925 value = *(uint64_t *)data.data;
2929 dassert_exp(exp, 0);
2933 switch(exp->ex_Type->ty_Bytes) {
2935 value = *(int8_t *)data.data;
2938 value = *(int16_t *)data.data;
2941 value = *(int32_t *)data.data;
2944 value = *(int64_t *)data.data;
2948 dassert_exp(exp, 0);
2956 * resolveCompoundExp() - resolve a compound expression (called from
2957 * resolveExp() and resolveExpOper()).
2959 * Resolve a compound expression. Compound expressions require
2960 * a compound type to normalize against. This will work for
2961 * direct assignments, return values, casts, and procedure arguments
2964 * NOTE: We can't use itype if EXF_REQ_ARRAY is specified because
2965 * its hinting for the array optimization case, which we cannot do.
2967 * Compound expressions may be used in conjuction with types
2968 * reprsenting classes, compound types, and procedure arguments. The
2969 * compound expression may contain subclasses of the superclasses expected
2970 * by itype. This is only allowed if the procedure's body has not yet been
2971 * generated (for example, a method call in a subclass).
2973 * Partially resolved operators are typically converted into procedure calls
2974 * and method calls are also partially resolved, so some elements may already
2977 * XXX named initialization, missing elements (structural
2978 * initialization), and so forth needs to be dealt with.
2981 resolveCompoundExp(SemGroup *isg, SemGroup *sg, Exp *exp,
2982 Type *itype, int flags)
2992 flags &= ~RESOLVE_AUTOCAST; /* not applicable to this function */
2995 * Expression dup()ing
2997 if (exp->ex_Flags & EXF_DUPEXP) {
2999 static int count; fprintf(stderr, "DUPEXPC %d\n", ++count);
3001 exp = DupExp(sg, exp);
3004 if (itype && (exp->ex_Flags & EXF_REQ_ARRAY) == 0)
3005 exp->ex_Type = itype;
3008 * If we don't have a SemGroup to normalize against, XXX how should
3009 * we normalize the compound expression?
3011 if (exp->ex_Type == NULL) {
3012 dassert_exp(exp, 0);
3016 * Normalize the compound expression based on the
3017 * argument types expected by the procedure. We have
3018 * to resolve the type before we start the scan in order
3019 * to ensure that d_Offset is properly assigned.
3021 * Use the declarations found in the compound type
3022 * semantic group to coerce the procedure arguments to
3023 * generate the correct compound type. Note that resolveExp()
3024 * recursion must still use the SemGroup that was passed to us.
3026 * XXX deal with defaults and pre-resolved arguments. XXX
3028 type = exp->ex_Type = RESOLVETYPE(exp->ex_Type);
3030 switch(type->ty_Op) {
3032 sg2 = type->ty_ArgsType.et_SemGroup;
3035 sg2 = type->ty_VarType.et_SemGroup;
3038 sg2 = type->ty_CompType.et_SemGroup;
3041 sg2 = type->ty_ClassType.et_SemGroup;
3044 dassert_exp(exp, 0);
3045 sg2 = NULL; /* NOT REACHED */
3048 pscan = &exp->ex_Lhs;
3051 * Scan the compound expression and match it up against the compound
3054 d = RUNE_FIRST(&sg2->sg_DeclList);
3055 while ((scan = *pscan) != NULL) {
3056 if (scan->ex_ArgId != NULL) {
3058 * Named argument, find it
3060 * (Overloading not allowed)
3062 int eno = TOK_ERR_ID_NOT_FOUND;
3065 nd = FindDeclId(sg2, scan->ex_ArgId, &eno);
3067 ExpFatalError(scan, eno);
3072 * XXX for now, punt on setting EXF_PROBCONST
3073 * if the named argument skips a declaration.
3075 if (nd != d && nd != RUNE_NEXT(d, d_Node)) {
3081 * Unnamed argument, run through sequentially. Skip
3082 * any non-storage or global storage.
3084 while (d && d->d_Op != DOP_ARGS_STORAGE &&
3085 d->d_Op != DOP_STACK_STORAGE &&
3086 d->d_Op != DOP_GROUP_STORAGE
3088 d = RUNE_NEXT(d, d_Node);
3092 * Ran out of storage declarations. If this is a
3093 * var-args SemGroup then we actually create a new
3094 * SemGroup (and eventually a new type) to represent
3097 * We then extend the varargs SemGroup. This isn't
3102 (sg2->sg_Flags & SGF_VARARGS)) {
3103 sg2 = DupSemGroup(sg2->sg_Parent, NULL, sg2, 1);
3105 if (resolveSemGroup1(sg3, flags) &&
3106 resolveSemGroup2(sg3, flags))
3107 resolveSemGroup3(sg3, flags);
3114 "Too many arguments in "
3116 dassert_exp(scan, 0);
3122 * Unlink the expression from the compound list temporarily
3123 * so we can safely resolve it. Either cast the expression
3124 * to the compound element, or create a compound element
3125 * (e.g. varargs call) to match the expression.
3127 * Due to the resolver moving things around, the elements of
3128 * a compound expression are sometimes resolved multiple times.
3130 *pscan = scan->ex_Next;
3131 scan->ex_Next = NULL;
3133 Type *stype = d->d_StorDecl.ed_Type;
3139 if (SimilarType(stype, &PointerType) &&
3140 (stype->ty_SQFlags & SF_LVALUE) == SF_LVALUE
3143 sflags = flags & ~RESOLVE_AUTOCAST;
3145 sflags = flags | RESOLVE_AUTOCAST;
3147 if (d->d_ScopeFlags & SCOPE_LVALUE)
3148 scan->ex_Flags |= EXF_ADDRUSED;
3150 if ((scan->ex_Flags & EXF_RESOLVED) == 0) {
3151 scan = resolveExp(isg, sg, scan,
3155 * Since we have already resolved the
3156 * expression we need to do the same sanity
3157 * checking that it would do to cast.
3160 (stype->ty_SQFlags & SF_LVALUE) == 0 ||
3161 (scan->ex_Type->ty_SQFlags & SF_LVALUE));
3162 if (!SimilarType(stype, scan->ex_Type)) {
3163 scan = resolveExpCast(isg, sg, scan,
3168 Scope tscope = INIT_SCOPE(0);
3170 if ((scan->ex_Flags & EXF_RESOLVED) == 0)
3171 scan = resolveExp(isg, sg, scan, NULL,
3172 flags & ~RESOLVE_AUTOCAST);
3173 dassert(varargs != 0);
3174 d = AllocDeclaration(sg2, DOP_ARGS_STORAGE, &tscope);
3175 d->d_StorDecl.ed_Type = DEL_LVALUE(scan->ex_Type);
3177 d->d_Bytes = scan->ex_Type->ty_Bytes;
3178 d->d_AlignMask = scan->ex_Type->ty_AlignMask;
3181 * __align(%d) scope qualifier, override the type's
3184 if ((d->d_Scope.s_Flags & SCOPE_ALIGN) &&
3185 d->d_Scope.s_AlignOverride) {
3186 d->d_AlignMask = d->d_Scope.s_AlignOverride - 1;
3190 sg2->sg_Bytes = (sg2->sg_Bytes + d->d_AlignMask) &
3193 d->d_Offset = sg2->sg_Bytes;
3195 sg2->sg_Bytes += d->d_Bytes;
3196 if (sg2->sg_AlignMask < d->d_AlignMask)
3197 sg2->sg_AlignMask = d->d_AlignMask;
3202 * Relink and check if constant
3204 scan->ex_Next = *pscan;
3206 if ((scan->ex_Flags & (EXF_CONST | EXF_PROBCONST)) == 0)
3210 * If the declaration requires an LVALUE, assert that
3211 * we have an lvalue. Otherwise set the direct-store
3212 * request (also see InterpCompoundExp).
3214 if (d->d_ScopeFlags & SCOPE_LVALUE) {
3215 if ((scan->ex_Type->ty_SQFlags & SF_LVALUE) == 0)
3216 fprintf(stderr, "argument must be an lvalue\n");
3218 scan->ex_Type->ty_SQFlags & SF_LVALUE);
3224 d = RUNE_NEXT(d, d_Node);
3225 pscan = &scan->ex_Next;
3229 * Make sure the caller knows its a var-args function even if
3230 * we didn't supply any additional args. Otherwise the backend
3231 * may not generate the correct form for calls to the target.
3234 (sg2->sg_Flags & SGF_VARARGS)) {
3235 sg2 = DupSemGroup(sg2->sg_Parent, NULL, sg2, 1);
3240 * Resolve the varargs sg2 after building it.
3243 if (resolveSemGroup1(sg2, flags) &&
3244 resolveSemGroup2(sg2, flags)) {
3245 resolveSemGroup3(sg2, flags);
3247 /* resolveStorageSemGroupAlign(sg2); */
3248 /*resolveStorageSemGroup(sg2, 0, 0);*/
3252 * If we made a var-args call, adjust the expression's type
3255 dassert(type->ty_Op == TY_ARGS);
3256 exp->ex_Type = RESOLVETYPE(TypeToVarType(type, sg2));
3259 exp->ex_Flags |= EXF_PROBCONST;
3261 exp->ex_Flags |= EXF_RESOLVED;
3266 * resolveExpCast() - Cast the expression to the specified type and return
3267 * the cast expression.
3269 * Note that expression nodes depend on their ex_Type being correct,
3270 * and also expressions may be shared, so be careful not to modify the
3271 * ex_Type (or anything else) in the existing expression.
3273 * This code is somewhat different then resolveExpOper() and friends.
3274 * The Exp argument has already been resolved so do not resolve it
3275 * again, and the cast type already has SF_LVALUE set or cleared as
3276 * appropriate (had better be cleared!)
3278 * As with operators we have to locate the cast declaration matching
3279 * the cast we want to do.
3282 resolveExpCast(SemGroup *isg, SemGroup *sg, Exp *exp, Type *ltype, int flags)
3287 flags &= ~RESOLVE_AUTOCAST; /* not applicable to this function */
3289 rtype = exp->ex_Type;
3290 dassert(rtype && ltype);
3292 * XXX attempt to cast from subclass to superclass?
3296 * XXX look in our local semantic hierarchy for a compatible cast ?
3300 * Look in the right hand (source) type for the cast
3302 d = findCast(rtype, ltype, rtype, flags);
3305 * If that fails then look in the left hand (destination) type for
3309 d = findCast(ltype, ltype, rtype, flags);
3312 if (d == NULL && (rtype->ty_Op == TY_PTRTO ||
3313 rtype->ty_Op == TY_REFTO ||
3314 rtype->ty_Op == TY_CPTRTO)) {
3315 d = findCast(&PointerType, ltype, rtype, flags);
3321 * We could not find a specific cast operator. There are
3322 * some inherent casts that we can do. We run through these
3323 * in attempt to come up with matching types.
3325 if (ltype->ty_Op != rtype->ty_Op &&
3326 (ltype->ty_Op == TY_PTRTO || ltype->ty_Op == TY_CPTRTO ||
3327 ltype->ty_Op == TY_ARYOF) &&
3328 (rtype->ty_Op == TY_PTRTO || rtype->ty_Op == TY_CPTRTO ||
3329 rtype->ty_Op == TY_ARYOF)) {
3331 * Pointers, C pointers, or arrays can be cast to
3332 * pointers, C pointers, or arrays of the same type.
3334 * Cast the right hand type to an equivalent
3335 * pointer/cpointer/array of the right hand type
3336 * and re-resolve the cast.
3338 exp = ExpToCastExp(exp,
3339 RESOLVETYPE(ChangeType(rtype, ltype->ty_Op)));
3340 return(resolveExpCast(isg, sg, exp, ltype, flags));
3341 } else if (MatchType(ltype, rtype) <= SG_COMPAT_PART) {
3343 * If the types are compatible (casting rtype->ltype),
3344 * we can cast trivially.
3346 exp = ExpToCastExp(exp, ltype);
3347 } else if (MatchType(&NumericType, ltype) <= SG_COMPAT_PART &&
3348 MatchType(&NumericType, rtype) <= SG_COMPAT_PART) {
3350 * Casting from one numeric type to another must be
3351 * supported by the interpreter/compiler.
3353 exp = ExpToCastExp(exp, ltype);
3354 } else if (SimilarType(&VoidType, ltype)) {
3356 * Casting anything to void is allowed (throwing the
3357 * object away). E.g. statement-expressions.
3359 exp = ExpToCastExp(exp, ltype);
3360 } else if (SimilarType(&VoidPtrType, ltype)) {
3362 * Casting a pointer to a (void *) is trivial, but is
3363 * only allowed if the underlying structure does not
3364 * contain any pointers.
3366 * NOTE: Generally only used when a pointer is being
3367 * cast to an integer. Rune does not allow
3368 * casting back to other pointer types.
3370 * XXX validate integral # of objects fit in pointer
3373 dassert_exp(exp, (rtype->ty_PtrType.et_Type->ty_Flags & TF_HASLVPTR) == 0);
3374 exp = ExpToCastExp(exp, ltype);
3375 } else if (SimilarType(&VoidRefType, ltype)) {
3377 * Casting a pointer to a (void @) is trivial.
3379 * NOTE: Generally only used when a pointer is being
3380 * cast to an integer. Rune does not allow
3381 * casting back to other pointer types.
3383 * XXX validate integral # of objects fit in pointer
3386 dassert_exp(exp, (rtype->ty_RefType.et_Type->ty_Flags & TF_HASLVPTR) == 0);
3387 exp = ExpToCastExp(exp, ltype);
3388 } else if (SimilarType(rtype, &VoidPtrType)) {
3390 * Casting from a void pointer may not be trivial
3391 * but we leave it up to the interpreter/compiler.
3393 * Only allow if the target does not contain any
3394 * pointers or if the right-hand-side is NULL.
3396 * XXX validate integral # of objects fit in pointer
3399 switch(ltype->ty_Op) {
3401 if ((exp->ex_Flags & EXF_NULL) == 0)
3402 dassert_exp(exp, (ltype->ty_RefType.et_Type->ty_Flags & TF_HASLVPTR) == 0);
3405 if ((exp->ex_Flags & EXF_NULL) == 0)
3406 dassert_exp(exp, (ltype->ty_PtrType.et_Type->ty_Flags & TF_HASLVPTR) == 0);
3411 exp = ExpToCastExp(exp, ltype);
3412 } else if (SimilarType(rtype, &CVoidPtrType)) {
3413 switch(ltype->ty_Op) {
3415 if ((exp->ex_Flags & EXF_NULL) == 0)
3416 dassert_exp(exp, (ltype->ty_PtrType.et_Type->ty_Flags & TF_HASLVPTR) == 0);
3421 } else if (SimilarType(ltype, &BoolType) &&
3422 (rtype->ty_Op == TY_PTRTO ||
3423 rtype->ty_Op == TY_REFTO ||
3424 rtype->ty_Op == TY_CPTRTO)) {
3426 * Any pointer can be cast to a boolean, which
3427 * tests against NULL.
3429 exp = ExpToCastExp(exp, ltype);
3430 } else if (ltype->ty_Op == rtype->ty_Op &&
3431 (ltype->ty_Op == TY_PTRTO ||
3432 ltype->ty_Op == TY_CPTRTO ||
3433 ltype->ty_Op == TY_ARYOF)) {
3435 * We allow casts of pointers to similar numeric
3436 * types if they are the same size, though this is
3437 * really rather a hack. This is mainly to handle
3438 * the signed<->unsigned cast case. XXX
3442 switch(ltype->ty_Op) {
3444 if (MatchType(&NumericType,
3445 ltype->ty_PtrType.et_Type) <=
3446 SG_COMPAT_SUBCLASS &&
3447 MatchType(&NumericType,
3448 rtype->ty_PtrType.et_Type) <=
3449 SG_COMPAT_SUBCLASS &&
3450 ltype->ty_Bytes == rtype->ty_Bytes
3452 exp = ExpToCastExp(exp, ltype);
3457 if (MatchType(&NumericType,
3458 ltype->ty_CPtrType.et_Type) <=
3459 SG_COMPAT_SUBCLASS &&
3460 MatchType(&NumericType,
3461 rtype->ty_CPtrType.et_Type) <=
3462 SG_COMPAT_SUBCLASS &&
3463 ltype->ty_Bytes == rtype->ty_Bytes
3465 exp = ExpToCastExp(exp, ltype);
3470 if (MatchType(&NumericType,
3471 ltype->ty_AryType.et_Type) <=
3472 SG_COMPAT_SUBCLASS &&
3473 MatchType(&NumericType,
3474 rtype->ty_AryType.et_Type) <=
3475 SG_COMPAT_SUBCLASS &&
3476 ltype->ty_Bytes == rtype->ty_Bytes
3478 exp = ExpToCastExp(exp, ltype);
3485 "Unable to resolve cast from pointers "
3486 "to dissimilar numeric types "
3488 TypeToStr(rtype, NULL),
3489 TypeToStr(ltype, NULL));
3490 dassert_exp(exp, 0);
3494 "Unable to resolve cast from %s to %s\n",
3495 TypeToStr(rtype, NULL),
3496 TypeToStr(ltype, NULL));
3497 dassert_exp(exp, 0);
3499 } else if (d->d_ScopeFlags & SCOPE_INTERNAL) {
3501 * We found a cast operator and it is an internal operator
3503 exp = ExpToCastExp(exp, ltype);
3507 * We found a cast operator and it is a Rune cast procedure. We
3508 * must convert the cast to a procedure call. If we want
3509 * resolveCompoundExp() to be able to generate a compatible
3510 * procedure (in a subclass) we have to tell it about the
3515 sexp = ExpToCompoundExp(exp, TOK_COMPOUND);
3516 if (d->d_ProcDecl.ed_ProcBody == NULL)
3518 sexp = resolveCompoundExp(isg, sg, sexp,
3519 d->d_ProcDecl.ed_Type->ty_ProcType.et_ArgsType,
3521 exp = AllocExp(NULL);
3522 exp->ex_Lhs = AllocExp(NULL);
3523 exp->ex_Lhs->ex_Token = TOK_DECL;
3524 exp->ex_Lhs->ex_Id = d->d_Id;
3525 exp->ex_Lhs->ex_Decl = d;
3526 exp->ex_Lhs->ex_Type = d->d_ProcDecl.ed_Type;
3527 exp->ex_Lhs->ex_Flags |= EXF_RESOLVED;
3529 exp->ex_Flags |= EXF_BINARY;
3530 exp->ex_Token = TOK_CALL;
3531 /* XXX use ltype or procedure's rettype? */
3532 exp->ex_Type = ltype;
3533 LexDupRef(&sexp->ex_LexRef, &exp->ex_LexRef);
3534 LexDupRef(&sexp->ex_LexRef, &exp->ex_Lhs->ex_LexRef);
3536 exp->ex_Flags |= EXF_RESOLVED;
3542 findCast(Type *btype, Type *ltype, Type *rtype, int flags)
3547 flags &= ~RESOLVE_AUTOCAST; /* not applicable to this function */
3550 * Locate the base type. If the base type does not have a SemGroup
3551 * there are no casts. (XXX put system operators here)
3553 sg = BaseType(&btype);
3559 * Look for the cast in the SemGroup
3561 RUNE_FOREACH(d, &sg->sg_DeclList, d_Node) {
3562 if (d->d_Op == DOP_PROC && (d->d_ScopeFlags & SCOPE_CAST)) {
3563 if (MatchCastTypes(d, ltype, rtype))
3569 * Failed. If the base type is a compound type, look for the
3570 * cast in the SemGroup for each element making up the compound
3571 * type. e.g. so (mycustomtype, double) would find the cast
3574 if (btype->ty_Op == TY_COMPOUND) {
3575 RUNE_FOREACH(d, &sg->sg_DeclList, d_Node) {
3577 if (d->d_Op & DOPF_STORAGE) {
3578 d2 = findCast(d->d_StorDecl.ed_Type,
3579 ltype, rtype, flags);
3580 } else if (d->d_Op == DOP_TYPEDEF) {
3581 d2 = findCast(d->d_TypedefDecl.ed_Type,
3582 ltype, rtype, flags);
3595 * resolveExpOper() - resolve an operator
3597 * This is complex enough that it is broken out into its own procedure.
3598 * Normally we just look the operator up but we have to special case
3599 * pointer arithmatic because we do will not know until now that we
3602 * itype is a return-type hint only. resolveExpOper() can ignore it
3603 * if it wishes. We currently use it to detect cast-to-void, such as
3604 * when an expression like "++i" is used in a for() loop or as a
3605 * standalone statement. This allows us to optimize the case.
3608 resolveExpOper(SemGroup *isg, SemGroup *sg, Exp *exp, Type *itype, int flags)
3611 int isPointerOp = 0;
3614 flags &= ~RESOLVE_AUTOCAST; /* not applicable to this function */
3616 loadExpCopy(©, exp);
3617 dassert_exp(exp, exp->ex_Id != NULL);
3618 if (exFlags & EXF_BINARY) {
3619 exLhs = resolveExp(isg, sg, exLhs, NULL, flags);
3620 exRhs = resolveExp(isg, sg, exRhs, NULL, flags);
3621 } else if (exFlags & EXF_UNARY) {
3622 exLhs = resolveExp(isg, sg, exLhs, NULL, flags);
3624 dassert_exp(exp, 0);
3628 * If the lhs is a pointer look the operator up in the Pointer
3629 * class first. Operators in the Pointer class are special-cased.
3630 * A second pointer argument or a pointer return value must match
3633 * If this fails, or if the ltype is not a pointer, then look
3634 * the operator up normally.
3636 if (exLhs->ex_Type->ty_Op == TY_PTRTO ||
3637 exLhs->ex_Type->ty_Op == TY_REFTO ||
3638 exLhs->ex_Type->ty_Op == TY_CPTRTO
3643 if (exFlags & EXF_BINARY) {
3644 rtype = exRhs->ex_Type;
3645 ltype = exLhs->ex_Type;
3647 dassert(exFlags & EXF_UNARY);
3649 ltype = exLhs->ex_Type;
3651 d = findOper(&PointerType, exp->ex_Id, ltype, rtype, flags);
3655 d = findExpOper(©, flags);
3657 d = findExpOper(©, flags);
3661 * Fall through to finish up resolving the operator. We just set
3662 * ex_Decl for internal operators, and construct a call for
3663 * non-internal procedural operators.
3671 dassert_exp(exp, d != NULL);
3672 dassert_exp(exp, d->d_Op == DOP_PROC);
3673 dassert_exp(exp, d->d_ProcDecl.ed_Type->ty_Op == TY_PROC);
3674 type = d->d_ProcDecl.ed_Type;
3675 exType = type->ty_ProcType.et_RetType;
3678 * Special case for internal Pointer ops. The return type is
3679 * the left-hand type (we may still optimize it to void later).
3682 (d->d_ScopeFlags & SCOPE_INTERNAL) &&
3683 SimilarType(&VoidRefType, exType)
3685 if (exType->ty_SQFlags & SF_LVALUE)
3686 exType = ADD_LVALUE(exLhs->ex_Type);
3688 exType = DEL_LVALUE(exLhs->ex_Type);
3691 type = d->d_ProcDecl.ed_Type->ty_ProcType.et_ArgsType;
3692 dassert(type->ty_Op == TY_ARGS);
3693 sg2 = type->ty_ArgsType.et_SemGroup;
3696 * Assert that LVALUE requirements are met. XXX MatchType()
3697 * code should disallow the non-lvalue-cast-to-lvalue case
3698 * so we don't have to do a check here.
3700 RUNE_FOREACH(d2, &sg2->sg_DeclList, d_Node) {
3701 if ((d2->d_Op & DOPF_STORAGE) &&
3702 d2->d_Op != DOP_GLOBAL_STORAGE) {
3704 if ((d2->d_ScopeFlags & SCOPE_LVALUE) &&
3705 (exLhs->ex_Type->ty_SQFlags &
3709 "lhs of exp must be "
3711 dassert_exp(exp, 0);
3713 } else if (count == 1) {
3714 if ((d2->d_ScopeFlags & SCOPE_LVALUE) &&
3715 (exRhs->ex_Type->ty_SQFlags &
3719 "rhs of exp must be "
3721 dassert_exp(exp, 0);
3728 if (d->d_ScopeFlags & SCOPE_INTERNAL) {
3730 * Internal operator. Optimize any cast to void
3731 * by having the internal function deal with it.
3732 * (since we aren't setting exType the optimization
3733 * currently doesn't do anything, see ST_Exp)
3736 if (itype == &VoidType) {
3738 exFlags |= EXF_RET_VOID;
3742 * Normal procedural operator. Convert the left and
3743 * right hand sides to a compound expression and
3744 * convert exp to a TOK_CALL. NOTE! ex_Rhs may be
3747 * The compound expression may need to rewrite a
3748 * subclass procedure, which it can do if the
3749 * procedure's body has not yet been created (or
3750 * duplicated from the superclass). ex_Decl must
3751 * be set in this case.
3753 * Note that the expression structure may be shared.
3754 * The conversion is permanent so that is ok.
3756 * XXX keep the type intact?
3758 exLhs->ex_Next = exRhs;
3760 exRhs = ExpToCompoundExp(exRhs, TOK_COMPOUND);
3761 if (d->d_ProcDecl.ed_ProcBody == NULL)
3763 exRhs = resolveCompoundExp(isg, sg, exRhs, type, flags);
3764 exLhs = AllocExp(NULL);
3765 LexDupRef(&exp->ex_LexRef, &exLhs->ex_LexRef);
3766 exLhs->ex_Token = TOK_ID;
3767 exLhs->ex_Id = d->d_Id;
3769 exLhs->ex_Type = d->d_ProcDecl.ed_Type;
3770 exLhs->ex_Flags |= EXF_RESOLVED;
3771 exToken = exp->ex_Token = TOK_CALL;
3772 exFlags = EXF_BINARY;
3777 "Unable to resolve operator: %s\n", exp->ex_Id);
3778 dassert_exp(exp, 0);
3782 * Flag a pure operator whos arguments are constants as probably
3785 if (d->d_ScopeFlags & SCOPE_PURE) {
3786 if ((exLhs->ex_Flags & (EXF_CONST | EXF_PROBCONST)) &&
3788 (exRhs->ex_Flags & (EXF_CONST | EXF_PROBCONST)))) {
3789 exFlags |= EXF_PROBCONST;
3793 exFlags |= EXF_RESOLVED;
3794 return(dupExpCopy(©, exp));
3798 loadExpCopy(Exp *copy, Exp *exp)
3800 copy->ex_Lhs = exp->ex_Lhs;
3801 copy->ex_Rhs = exp->ex_Rhs;
3802 copy->ex_Flags = exp->ex_Flags;
3803 copy->ex_Type = exp->ex_Type;
3804 copy->ex_Decl = exp->ex_Decl;
3805 copy->ex_Token = exp->ex_Token;
3806 copy->ex_Visibility = exp->ex_Visibility;
3807 copy->ex_Id = exp->ex_Id;
3808 copy->ex_ArgId = exp->ex_ArgId;
3809 copy->ex_AuxExp = exp->ex_AuxExp;
3813 saveExpCopy(Exp *copy, Exp *exp)
3815 exp->ex_Lhs = copy->ex_Lhs;
3816 exp->ex_Rhs = copy->ex_Rhs;
3817 exp->ex_Flags = copy->ex_Flags;
3818 exp->ex_Type = copy->ex_Type;
3819 exp->ex_Decl = copy->ex_Decl;
3820 exp->ex_Token = copy->ex_Token;
3821 exp->ex_Visibility = copy->ex_Visibility;
3822 exp->ex_Id = copy->ex_Id;
3823 exp->ex_ArgId = copy->ex_ArgId;
3824 exp->ex_AuxExp = copy->ex_AuxExp;
3827 #define EXF_DUPSHAREFLAGS -1
3830 dupExpCopy(Exp *copy, Exp *exp)
3834 if ((exp->ex_Flags & EXF_DUPEXP) == 0) {
3835 saveExpCopy(copy, exp);
3840 * We can share the expression or subexpression across duplicated
3841 * elements in distinct subclasses if these conditions are met.
3843 * Note: 0x80000000 for ex_Visibility simply means that the visibility
3844 * was never modified and can be changed for the first time.
3845 * Superclasses are resolved first so we should be ok.
3847 if (exp->ex_Lhs == copy->ex_Lhs &&
3848 exp->ex_Rhs == copy->ex_Rhs &&
3849 ((exp->ex_Flags ^ copy->ex_Flags) & ~EXF_DUPSHAREFLAGS) == 0 &&
3850 (exp->ex_Type == copy->ex_Type || exp->ex_Type == NULL) &&
3851 exp->ex_Token == copy->ex_Token &&
3852 (exp->ex_Decl == copy->ex_Decl || exp->ex_Decl == NULL) &&
3853 (exp->ex_Id == copy->ex_Id || exp->ex_Id == NULL) &&
3854 (exp->ex_ArgId == copy->ex_ArgId || exp->ex_ArgId == NULL) &&
3855 (exp->ex_AuxExp == copy->ex_AuxExp || exp->ex_AuxExp == NULL) &&
3856 (exp->ex_Visibility == copy->ex_Visibility ||
3857 (exp->ex_Visibility & 0x80000000))
3861 fprintf(stderr, "DUPEXPB COMPARE %d %p\n", ++count, exp);
3863 saveExpCopy(copy, exp);
3867 nexp = AllocExp(NULL);
3868 LexDupRef(&exp->ex_LexRef, &nexp->ex_LexRef);
3874 "DUPEXPB %d %p lhs (%p,%p) rhs (%p,%p) "
3875 "flags (%08x,%08x) types (%p, %p) "
3876 "tokens (%04x, %04x), decl (%p, %p) "
3880 exp->ex_Lhs, copy->ex_Lhs,
3881 exp->ex_Rhs, copy->ex_Rhs,
3882 exp->ex_Flags & ~EXF_DUPSHAREFLAGS,
3883 copy->ex_Flags & ~EXF_DUPSHAREFLAGS,
3884 exp->ex_Type, copy->ex_Type,
3885 exp->ex_Token, copy->ex_Token,
3886 exp->ex_Decl, copy->ex_Decl,
3887 exp->ex_Visibility, copy->ex_Visibility
3889 ExpPrintError(exp, 0);
3893 copy->ex_Flags &= ~EXF_DUPEXP;
3894 saveExpCopy(copy, nexp);
3900 * resolveType() - Resolve a type
3902 * This routine is responsible for resolving the size and alignment
3903 * features of a type. Note that we do not special-case LVALUE
3904 * qualified types here.
3906 * This routine is also rsponsible for resolving the visibility of
3907 * a type's elements. Visibility is inherited from sub-types. Base
3908 * classes's visibility should already be set by resolveSuperClass()
3911 resolveType(Type *type, Type *adjtype, int flags)
3913 SemGroup *sg = NULL;
3917 flags &= ~RESOLVE_AUTOCAST; /* not applicable to this function */
3919 if (type->ty_Flags & TF_RESOLVED)
3922 dassert_type(type, (type->ty_Flags & TF_RESOLVING) == 0);
3923 type->ty_Flags |= TF_RESOLVING;
3925 switch(type->ty_Op) {
3928 * NOTE: TF_HASLVPTR inherited as appropriate after switch.
3930 * NOTE: Special case, PointerType fields not in classes XXX
3931 * (force alignment and bytes)?
3933 dassert(type->ty_SQList ==
3934 &type->ty_ClassType.et_SemGroup->sg_ClassList);
3935 sg = type->ty_ClassType.et_SemGroup;
3936 do2 = resolveSemGroup1(sg, flags);
3937 if (type != &PointerType) {
3938 type->ty_Bytes = sg->sg_Bytes;
3939 type->ty_AlignMask = sg->sg_AlignMask;
3941 /* visibility already determined by resolveSuperClass? */
3943 if (type->ty_ClassType.et_Super &&
3944 type->ty_ClassType.et_Super->ty_Op == TY_UNRESOLVED) {
3945 type->ty_ClassType.et_Super =
3946 resolveSuperClass(type->ty_ClassType.et_Super);
3950 * Type inherits ISUNSIGNED from class. This is a special
3951 * flag helper for the interpreter and code generator.
3953 if (sg->sg_Flags & SGF_ISINTEGER)
3954 type->ty_Flags |= TF_ISINTEGER;
3955 if (sg->sg_Flags & SGF_ISUNSIGNED)
3956 type->ty_Flags |= TF_ISUNSIGNED;
3957 if (sg->sg_Flags & SGF_ISFLOATING)
3958 type->ty_Flags |= TF_ISFLOATING;
3959 if (sg->sg_Flags & SGF_ISBOOL)
3960 type->ty_Flags |= TF_ISBOOL;
3961 if (sg->sg_Flags & SGF_HASASS)
3962 type->ty_Flags |= TF_HASASS;
3963 dassert(type->ty_Visibility != 0);
3967 * NOTE: Do not set TF_HASLVPTR, C pointers are not tracked.
3969 type->ty_Bytes = sizeof(void *);
3970 type->ty_AlignMask = POINTER_ALIGN;
3971 type->ty_CPtrType.et_Type =
3972 RESOLVETYPEADJ(type->ty_CPtrType.et_Type, type);
3973 type->ty_Visibility = type->ty_CPtrType.et_Type->ty_Visibility;
3977 * Set TF_HASLVPTR, pointers are tracked.
3979 type->ty_Bytes = sizeof(PointerStor);
3980 type->ty_AlignMask = POINTER_ALIGN;
3981 type->ty_PtrType.et_Type =
3982 RESOLVETYPEADJ(type->ty_PtrType.et_Type, type);
3983 type->ty_Visibility = type->ty_PtrType.et_Type->ty_Visibility;
3984 type->ty_Flags |= TF_HASLVPTR;
3988 * Set TF_HASLVPTR, references are tracked.
3990 type->ty_Bytes = sizeof(PointerStor);
3991 type->ty_AlignMask = POINTER_ALIGN;
3992 type->ty_RefType.et_Type =
3993 RESOLVETYPEADJ(type->ty_RefType.et_Type, type);
3994 type->ty_Visibility = type->ty_RefType.et_Type->ty_Visibility;
3995 type->ty_Flags |= TF_HASLVPTR;
3999 * Inherit TF_HASLVPTR (if array type is or contains something
4000 * which needs to be tracked).
4002 * XXX allow ArySize resolve to local expression?
4003 * XXX use interpreter to resolve constant expression?
4004 * XXX SemGroup passed as NULL.
4006 * XXX hack, ex_ArySize can be shared amoungst qualified
4007 * array types. Only resolve it once. XXX
4009 * YYY hack what is our ImportSemGroup ???
4012 Exp *exp = type->ty_AryType.et_ArySize;
4013 if ((exp->ex_Flags & EXF_RESOLVED) == 0) {
4014 exp = resolveConstExp(NULL,
4015 type->ty_AryType.et_SemGroup,
4018 type->ty_AryType.et_ArySize = exp;
4019 type->ty_AryType.et_Type =
4020 RESOLVETYPEADJ(type->ty_AryType.et_Type, type);
4021 type->ty_AryType.et_Count = resolveGetConstExpInt64(exp);
4022 type->ty_AlignMask =
4023 type->ty_AryType.et_Type->ty_AlignMask;
4025 type->ty_AryType.et_Type->ty_Bytes *
4026 type->ty_AryType.et_Count;
4028 type->ty_Visibility = type->ty_AryType.et_Type->ty_Visibility;
4029 type->ty_Flags |= type->ty_AryType.et_Type->ty_Flags &
4030 (TF_HASLVPTR | TF_HASCONSTRUCT |
4031 TF_HASDESTRUCT | TF_HASGCONSTRUCT |
4032 TF_HASGDESTRUCT | TF_HASASS);
4036 * NOTE: TF_HASLVPTR inherited as appropriate after switch.
4038 sg = type->ty_CompType.et_SemGroup;
4039 do2 = resolveSemGroup1(sg, flags);
4040 type->ty_Bytes = sg->sg_Bytes;
4041 type->ty_AlignMask = sg->sg_AlignMask;
4042 type->ty_Visibility = SCOPE_ALL_VISIBLE;
4046 * NOTE: TF_HASLVPTR inherited as appropriate after switch.
4048 sg = type->ty_VarType.et_SemGroup;
4049 do2 = resolveSemGroup1(sg, flags);
4050 type->ty_Bytes = sg->sg_Bytes;
4051 type->ty_AlignMask = sg->sg_AlignMask;
4052 type->ty_Visibility = SCOPE_ALL_VISIBLE;
4056 * NOTE: TF_HASLVPTR inherited as appropriate after switch.
4058 sg = type->ty_ArgsType.et_SemGroup;
4059 do2 = resolveSemGroup1(sg, flags);
4060 type->ty_Bytes = sg->sg_Bytes;
4061 type->ty_AlignMask = sg->sg_AlignMask;
4062 type->ty_Visibility = SCOPE_ALL_VISIBLE;
4066 * NOTE: Storage not tracked.
4068 type->ty_ProcType.et_ArgsType =
4069 RESOLVETYPE(type->ty_ProcType.et_ArgsType);
4070 type->ty_ProcType.et_RetType =
4071 RESOLVETYPEADJ(type->ty_ProcType.et_RetType, type);
4073 type->ty_AlignMask = 0;
4074 type->ty_Visibility = SCOPE_ALL_VISIBLE;
4078 * NOTE: Base storage is not tracked.
4080 type->ty_Bytes = type->ty_StorType.et_Bytes;
4081 /* XXX check pwr of 2 */
4083 type->ty_AlignMask = type->ty_Bytes - 1;
4084 type->ty_Visibility = SCOPE_ALL_VISIBLE;
4088 * NOTE: Tracking set by resolveType().
4090 type->ty_Flags &= ~TF_RESOLVING;
4091 type = resolveSuperClass(type);
4093 errorDottedId(otype->ty_UnresType.et_DottedId,
4094 "Unable to resolve class");
4098 type = RESOLVETYPE(type);
4099 type->ty_Flags |= TF_RESOLVING;
4100 /* visibility set by resolveSuperClass() */
4104 * NOTE: Tracking unknown (must be handled at run-time).
4106 type->ty_Visibility = SCOPE_ALL_VISIBLE;
4110 * NOTE: Storage is persistent, so wrapper is not tracked.
4112 type->ty_Visibility = SCOPE_ALL_VISIBLE; /* XXX */
4115 dpanic("Unknown type %d (type=%p)", type->ty_Op, type);
4118 type->ty_Flags &= ~TF_RESOLVING;
4119 type->ty_Flags |= TF_RESOLVED;
4121 do2 = resolveSemGroup2(sg, flags);
4123 resolveSemGroup3(sg, flags);
4127 * Resolve tracking flags so the run-time can take appropriate
4131 if (sg->sg_Flags & SGF_HASASS)
4132 type->ty_Flags |= TF_HASASS;
4134 type->ty_Flags |= TF_HASLVPTR;
4135 if (sg->sg_Flags & SGF_VARARGS)
4136 type->ty_Flags |= TF_HASLVPTR; /* XXX TF_VARARGS */
4138 type->ty_Flags |= TF_HASCONSTRUCT;
4140 type->ty_Flags |= TF_HASDESTRUCT;
4142 * Combine constructor/destructor hint flags for globals
4143 * because we have just one linked list for global constructors
4144 * and destructors (no need to optimize heavily).
4147 type->ty_Flags |= TF_HASGCONSTRUCT|TF_HASGDESTRUCT;
4151 * Resolve the default expression for the type, if any.
4153 * XXX qualified types just copy the exp. bad bad YYY
4155 * YYY resolveExp() no ISG (import sem group)
4157 if (type->ty_AssExp) {
4158 if ((type->ty_AssExp->ex_Flags & EXF_RESOLVED) == 0) {
4159 type->ty_AssExp = resolveExp(NULL, sg, type->ty_AssExp,
4161 flags | RESOLVE_AUTOCAST);
4163 type->ty_Flags |= TF_HASASS;
4167 * If adjtype is non-NULL it must be moved to the new type's QList.
4169 if (adjtype && type != otype) {
4170 if (adjtype->ty_SQList)
4171 RUNE_REMOVE(adjtype->ty_SQList, adjtype, ty_Node);
4172 adjtype->ty_SQList = &type->ty_QList;
4173 RUNE_INSERT_TAIL(adjtype->ty_SQList, adjtype, ty_Node);
4177 * ty_DynamicVector is nominally used when a Rune binary is run, but
4178 * we also need to set up enough of it such that mixed interpretation
4179 * and execution, or even just straight interpretation, works. This
4180 * is because the interpreter calls into libruntime.
4182 type->ty_DynamicVector = DefaultDynamicVector;
4188 * resolveSuperClass() - resolve an unresolved dotted id sequence into a class
4190 * Unresolved type identifier sequences must be resolved. We are also
4191 * responsible for setting the visibility of the type's elements.
4194 resolveSuperClass(Type *super)
4199 int visibility = SCOPE_ALL_VISIBLE;
4202 dassert_type(super, super->ty_Op == TY_UNRESOLVED);
4204 dottedId = super->ty_UnresType.et_DottedId;
4205 sg = super->ty_UnresType.et_SemGroup;
4207 d = FindDeclPath(NULL, super->ty_UnresType.et_ImportSemGroup,
4209 dottedId, FDC_NULL, &visibility, -1, &eno);
4214 * Resolve the unresolved type. Note that this occurs during class
4215 * resolution and we can't call resolveType() here without getting into
4216 * a loop, so we do not yet know storage requirements (ty_Bytes and
4221 sg = d->d_ClassDecl.ed_SemGroup;
4222 super->ty_Op = TY_CLASS;
4223 super->ty_ClassType.et_SemGroup = sg;
4224 super->ty_ClassType.et_Super = d->d_ClassDecl.ed_Super;
4225 super->ty_Visibility = visibility;
4226 if (super->ty_SQList)
4227 RUNE_REMOVE(super->ty_SQList, super, ty_Node);
4228 super->ty_SQList = &sg->sg_ClassList;
4229 RUNE_INSERT_TAIL(super->ty_SQList, super, ty_Node);
4230 dassert(visibility);
4232 * XXX should we move the class from the unresolved list to
4233 * the new SemGroup's actual list?
4238 * Adjust super instead of allocating a new super, so all
4239 * other references to super using this class path get
4243 dassert_type(super, d->d_TypedefDecl.ed_Type != super);
4245 d->d_TypedefDecl.ed_Type,
4248 d->d_TypedefDecl.ed_Type->ty_SQFlags,
4252 super->ty_Visibility = visibility;
4255 errorDottedId(dottedId, "identifier is not a class or typedef");
4256 dassert_type(super, 0);
4262 * Resolve the declarations in a semantic group. We have to do this if
4263 * (a) The declaration(s) would not otherwise be resolved by our statement
4264 * scan, or (b) We need definitive size/alignment information now rather
4267 * Also resolve SemGroup global initialization dependencies via SemGroupDepend.
4269 * SemGroup resolution occurs in three stages in order to deal with
4270 * resolver loops. The first stage does just enough to figure out
4271 * how large the non-global part of the SemGroup is (e.g. doesn't run
4272 * through pointers). The second stage handles global elements, and the
4273 * third stage completes the process.
4275 * NOTE! This code does not resolve declarations related to executable
4276 * semantic groups, such as sub-blocks within a procedure, but it does
4277 * have to resolve procedure definitions found in Class's and such.
4279 * NOTE! This code handles the last stage of subclass refinement, by
4280 * checking the validity of the refinement and setting sg_Compat properly.
4284 resolveSemGroup1(SemGroup *sg, int flags)
4290 flags &= ~RESOLVE_AUTOCAST; /* not applicable to this function */
4292 dep = resolvePushSGDepend(sg);
4293 if (sg->sg_Flags & SGF_RESOLVED) {
4294 resolvePopSGDepend(dep);
4297 if (sg->sg_Flags & SGF_RESOLVING) {
4299 "Unable to resolve embedded recursive reference\n");
4300 dassert_semgrp(sg, (sg->sg_Flags & SGF_RESOLVING) == 0);
4302 sg->sg_Flags |= SGF_RESOLVING;
4305 * First pass - resolve storage only. Note that this specifically
4306 * does not try to handle the multiple semantic layers inside a
4307 * procedure. See ResolveStorage() for that.
4309 RUNE_FOREACH(d, &sg->sg_DeclList, d_Node) {
4318 * Deal with constructor/destructor chaining.
4320 if (d->d_ScopeFlags & SCOPE_GLOBAL) {
4321 if ((d->d_Flags & DF_ONGLIST) == 0 &&
4322 (d->d_ScopeFlags & (SCOPE_CONSTRUCTOR |
4323 SCOPE_DESTRUCTOR))) {
4324 d->d_GNext = d->d_MyGroup->sg_GBase;
4325 d->d_MyGroup->sg_GBase = d;
4326 d->d_Flags |= DF_ONGLIST;
4329 if ((d->d_Flags & DF_ONCLIST) == 0 &&
4330 (d->d_ScopeFlags & SCOPE_CONSTRUCTOR)) {
4331 d->d_CNext = d->d_MyGroup->sg_CBase;
4332 d->d_MyGroup->sg_CBase = d;
4333 d->d_Flags |= DF_ONCLIST;
4335 if ((d->d_Flags & DF_ONDLIST) == 0 &&
4336 (d->d_ScopeFlags & SCOPE_DESTRUCTOR)) {
4337 d->d_DNext = d->d_MyGroup->sg_DBase;
4338 d->d_MyGroup->sg_DBase = d;
4339 d->d_Flags |= DF_ONDLIST;
4343 case DOP_STACK_STORAGE:
4345 * can't happen. Stack storage is only used in
4346 * executable contexts.
4349 case DOP_ARGS_STORAGE:
4350 case DOP_GROUP_STORAGE:
4351 type = d->d_StorDecl.ed_Type;
4353 switch(type->ty_Op) {
4355 d->d_Bytes = sizeof(void *);
4356 d->d_AlignMask = POINTER_ALIGN;
4357 if ((d->d_Scope.s_Flags & SCOPE_ALIGN) &&
4358 d->d_Scope.s_AlignOverride) {
4360 d->d_Scope.s_AlignOverride - 1;
4365 if (d->d_ScopeFlags & SCOPE_LVALUE) {
4367 * NOTE: d->d_Bytes is different from
4368 * the size of the underlying
4369 * type that the LValueStor
4372 dassert(d->d_Op == DOP_ARGS_STORAGE);
4373 d->d_Bytes = sizeof(LValueStor);
4374 d->d_AlignMask = LVALUE_ALIGN;
4376 d->d_Bytes = sizeof(PointerStor);
4377 d->d_AlignMask = POINTER_ALIGN;
4379 if ((d->d_Scope.s_Flags & SCOPE_ALIGN) &&
4380 d->d_Scope.s_AlignOverride) {
4382 d->d_Scope.s_AlignOverride - 1;
4386 resolveDecl(d, flags);
4389 if (sg->sg_AlignMask < d->d_AlignMask)
4390 sg->sg_AlignMask = d->d_AlignMask;
4391 sg->sg_Bytes = (sg->sg_Bytes + d->d_AlignMask) &
4393 d->d_Offset = sg->sg_Bytes;
4394 sg->sg_Bytes += d->d_Bytes;
4395 if (d->d_StorDecl.ed_AssExp)
4396 sg->sg_Flags |= SGF_HASASS;
4397 if (type->ty_Flags & TF_HASASS)
4398 sg->sg_Flags |= SGF_HASASS;
4399 if (type->ty_Flags & TF_HASLVPTR)
4400 sg->sg_Flags |= SGF_HASLVPTR;
4402 case DOP_GLOBAL_STORAGE:
4403 /* handled in pass2 */
4406 dassert_semgrp(sg, 0);
4411 * Rollup &obj into a SemGroup flag.
4413 if (d->d_Flags & DF_ADDRUSED) {
4414 sg->sg_Flags |= SGF_ADDRUSED;
4415 fprintf(stderr, "RESOLVER ADDRUSED %s\n", d->d_Id);
4423 sg->sg_Bytes = (sg->sg_Bytes + sg->sg_AlignMask) & ~sg->sg_AlignMask;
4424 sg->sg_Flags |= SGF_RESOLVED;
4425 resolvePopSGDepend(dep);
4431 * Followup - resolve globals
4435 resolveSemGroup2(SemGroup *sg, int flags)
4440 flags &= ~RESOLVE_AUTOCAST; /* not applicable to this function */
4442 if (sg->sg_Flags & SGF_GRESOLVED)
4444 if (sg->sg_Flags & SGF_GRESOLVING) {
4446 "Unable to resolve embedded recursive reference\n");
4447 dassert_semgrp(sg, (sg->sg_Flags & SGF_GRESOLVING) == 0);
4449 sg->sg_Flags |= SGF_GRESOLVING;
4452 * First pass - resolve storage only. Note that this specifically
4453 * does not try to handle the multiple semantic layers inside a
4454 * procedure. See ResolveStorage() for that.
4456 RUNE_FOREACH(d, &sg->sg_DeclList, d_Node) {
4464 case DOP_STACK_STORAGE:
4466 * can't happen. Stack storage is only used in
4467 * executable contexts.
4470 case DOP_ARGS_STORAGE:
4471 case DOP_GROUP_STORAGE:
4473 * Non-globals were handled in pass-1
4476 case DOP_GLOBAL_STORAGE:
4478 * Global storage must be handled in pass-2
4480 type = d->d_StorDecl.ed_Type;
4482 switch(type->ty_Op) {
4484 d->d_Bytes = sizeof(void *);
4485 d->d_AlignMask = POINTER_ALIGN;
4486 if ((d->d_Scope.s_Flags & SCOPE_ALIGN) &&
4487 d->d_Scope.s_AlignOverride) {
4489 d->d_Scope.s_AlignOverride - 1;
4494 d->d_Bytes = sizeof(PointerStor);
4495 d->d_AlignMask = POINTER_ALIGN;
4496 if ((d->d_Scope.s_Flags & SCOPE_ALIGN) &&
4497 d->d_Scope.s_AlignOverride) {
4499 d->d_Scope.s_AlignOverride - 1;
4503 resolveDecl(d, flags);
4506 if (sg->sg_GlobalAlignMask < d->d_AlignMask)
4507 sg->sg_GlobalAlignMask = d->d_AlignMask;
4508 sg->sg_GlobalBytes = (sg->sg_GlobalBytes +
4509 d->d_AlignMask) & ~d->d_AlignMask;
4510 d->d_Offset = sg->sg_GlobalBytes;
4511 sg->sg_GlobalBytes += d->d_Bytes;
4512 if (d->d_StorDecl.ed_AssExp)
4513 sg->sg_Flags |= SGF_GHASASS;
4514 if (type->ty_Flags & TF_HASASS)
4515 sg->sg_Flags |= SGF_GHASASS;
4516 if (type->ty_Flags & TF_HASLVPTR)
4517 sg->sg_Flags |= SGF_GHASLVPTR;
4520 dassert_semgrp(sg, 0);
4528 sg->sg_GlobalBytes = (sg->sg_GlobalBytes + sg->sg_GlobalAlignMask) &
4529 ~sg->sg_GlobalAlignMask;
4530 sg->sg_Flags |= SGF_GRESOLVED;
4536 resolveSemGroup3(SemGroup *sg, int flags)
4541 flags &= ~RESOLVE_AUTOCAST; /* not applicable to this function */
4544 * 0 - reserved for dynamic initialization
4545 * 1 - reserved for dynamic destructor
4550 * Third pass, resolve non-storage entities after setting
4551 * SGF_RESOLVED, these entities may legally embed this class (if
4554 * Resolve pointers that were only partially resolved in the first
4557 * Refinements have been resolved but we have to check them for
4558 * legality and set sg_Compat.
4560 * Note that this is what allows us to typedef a subclass in its
4561 * superclass. The typedef itself is safe.
4563 * Also resolve storage pointer entities that were skipped in the
4564 * first pass. Such pointers could point to ourselves.
4566 * Finally, set SCOPE_UNLOCKED on any entity which does not
4567 * contain any lockable data (like int's).
4569 RUNE_FOREACH(d, &sg->sg_DeclList, d_Node) {
4571 * Final resolution of refinements.
4573 if (d->d_ScopeFlags & SCOPE_REFINE) {
4574 resolveDecl(d->d_Super, flags);
4575 resolveDecl(d, flags);
4576 RefineDeclaration(sg, d->d_Super, d);
4587 resolveDecl(d, flags);
4590 resolveDecl(d, flags);
4593 * For now internal generation does not need a
4594 * dynamic component (and doesn't generate external
4595 * code so the function wouldn't exist anyway).
4597 if (d->d_ScopeFlags & SCOPE_INTERNAL)
4601 * Assign the dynamic index. There may be multiple
4602 * entries for the same d_Id, they are ordered such
4603 * that refinements use the same DynIndex as in
4604 * the superclass which is what allows dynamic method
4605 * calls to work properly. All non-refined subclass
4606 * elements are ordered after all refined/non=refined
4607 * superclass elements (replacing the superclass
4608 * element and using the same DynIndex when refined).
4610 d->d_DynIndex = dyncount;
4613 case DOP_ARGS_STORAGE:
4614 case DOP_GROUP_STORAGE:
4615 /*case DOP_STACK_STORAGE:*/
4616 case DOP_GLOBAL_STORAGE:
4617 switch(d->d_StorDecl.ed_Type->ty_Op) {
4621 resolveDecl(d, flags);
4626 dassert_semgrp(sg, 0);
4632 * If no dynamic methods and no dynamic initialization or destruction
4633 * required, set dyncount to 0.
4635 if (dyncount == 2 &&
4636 (sg->sg_Flags & SGF_HASASS) == 0 &&
4637 sg->sg_SRBase == NULL &&
4638 sg->sg_CBase == NULL &&
4639 sg->sg_DBase == NULL) {
4642 sg->sg_DynCount = dyncount;
4643 sg->sg_Flags &= ~SGF_RESOLVING;
4647 * findExpOper() - Find operator declaration matching expression
4649 * Locate the operator declaration (a DOP_PROCDEF) that matches
4650 * the expression or NULL if no match could be found. The expression's
4651 * left and right hand sides must already be resolved.
4653 * NOTE! A temporary 'copy' Exp may be passed, not all fields are valid.
4657 findExpOper(Exp *exp, int flags)
4663 flags &= ~RESOLVE_AUTOCAST; /* not applicable to this function */
4665 if (exp->ex_Flags & EXF_BINARY) {
4666 rtype = exp->ex_Rhs->ex_Type;
4667 ltype = exp->ex_Lhs->ex_Type;
4669 dassert(exp->ex_Flags & EXF_UNARY);
4671 ltype = exp->ex_Lhs->ex_Type;
4675 * XXX look in our local semantic hierarchy for a compatible operator ?
4679 * Attempt to find a matching operator from the left hand side
4681 d = findOper(ltype, exp->ex_Id, ltype, rtype, flags);
4683 if (d || (exp->ex_Flags & EXF_BINARY) == 0)
4686 d = findOper(rtype, exp->ex_Id, ltype, rtype, flags);
4692 findOper(Type *btype, string_t id, Type *ltype, Type *rtype, int flags)
4696 int args = (rtype != NULL) ? 2 : 1;
4698 flags &= ~RESOLVE_AUTOCAST; /* not applicable to this function */
4701 * Locate the base type. If the base type does not have a SemGroup
4702 * there are no operators. (XXX put system operators here)
4704 sg = BaseType(&btype);
4710 * Look for the operator in the SemGroup
4712 for (d = FindOperId(sg, id, args); d; d = d->d_ONext) {
4713 resolveDecl(d, flags);
4714 if (d->d_MyGroup == sg &&
4715 d->d_Op == DOP_PROC &&
4716 d->d_ProcDecl.ed_OperId == id &&
4717 MatchOperatorTypes(d, ltype, rtype)
4724 * Failed. If the base type is a compound type, look for the
4725 * operator in the SemGroup for each element making up the compound
4726 * type. e.g. so (mycustomtype, double) would find the operator
4729 if (btype->ty_Op == TY_COMPOUND) {
4730 RUNE_FOREACH(d, &sg->sg_DeclList, d_Node) {
4732 if (d->d_Op & DOPF_STORAGE) {
4733 d2 = findOper(d->d_StorDecl.ed_Type, id,
4734 ltype, rtype, flags);
4735 } else if (d->d_Op == DOP_TYPEDEF) {
4736 d2 = findOper(d->d_TypedefDecl.ed_Type, id,
4737 ltype, rtype, flags);
4749 errorDottedId(string_t *ary, const char *ctl, ...)
4755 vfprintf(stderr, ctl, va);
4757 fprintf(stderr, ": %s", ary[0]);
4758 for (i = 1; ary[i]; ++i)
4759 fprintf(stderr, ".%s", ary[i]);
4760 fprintf(stderr, "\n");
4764 * Resolve the alignment requirements for SemGroups related to
4765 * statements, including the alignment requirements needed for
4766 * temporary expression space.
4769 ResolveAlignment(Stmt *st, int flags)
4771 SemGroup *sg = st->st_MyGroup;
4774 if (st->st_Flags & STF_ALIGNRESOLVED)
4776 st->st_Flags |= STF_ALIGNRESOLVED;
4779 * If this is an executable semantic layer or an import layer then
4780 * assign storage to declarations up-front. Of the various
4781 * DOP_*_STORAGE ops, we should only see DOP_STACK_STORAGE and
4782 * DOP_GLOBAL_STORAGE.
4784 * Note: if this is the root ST_Import STF_SEMANTIC is *NOT* set and
4787 if ((st->st_Flags & STF_SEMANTIC) && st->st_Op != ST_Class) {
4791 * Pre-scan for alignment. Don't try to propagate the
4792 * alignment to the parent for now as that would require
4793 * recalculating the parent(s).
4795 RUNE_FOREACH(d, &sg->sg_DeclList, d_Node) {
4797 case DOP_STACK_STORAGE:
4798 case DOP_ARGS_STORAGE:
4799 case DOP_GROUP_STORAGE:
4800 if (sg->sg_AlignMask < d->d_AlignMask)
4801 sg->sg_AlignMask = d->d_AlignMask;
4803 case DOP_GLOBAL_STORAGE:
4804 if (sg->sg_GlobalAlignMask < d->d_AlignMask)
4805 sg->sg_GlobalAlignMask = d->d_AlignMask;
4824 d = st->st_TypedefStmt.es_Decl;
4825 resolveStorageDeclExpAlign(d, &sg->sg_TmpAlignMask);
4830 * NOTE: Don't calculate for declarations that belong in
4831 * a different context.
4837 d = st->st_DeclStmt.es_Decl;
4839 for (i = 0; i < st->st_DeclStmt.es_DeclCount; ++i) {
4840 if (st->st_MyGroup == d->d_MyGroup)
4841 resolveStorageDeclExpAlign(d, &sg->sg_TmpAlignMask);
4842 d = RUNE_NEXT(d, d_Node);
4854 if (st->st_LoopStmt.es_BCond) {
4855 resolveStorageExpAlign(st->st_LoopStmt.es_BCond,
4856 &sg->sg_TmpAlignMask);
4858 if (st->st_LoopStmt.es_ACond) {
4859 resolveStorageExpAlign(st->st_LoopStmt.es_ACond,
4860 &sg->sg_TmpAlignMask);
4862 if (st->st_LoopStmt.es_AExp) {
4863 resolveStorageExpAlign(st->st_LoopStmt.es_AExp,
4864 &sg->sg_TmpAlignMask);
4873 resolveStorageExpAlign(st->st_IfStmt.es_Exp,
4874 &sg->sg_TmpAlignMask);
4877 if (st->st_RetStmt.es_Exp)
4878 resolveStorageExpAlign(st->st_RetStmt.es_Exp,
4879 &sg->sg_TmpAlignMask);
4882 if (st->st_ResStmt.es_Exp)
4883 resolveStorageExpAlign(st->st_ResStmt.es_Exp,
4884 &sg->sg_TmpAlignMask);
4888 * The switch expression's temporary data must be saved while
4889 * we are executing the sub-statements (the cases).
4891 resolveStorageExpAlign(st->st_SwStmt.es_Exp,
4892 &sg->sg_TmpAlignMask);
4895 if (st->st_CaseStmt.es_Exp)
4896 resolveStorageExpAlign(st->st_CaseStmt.es_Exp,
4897 &sg->sg_TmpAlignMask);
4900 resolveStorageExpAlign(st->st_ExpStmt.es_Exp,
4901 &sg->sg_TmpAlignMask);
4903 case ST_ThreadSched:
4906 dassert_stmt(st, 0);
4910 * Calculate storage requirements for substatements. offset
4911 * acts as our base. We union the storage for the substatements
4912 * together. Note that often scan->sg_MyGroup == sg.
4914 RUNE_FOREACH(scan, &st->st_List, st_Node) {
4915 if (scan->st_Op == ST_Class) {
4916 ResolveAlignment(scan, flags);
4917 } else if (scan->st_Op == ST_Decl &&
4918 scan->st_DeclStmt.es_Decl->d_MyGroup !=
4924 } else if (scan->st_Op == ST_Decl &&
4925 (scan->st_DeclStmt.es_Decl->d_Flags & DF_RESOLVED)) {
4927 * See prior comments, skip declarations that
4928 * were moved to another context
4930 * (already resolved so can use junk offsets)
4932 resolveStorageDeclExpAlign(scan->st_DeclStmt.es_Decl,
4933 &sg->sg_TmpAlignMask);
4934 } else if (scan->st_Op == ST_Proc &&
4935 scan->st_ProcStmt.es_Decl->d_ProcDecl.ed_OrigBody == scan
4937 /* Do not resolve template procedures! */
4938 } else if (scan->st_Flags & STF_SEMTOP) {
4939 ResolveAlignment(scan, flags);
4941 ResolveAlignment(scan, flags);
4946 * If this is a new semantic level call resolveStorageSemGroup() to
4947 * do the final cleanup of SemGroup issues. This will redundantly
4948 * calculate temporary space requirements. Also, due to type/class
4949 * references the temporary space for a class may have already been
4950 * resolved. Since a class can only contain declarations it had
4951 * better match what we calculate here.
4953 * Note that for non-Class executable SemGroup's TmpBytes is
4954 * incorporated in a downward fashion while sg_Bytes is incorporated
4955 * in an upward fashion. It can become quite confusing. Don't ask
4956 * me why I did it that way.
4958 if (st->st_Flags & STF_SEMANTIC) {
4959 if ((sg->sg_Flags & SGF_TMPRESOLVED) == 0) {
4960 resolveStorageSemGroupAlign(sg);
4965 * Propagate alignment requirements upward.
4967 if ((st->st_Flags & (STF_SEMANTIC|STF_SEMTOP)) == STF_SEMANTIC) {
4968 if (sg->sg_Parent->sg_AlignMask < sg->sg_AlignMask)
4969 sg->sg_Parent->sg_AlignMask = sg->sg_AlignMask;
4970 if (sg->sg_Parent->sg_TmpAlignMask < sg->sg_TmpAlignMask)
4971 sg->sg_Parent->sg_TmpAlignMask = sg->sg_TmpAlignMask;
4976 * ResolveStorage() - Final storage resolution pass
4978 * This pass carefully scans the SemGroup hierarchy and assigns
4979 * offsets to declarations.
4981 * PROCEDURES - all the various 'executable' semantic layers in
4982 * a procedure are collapsed together for efficiency, so we only
4983 * have to manage one context. This means that the d_Offset
4984 * assigned to declarations in sub-blocks may exceed the sg_ size
4985 * of the sub-block's SemGroup. We do not attempt to resolve
4986 * procedure body templates (d_ProcDecl.ed_OrigBody).
4988 * CLASSES - are given offsets in their SemGroup's relative to 0, if
4989 * not already resolved.
4991 * IMPORTS - are given offsets in their SemGroup's relative to 0
4993 * COMPOUND TYPES - (such as procedure arguments) are given offsets
4994 * in their SemGroup's relative to 0.
4996 * TEMPORARY STORAGE - expressions may require temporary storage
4997 * for intermediate results. That space is reserved here.
4999 * We specifically do not resolve unrelated storage.
5003 ResolveStorage(Stmt *st, int flags)
5008 runesize_t ngoffset;
5009 SemGroup *sg = st->st_MyGroup;
5014 if (st->st_Op != ST_Class) {
5015 dassert((st->st_Flags & STF_RESOLVING) == 0);
5016 if (st->st_Flags & STF_RESOLVED) {
5019 st->st_Flags |= STF_RESOLVING;
5022 dassert(st->st_Flags & STF_ALIGNRESOLVED);
5023 if (st->st_Flags & STF_TMPRESOLVED)
5025 st->st_Flags |= STF_TMPRESOLVED;
5028 * If this is an executable semantic layer or an import layer then
5029 * assign storage to declarations up-front. Of the various
5030 * DOP_*_STORAGE ops, we should only see DOP_STACK_STORAGE and
5031 * DOP_GLOBAL_STORAGE.
5033 * Note: if this is the root ST_Import STF_SEMANTIC is *NOT* set and
5036 if ((st->st_Flags & STF_SEMANTIC) && st->st_Op != ST_Class) {
5039 dassert((sg->sg_Flags & (SGF_FRESOLVED|SGF_FRESOLVING)) == 0);
5041 sg->sg_Flags |= SGF_FRESOLVING;
5044 * The base offset for sub-semantic-blocks must match the
5045 * alignment they require in order to allow us to do an
5046 * aligned BZEROing of the space. We do not include the
5047 * temporary space here (it does not need to be BZERO'd).
5049 * NOTE: sg_TmpAlignMask is taken into accoun when the
5050 * top-level frame is allocated.
5052 if (st->st_Flags & STF_SEMTOP) {
5053 dassert(sg->sg_Bytes == 0);
5056 offset = sg->sg_Parent->sg_Bytes;
5057 offset = (offset + sg->sg_AlignMask) &
5061 sg->sg_BlkOffset = offset;
5063 RUNE_FOREACH(d, &sg->sg_DeclList, d_Node) {
5065 case DOP_STACK_STORAGE:
5066 case DOP_ARGS_STORAGE:
5067 case DOP_GROUP_STORAGE:
5068 type = d->d_StorDecl.ed_Type;
5069 offset = (offset + d->d_AlignMask) &
5071 dassert_decl(d, d->d_Offset == (runesize_t)-1);
5072 d->d_Offset = offset;
5073 offset += d->d_Bytes;
5074 if (d->d_StorDecl.ed_AssExp)
5075 sg->sg_Flags |= SGF_HASASS;
5076 if (type->ty_Flags & TF_HASASS)
5077 sg->sg_Flags |= SGF_HASASS;
5078 if (type->ty_Flags & TF_HASLVPTR)
5079 sg->sg_Flags |= SGF_HASLVPTR;
5081 case DOP_GLOBAL_STORAGE:
5082 type = d->d_StorDecl.ed_Type;
5083 sg->sg_GlobalBytes =
5084 (sg->sg_GlobalBytes + d->d_AlignMask) &
5086 dassert_decl(d, d->d_Offset == (runesize_t)-1);
5087 d->d_Offset = sg->sg_GlobalBytes;
5088 sg->sg_GlobalBytes += d->d_Bytes;
5089 if (d->d_StorDecl.ed_AssExp)
5090 sg->sg_Flags |= SGF_GHASASS;
5091 if (type->ty_Flags & TF_HASASS)
5092 sg->sg_Flags |= SGF_GHASASS;
5093 if (type->ty_Flags & TF_HASLVPTR)
5094 sg->sg_Flags |= SGF_GHASLVPTR;
5102 * The byte size of the block does not have to be aligned,
5103 * but aligning it (within reason) might provide a benefit.
5105 sg->sg_Bytes = offset;
5108 if (sg->sg_AlignMask < 256) {
5109 sg->sg_Bytes = (offset + sg->sg_AlignMask) &
5112 if (sg->sg_GlobalAlignMask < 256) {
5113 sg->sg_GlobalBytes =
5114 (sg->sg_GlobalBytes + sg->sg_GlobalAlignMask) &
5115 ~sg->sg_GlobalAlignMask;
5118 sg->sg_BlkBytes = sg->sg_Bytes - sg->sg_BlkOffset;
5119 sg->sg_Flags |= SGF_FRESOLVED;
5120 sg->sg_Flags &= ~SGF_FRESOLVING;
5124 * Figure out how much temporary space we need to be able to execute
5125 * statements and expressions. Temporary space, like the main
5126 * procedural space, must be inherited from and consolidated into
5127 * the top-level SemGroup
5130 offset = sg->sg_TmpBytes;
5132 goffset = sg->sg_GlobalTmpBytes;
5136 * Root ST_Import. avoid compiler warnings
5146 if (st->st_ImportStmt.es_DLL) {
5147 void (*func)(void) = dlsym(st->st_ImportStmt.es_DLL,
5158 resolveStorageDeclExp(st->st_TypedefStmt.es_Decl,
5159 &noffset, &ngoffset);
5164 * Temporary space for declarations are handled here.
5166 * Resolve declarations, skipping any whos context was
5167 * moved to a class (e.g. a declaration at the top level
5168 * of a file like Fd.setfd(...) also exists in the Fd class).
5174 d = st->st_DeclStmt.es_Decl;
5176 if (d->d_Op == DOP_GLOBAL_STORAGE)
5177 st->st_DeclStmt.es_TmpOffset = goffset;
5179 st->st_DeclStmt.es_TmpOffset = offset;
5180 printf("STDECLTMPOFFSET %zd\n", offset);
5181 for (i = 0; i < st->st_DeclStmt.es_DeclCount; ++i) {
5182 runesize_t xoffset = offset;
5183 runesize_t xgoffset = goffset;
5186 if (st->st_MyGroup != d->d_MyGroup) {
5187 /*printf("SKIPB %s\n", d->d_Id)*/;
5188 resolveStorageDeclExp(d, &xoffset, &xgoffset);
5189 } else if (d->d_Flags & DF_RESOLVED) {
5190 resolveStorageDeclExp(d, &xoffset, &xgoffset);
5194 resolveStorageDeclExp(
5199 if (noffset < xoffset)
5201 if (ngoffset < xgoffset)
5202 ngoffset = xgoffset;
5203 d = RUNE_NEXT(d, d_Node);
5217 if (st->st_LoopStmt.es_BCond) {
5219 resolveStorageExp(st->st_LoopStmt.es_BCond,
5221 if (noffset < xoffset)
5224 if (st->st_LoopStmt.es_ACond) {
5226 resolveStorageExp(st->st_LoopStmt.es_ACond,
5228 if (noffset < xoffset)
5231 if (st->st_LoopStmt.es_AExp) {
5233 resolveStorageExp(st->st_LoopStmt.es_AExp,
5235 if (noffset < xoffset)
5245 resolveStorageExp(st->st_IfStmt.es_Exp, &noffset);
5248 if (st->st_RetStmt.es_Exp)
5249 resolveStorageExp(st->st_RetStmt.es_Exp, &noffset);
5252 if (st->st_ResStmt.es_Exp)
5253 resolveStorageExp(st->st_ResStmt.es_Exp, &noffset);
5257 * The switch expression's temporary data must be saved while
5258 * we are executing the sub-statements (the cases).
5260 resolveStorageExp(st->st_SwStmt.es_Exp, &noffset);
5265 if (st->st_CaseStmt.es_Exp)
5266 resolveStorageExp(st->st_CaseStmt.es_Exp, &noffset);
5269 resolveStorageExp(st->st_ExpStmt.es_Exp, &noffset);
5271 case ST_ThreadSched:
5274 dassert_stmt(st, 0);
5278 * Calculate storage requirements for substatements. offset
5279 * acts as our base. We union the storage for the substatements
5280 * together. Note that often scan->sg_MyGroup == sg.
5282 RUNE_FOREACH(scan, &st->st_List, st_Node) {
5283 dassert(scan->st_Op != ST_Proc);
5284 if (scan->st_Op == ST_Class) {
5285 ResolveStorage(scan, flags);
5287 } else if (scan->st_Op == ST_Decl &&
5288 scan->st_DeclStmt.es_Decl->d_MyGroup !=
5291 * See prior comments, skip declarations that
5292 * were moved to another context.
5294 * (does not belong in context so can use
5297 runesize_t junk1 = 0;
5298 runesize_t junk2 = 0;
5300 printf("SKIPC %s\n",
5301 scan->st_DeclStmt.es_Decl->d_Id);
5303 resolveStorageDeclExp(scan->st_DeclStmt.es_Decl,
5305 } else if (scan->st_Op == ST_Decl &&
5306 (scan->st_DeclStmt.es_Decl->d_Flags & DF_RESOLVED)) {
5308 * See prior comments, skip declarations that
5309 * were moved to another context
5311 * (already resolved so can use junk offsets)
5313 runesize_t junk1 = 0;
5314 runesize_t junk2 = 0;
5316 printf("SKIPD %s\n",
5317 scan->st_DeclStmt.es_Decl->d_Id);
5319 runesize_t save_offset;
5320 runesize_t save_goffset;
5321 save_offset = scan->st_MyGroup->sg_TmpBytes;
5322 save_goffset = scan->st_MyGroup->sg_GlobalTmpBytes;
5323 scan->st_MyGroup->sg_TmpBytes = offset;
5324 scan->st_MyGroup->sg_GlobalTmpBytes = goffset;
5325 resolveStorageDeclExp(scan->st_DeclStmt.es_Decl,
5327 if (scan->st_MyGroup->sg_TmpBytes < save_offset)
5328 scan->st_MyGroup->sg_TmpBytes = save_offset;
5329 if (scan->st_MyGroup->sg_GlobalTmpBytes < save_goffset) {
5330 scan->st_MyGroup->sg_GlobalTmpBytes = save_goffset;
5332 if (noffset < scan->st_MyGroup->sg_TmpBytes)
5333 noffset = scan->st_MyGroup->sg_TmpBytes;
5334 if (ngoffset < scan->st_MyGroup->sg_GlobalTmpBytes)
5335 ngoffset = scan->st_MyGroup->sg_GlobalTmpBytes;
5337 } else if (scan->st_Op == ST_Proc) {
5338 /* Do not resolve template procedures! */
5339 fprintf(stderr, "STORAGE %s\n", scan->st_ProcStmt.es_Decl->d_Id);
5340 if (scan->st_ProcStmt.es_Decl->d_ProcDecl.ed_OrigBody == scan) {
5343 } else if (scan->st_Flags & STF_SEMTOP) {
5344 assert(scan->st_MyGroup != sg);
5345 ResolveStorage(scan, flags);
5348 * This is a bit of a mess. The baseline
5349 * sg_TmpBytes needs to be set so calculated
5350 * temporary offsets are relative to it, and
5351 * then restored. Otherwise we might blow
5352 * away the SGF_TMPRESOLVED SemGroup
5356 runesize_t save_offset;
5357 runesize_t save_goffset;
5358 save_offset = scan->st_MyGroup->sg_TmpBytes;
5359 save_goffset = scan->st_MyGroup->sg_GlobalTmpBytes;
5360 scan->st_MyGroup->sg_TmpBytes = offset;
5361 scan->st_MyGroup->sg_GlobalTmpBytes = goffset;
5362 ResolveStorage(scan, flags);
5364 if (scan->st_MyGroup->sg_TmpBytes < save_offset)
5365 scan->st_MyGroup->sg_TmpBytes = save_offset;
5366 if (scan->st_MyGroup->sg_GlobalTmpBytes < save_goffset) {
5367 scan->st_MyGroup->sg_GlobalTmpBytes = save_goffset;
5369 if (noffset < scan->st_MyGroup->sg_TmpBytes)
5370 noffset = scan->st_MyGroup->sg_TmpBytes;
5371 if (ngoffset < scan->st_MyGroup->sg_GlobalTmpBytes)
5372 ngoffset = scan->st_MyGroup->sg_GlobalTmpBytes;
5377 * If this is a new semantic level call resolveStorageSemGroup() to
5378 * do the final cleanup of SemGroup issues. This will redundantly
5379 * calculate temporary space requirements. Also, due to type/class
5380 * references the temporary space for a class may have already been
5381 * resolved. Since a class can only contain declarations it had
5382 * better match what we calculate here.
5384 * Note that for non-Class executable SemGroup's TmpBytes is
5385 * incorporated in a downward fashion while sg_Bytes is incorporated
5386 * in an upward fashion. It can become quite confusing. Don't ask
5387 * me why I did it that way.
5389 if (st->st_Flags & STF_SEMANTIC) {
5390 if ((sg->sg_Flags & SGF_TMPRESOLVED) == 0) {
5391 resolveStorageSemGroup(sg, noffset, ngoffset);
5393 dassert(sg->sg_TmpBytes == noffset &&
5394 sg->sg_GlobalTmpBytes == ngoffset);
5397 sg->sg_TmpBytes = noffset;
5398 sg->sg_GlobalTmpBytes = ngoffset;
5399 } /* else this is the Root st_Import */
5401 if ((st->st_Flags & (STF_SEMANTIC|STF_SEMTOP)) == STF_SEMANTIC) {
5402 sg->sg_Parent->sg_Bytes = sg->sg_Bytes;
5407 * resolveStorageDeclExp() - resolve the storage reservation required to
5408 * process an expression.
5410 * This is an expression tree traversal storage resolution procedure.
5411 * We have to traverse through declarations to get to default assignments
5414 * If a declaration has no assigned default the underlying type may
5415 * itself have an assigned default which must be dealt with.
5418 resolveStorageDeclExpAlign(Declaration *d, runesize_t *expalignp)
5422 /* recursion already dealt with */
5424 case DOP_ARGS_STORAGE:
5425 case DOP_STACK_STORAGE:
5426 case DOP_GROUP_STORAGE:
5428 Type *type = d->d_StorDecl.ed_Type;
5430 resolveStorageTypeExpAlign(type, expalignp);
5431 if (d->d_StorDecl.ed_AssExp) {
5432 resolveStorageExpAlign(d->d_StorDecl.ed_AssExp,
5437 case DOP_GLOBAL_STORAGE:
5439 Type *type = d->d_StorDecl.ed_Type;
5441 resolveStorageTypeExpAlign(type, expalignp);
5442 if (d->d_StorDecl.ed_AssExp) {
5443 resolveStorageExpAlign(d->d_StorDecl.ed_AssExp,
5450 * Never try to resolve storage considerations for an
5451 * alias's assignment in the declaration itself. The
5452 * run-time context depends on who and how many other
5453 * parts of the program reference the alias and the expression
5454 * tree will be duplicated for each.
5457 resolveStorageExpExp(d->d_AliasDecl.ed_AssExp, expalignp);
5461 /* XXX what about ty_AssExp ? should be in global space */
5464 /* recursion already dealt with */
5468 * Resolution of procedure declarations might have been
5469 * deferred (see TOK_ID in resolveExp()).
5475 if ((st = d->d_ProcDecl.ed_ProcBody) != NULL) {
5476 ResolveAlignment(st, 0);
5486 resolveStorageDeclExp(Declaration *d, runesize_t *offset, runesize_t *goffset)
5490 /* recursion already dealt with */
5492 case DOP_ARGS_STORAGE:
5493 case DOP_STACK_STORAGE:
5494 case DOP_GROUP_STORAGE:
5496 Type *type = d->d_StorDecl.ed_Type;
5497 runesize_t save_offset = *offset;
5499 resolveStorageType(type, &save_offset, 0);
5500 if (d->d_StorDecl.ed_AssExp) {
5501 resolveStorageExp(d->d_StorDecl.ed_AssExp,
5504 if (*offset < save_offset)
5505 *offset = save_offset;
5508 case DOP_GLOBAL_STORAGE:
5510 Type *type = d->d_StorDecl.ed_Type;
5511 runesize_t save_offset = *goffset;
5513 resolveStorageType(type, &save_offset, 1);
5514 if (d->d_StorDecl.ed_AssExp) {
5515 resolveStorageExp(d->d_StorDecl.ed_AssExp,
5518 if (*goffset < save_offset)
5519 *goffset = save_offset;
5524 * Never try to resolve storage considerations for an
5525 * alias's assignment in the declaration itself. The
5526 * run-time context depends on who and how many other
5527 * parts of the program reference the alias and the expression
5528 * tree will be duplicated for each.
5531 if (d->d_ScopeFlags & SCOPE_GLOBAL)
5532 resolveStorageExp(d->d_AliasDecl.ed_AssExp, NULL, NULL);
5534 resolveStorageExp(d->d_AliasDecl.ed_AssExp, NULL, NULL);
5538 /* XXX what about ty_AssExp ? should be in global space */
5541 /* recursion already dealt with */
5547 if ((st = d->d_ProcDecl.ed_ProcBody) != NULL) {
5548 ResolveStorage(st, 0);
5558 * resolveStorageExp() - resolve the temporary storage required to
5559 * support the expression, if any.
5561 * We do not need to assign storage for expressions which return
5562 * lvalues, because they will simply return a pointer into
5563 * non-temporary storage.
5566 resolveStorageExpOnly(Exp *exp, runesize_t *offset)
5571 * Stop if the expression resolves to a type rather then a value,
5572 * e.g. when you do something like switch (typeof(int)) { ... }
5573 * Types are handled as thin pointers.
5575 exp->ex_Flags |= EXF_TMPRESOLVED;
5576 if (exp->ex_Flags & EXF_RET_TYPE) {
5577 *offset = (*offset + POINTER_ALIGN - 1) & ~(POINTER_ALIGN - 1);
5578 exp->ex_TmpOffset = *offset;
5579 *offset += sizeof(void *);
5585 * Assign temporary offset. This offset does not overlap temporary
5586 * space reserved for sub-expressions.
5588 * We must have an assigned type. Expression sequences like:
5589 * 'module.blah' are collapsed into 'blah' long before we get
5590 * here, or they should be. We should not encounter any
5591 * TOK_TCMV_ID expression tokens. Structural id's (the right hand
5592 * side of X.Y) are resolved by their parent expression node and
5593 * no typing or temporary space is required.
5595 * Expressions that return lvalues do not need temporary space.
5597 type = exp->ex_Type;
5599 switch(exp->ex_Token) {
5604 printf("EXP %p %04x %p\n",
5605 exp, exp->ex_Token, exp->ex_Decl);
5606 dassert_exp(exp, 0);
5609 exp->ex_TmpOffset = -3;
5610 } else if (type->ty_SQFlags & SF_LVALUE) {
5612 * Expressive elements which return lvalues do not get
5613 * temporary space. Note that this also prevents lvalues
5614 * such as large arrays (int ary[999999999]) from reserving
5615 * unnecessary stack space.
5617 * NOTE: SF_LVALUE is unrelated to SCOPE_LVALUE. SCOPE_LVALUE
5618 * applies to SemGroup storage (LValueStor). SF_LVALUE
5619 * merely flags the type for an expression as expecting
5620 * or not expecting an lvalue.
5624 * XXX removeme, LValueStor only applies to semgroups
5626 runesize_t lvmask = sizeof(LValueStor) - 1;
5627 *offset = (*offset + lvmask) & ~lvmask;
5628 exp->ex_TmpOffset = *offset;
5629 *offset = *offset + (lvmask + 1);
5631 exp->ex_TmpOffset = -2;
5634 * Reserve temporary space for potential intermediate
5637 * Compound expressions may need extra space to default-init
5638 * the compound value, it is expected to be available to the
5639 * generator right after the nominal type in the TmpOffset.
5640 * XXX also make available to the interpreter?
5642 * Procedure calls also may need extra space to default-init
5643 * the return value. XXX also make available to the
5646 *offset = (*offset + type->ty_AlignMask) & ~type->ty_AlignMask;
5647 exp->ex_TmpOffset = *offset;
5648 *offset = *offset + type->ty_Bytes;
5649 if (exp->ex_Token == TOK_COMPOUND) {
5651 * NOTE: type might not yet be changed to compound,
5652 * but single-element compound will use the
5653 * same temporary space.
5655 *offset += type->ty_TmpBytes;
5656 } else if (exp->ex_Token == TOK_CALL) {
5657 *offset += type->ty_TmpBytes;
5660 dassert(exp->ex_TmpOffset != -1);
5665 resolveStorageExpSub(Exp *exp, runesize_t *offset)
5669 * Early term. XXX don't do this. For the moment we have an issue
5670 * with how typeof() processes temporary expression storage. This
5671 * needs to be comprehensively fixed but it can be an issue if the
5672 * content is a dynamic type (via a ref or a var-args element)
5673 * so it is not trivial.
5675 if (exp->ex_Flags & EXF_RET_TYPE)
5679 resolveStorageType(exp->ex_Type, offset, 0);
5682 * Calculate the overlapping temporary space for sub-trees.
5684 if (exp->ex_Flags & EXF_BINARY) {
5686 * Ensure lhs's NON-RECURSIVE temporary storage on-return
5687 * does not intefere with rhs's, or vise-versa.
5689 * To do this offset the rhs storage by the non-recursive
5697 resolveStorageExp(exp->ex_Lhs, &xoffset);
5698 if (*offset < xoffset)
5700 if (exp->ex_Lhs->ex_TmpOffset >= 0) {
5701 xoffset = exp->ex_Lhs->ex_TmpOffset +
5702 exp->ex_Lhs->ex_Type->ty_Bytes;
5706 resolveStorageExp(exp->ex_Rhs, &xoffset);
5707 if (*offset < xoffset)
5709 } else if (exp->ex_Flags & EXF_UNARY) {
5710 resolveStorageExp(exp->ex_Lhs, offset);
5711 dassert_exp(exp, exp->ex_Lhs->ex_Next == NULL);
5712 } else if (exp->ex_Flags & EXF_COMPOUND) {
5714 * each element will be copied into the compound storage
5715 * in turn, so we can union the temporary storage required
5722 for (scan = exp->ex_Lhs; scan; scan = scan->ex_Next) {
5723 runesize_t xoffset = *offset;
5725 dassert_exp(scan, scan->ex_Type != NULL);
5727 resolveStorageExp(scan, &xoffset);
5728 if (noffset < xoffset)
5735 if (exp->ex_Token == TOK_CALL && exp->ex_Lhs->ex_Decl) {
5736 Declaration *d = exp->ex_Lhs->ex_Decl;
5737 fprintf(stderr, "FIXUP CALL %s type %p\n", d->d_Id, d->d_ProcDecl.ed_Type);
5738 dassert(d->d_Op == DOP_PROC);
5739 resolveStorageType(d->d_ProcDecl.ed_Type, offset, 0);
5744 /* XXX what about alias assign-expressions */
5745 else if (exp->ex_Flags & EXF_ALIAS) {
5747 dassert_decl(exp->ex_Decl,
5748 (exp->ex_Decl->d_ScopeFlags & SCOPE_GLOBAL) == 0);
5750 resolveStorageExp(exp->ex_Decl->d_AliasDecl.ed_AssExp, offset);
5756 * [re]resolve temporary storage requirements.
5758 * WARNING! This may be called more than once if an expression requires
5759 * resolve-time interpretation to generate a constant. In this
5760 * ex_TmpOffset for the sub-chain may be regenerated from 0,
5761 * and then just the top-level (post-constant-resolved)
5762 * ex_TmpOffset will be restored by the caller.
5765 resolveStorageExp(Exp *exp, runesize_t *offset)
5771 noffset = resolveStorageExpOnly(exp, &xoffset);
5773 resolveStorageExpSub(exp, &xoffset);
5774 if (*offset < xoffset)
5779 resolveStorageExpAlign(Exp *exp, runesize_t *expalignp)
5783 if (exp->ex_Flags & EXF_RET_TYPE) {
5784 if (*expalignp < POINTER_ALIGN)
5785 *expalignp = POINTER_ALIGN;
5789 resolveDecl(exp->ex_Decl, 0);
5793 type = exp->ex_Type;
5799 if (type->ty_SQFlags & SF_LVALUE) {
5800 if (*expalignp < POINTER_ALIGN)
5801 *expalignp = POINTER_ALIGN;
5803 if (*expalignp < type->ty_AlignMask)
5804 *expalignp = type->ty_AlignMask;
5806 resolveStorageTypeExpAlign(type, expalignp);
5809 if (exp->ex_Flags & EXF_BINARY) {
5810 resolveStorageExpAlign(exp->ex_Lhs, expalignp);
5811 resolveStorageExpAlign(exp->ex_Rhs, expalignp);
5812 } else if (exp->ex_Flags & EXF_UNARY) {
5813 resolveStorageExpAlign(exp->ex_Lhs, expalignp);
5814 } else if (exp->ex_Flags & EXF_COMPOUND) {
5817 for (scan = exp->ex_Lhs; scan; scan = scan->ex_Next) {
5818 resolveStorageExpAlign(scan, expalignp);
5821 } else if (exp->ex_Flags & EXF_ALIAS) {
5822 resolveStorageExpAlign(exp->ex_Decl->d_AliasDecl.ed_AssExp,
5828 if (exp->ex_Token == TOK_CALL && exp->ex_Lhs->ex_Decl) {
5829 Declaration *d = exp->ex_Lhs->ex_Decl;
5830 dassert(d->d_Op == DOP_PROC);
5831 resolveStorageTypeExpAlign(d->d_ProcDecl.ed_Type, expalignp);
5832 if (d->d_ProcDecl.ed_ProcBody)
5833 ResolveAlignment(d->d_ProcDecl.ed_ProcBody, 0);
5839 * resolveStorageType() - temporary space required to initialize type defaults
5841 * Figure out the temporary space required to initialize a type's
5842 * defaults. Note that the space will be figured independantly
5843 * for any SemGroup's.
5847 resolveStorageTypeExpAlign(Type *type, runesize_t *expalignp)
5849 SemGroup *sg = NULL;
5850 Type *subtype1 = NULL;
5851 Type *subtype2 = NULL;
5853 if (type->ty_Flags & TF_ALIGNRESOLVED) {
5854 if (*expalignp < type->ty_TmpAlignMask)
5855 *expalignp = type->ty_TmpAlignMask;
5858 type->ty_Flags |= TF_ALIGNRESOLVED;
5860 switch(type->ty_Op) {
5862 sg = type->ty_ClassType.et_SemGroup;
5865 subtype1 = type->ty_AryType.et_Type;
5868 sg = type->ty_CompType.et_SemGroup;
5871 subtype1 = type->ty_ProcType.et_ArgsType;
5872 subtype2 = type->ty_ProcType.et_RetType;
5875 sg = type->ty_ImportType.et_SemGroup;
5878 sg = type->ty_ArgsType.et_SemGroup;
5881 sg = type->ty_VarType.et_SemGroup;
5884 /* has nothing to do with initializing the pointer */
5885 /* subtype1 = type->ty_CPtrType.et_Type; */
5888 /* has nothing to do with initializing the pointer */
5889 /* subtype1 = type->ty_PtrType.et_Type; */
5892 /* has nothing to do with initializing the pointer */
5893 /* subtype1 = type->ty_RefType.et_Type; */
5898 * nothing to be done here.
5901 case TY_UNRESOLVED: /* should be no unresolved types at this stage */
5903 dassert_type(type, 0);
5907 resolveStorageTypeExpAlign(subtype1, &subtype1->ty_TmpAlignMask);
5908 if (subtype1->ty_AssExp) {
5909 resolveStorageExpAlign(subtype1->ty_AssExp,
5910 &subtype1->ty_TmpAlignMask);
5912 if (type->ty_TmpAlignMask < subtype1->ty_TmpAlignMask)
5913 type->ty_TmpAlignMask = subtype1->ty_TmpAlignMask;
5916 resolveStorageTypeExpAlign(subtype2, &subtype2->ty_TmpAlignMask);
5917 if (subtype2->ty_AssExp) {
5918 resolveStorageExpAlign(subtype2->ty_AssExp,
5919 &subtype2->ty_TmpAlignMask);
5921 if (type->ty_TmpAlignMask < subtype2->ty_TmpAlignMask)
5922 type->ty_TmpAlignMask = subtype2->ty_TmpAlignMask;
5924 if (type->ty_AssExp) {
5925 resolveStorageExpAlign(type->ty_AssExp, &type->ty_TmpAlignMask);
5928 if (resolveSemGroup1(sg, 0) && resolveSemGroup2(sg, 0))
5929 resolveSemGroup3(sg, 0);
5930 resolveStorageSemGroupAlign(sg);
5931 if (type->ty_TmpAlignMask < sg->sg_TmpAlignMask)
5932 type->ty_TmpAlignMask = sg->sg_TmpAlignMask;
5934 if (*expalignp < type->ty_TmpAlignMask)
5935 *expalignp = type->ty_TmpAlignMask;
5940 resolveStorageType(Type *type, runesize_t *offset, int isglob)
5942 SemGroup *sg = NULL;
5943 Type *subtype1 = NULL;
5944 Type *subtype2 = NULL;
5945 runesize_t save_offset1;
5946 runesize_t save_offset2;
5947 runesize_t save_offset3;
5948 runesize_t save_offsetx;
5950 dassert(type->ty_Flags & TF_ALIGNRESOLVED);
5951 if (type->ty_Flags & TF_TMPRESOLVED)
5953 type->ty_Flags |= TF_TMPRESOLVED;
5955 switch(type->ty_Op) {
5957 sg = type->ty_ClassType.et_SemGroup;
5960 subtype1 = type->ty_AryType.et_Type;
5963 sg = type->ty_CompType.et_SemGroup;
5966 subtype1 = type->ty_ProcType.et_ArgsType;
5967 subtype2 = type->ty_ProcType.et_RetType;
5970 sg = type->ty_ImportType.et_SemGroup;
5973 sg = type->ty_ArgsType.et_SemGroup;
5976 sg = type->ty_VarType.et_SemGroup;
5979 /* has nothing to do with initializing the pointer */
5980 /* subtype1 = type->ty_CPtrType.et_Type; */
5983 /* has nothing to do with initializing the pointer */
5984 /* subtype1 = type->ty_PtrType.et_Type; */
5987 /* has nothing to do with initializing the pointer */
5988 /* subtype1 = type->ty_RefType.et_Type; */
5993 * nothing to be done here.
5996 case TY_UNRESOLVED: /* should be no unresolved types at this stage */
5998 dassert_type(type, 0);
6001 save_offset1 = *offset;
6002 save_offset2 = *offset;
6003 save_offset3 = *offset;
6004 save_offsetx = *offset;
6006 /*resolveType(subtype1, NULL, 0);*/
6007 resolveStorageType(subtype1, &subtype1->ty_TmpBytes, 0);
6008 if (subtype1->ty_AssExp) {
6009 resolveStorageExp(subtype1->ty_AssExp,
6010 &subtype1->ty_TmpBytes);
6012 save_offset1 += subtype1->ty_TmpBytes;
6013 if (type->ty_TmpAlignMask < subtype1->ty_TmpAlignMask)
6014 type->ty_TmpAlignMask = subtype1->ty_TmpAlignMask;
6017 /*resolveType(subtype2, NULL, 0);*/
6018 resolveStorageType(subtype2, &subtype2->ty_TmpBytes, 0);
6019 if (subtype2->ty_AssExp) {
6020 resolveStorageExp(subtype2->ty_AssExp,
6021 &subtype2->ty_TmpBytes);
6023 save_offset2 += subtype2->ty_TmpBytes;
6024 if (type->ty_TmpAlignMask < subtype2->ty_TmpAlignMask)
6025 type->ty_TmpAlignMask = subtype2->ty_TmpAlignMask;
6027 if (type->ty_AssExp) {
6028 resolveStorageExp(type->ty_AssExp, &type->ty_TmpBytes);
6031 if (resolveSemGroup1(sg, 0) && resolveSemGroup2(sg, 0))
6032 resolveSemGroup3(sg, 0);
6033 resolveStorageSemGroup(sg, 0, 0);
6035 save_offset3 += sg->sg_GlobalTmpBytes;
6037 save_offset3 += sg->sg_TmpBytes;
6041 * Re-resolve the type flags. XXX mostly fixed once I handled
6042 * CBase/DBase/GBase in resolveSemGroup1().
6044 if (sg->sg_Flags & SGF_HASASS)
6045 type->ty_Flags |= TF_HASASS;
6047 type->ty_Flags |= TF_HASLVPTR;
6048 if (sg->sg_Flags & SGF_VARARGS)
6049 type->ty_Flags |= TF_HASLVPTR; /* XXX TF_VARARGS */
6051 type->ty_Flags |= TF_HASCONSTRUCT;
6053 type->ty_Flags |= TF_HASDESTRUCT;
6056 if (*offset < save_offset1)
6057 *offset = save_offset1;
6058 if (*offset < save_offset2)
6059 *offset = save_offset2;
6060 if (*offset < save_offset3)
6061 *offset = save_offset3;
6062 type->ty_TmpBytes = *offset - save_offsetx;
6066 * This is used to resolve temporary storage requirements for
6067 * SemGroup's related to classes and compound types. Temporary storage
6068 * requirements are calculated on a SemGroup-by-SemGroup basis and not
6069 * aggregated into any parent.
6071 * In the final pass we also reverse the constructor and destructor lists
6072 * (sg_CBase and sg_DBase), and the pointer/lvalue list (SRBase). These
6073 * lists were originally constructed by prepending and are thus in the
6078 resolveStorageSemGroupAlign(SemGroup *sg)
6082 if (sg->sg_Flags & SGF_ALIGNRESOLVED)
6084 sg->sg_Flags |= SGF_ALIGNRESOLVED;
6087 * SGF_RESOLVED might not be set. This can only happen because we
6088 * allow individual declarations in global SemGroups to be resolved
6089 * without having to resolve the whole group. This allows unused
6090 * declarations to be omitted by the code generator.
6092 if ((sg->sg_Flags & SGF_RESOLVED) == 0)
6093 sg->sg_Flags |= SGF_RESOLVED;
6095 RUNE_FOREACH(d, &sg->sg_DeclList, d_Node) {
6096 resolveStorageDeclExpAlign(d, &sg->sg_TmpAlignMask);
6097 if (d->d_ScopeFlags & SCOPE_GLOBAL) {
6098 if (sg->sg_GlobalAlignMask < d->d_AlignMask)
6099 sg->sg_GlobalAlignMask = d->d_AlignMask;
6101 if (sg->sg_AlignMask < d->d_AlignMask)
6102 sg->sg_AlignMask = d->d_AlignMask;
6109 resolveStorageSemGroup(SemGroup *sg, runesize_t noffset, runesize_t ngoffset)
6115 if ((sg->sg_Flags & SGF_RESOLVED) == 0) {
6116 if (resolveSemGroup1(sg, 0) && resolveSemGroup2(sg, 0))
6117 resolveSemGroup3(sg, 0);
6120 dassert(sg->sg_Flags & SGF_ALIGNRESOLVED);
6121 if (sg->sg_Flags & SGF_TMPRESOLVED)
6123 sg->sg_Flags |= SGF_TMPRESOLVED;
6128 RUNE_FOREACH(d, &sg->sg_DeclList, d_Node) {
6129 runesize_t offset = 0;
6130 runesize_t goffset = 0;
6132 resolveStorageDeclExp(d, &offset, &goffset);
6133 if (noffset < offset)
6135 if (ngoffset < goffset)
6142 if ((d2 = sg->sg_CBase) != NULL) {
6143 sg->sg_CBase = NULL;
6144 while ((d = d2) != NULL) {
6146 d->d_CNext = sg->sg_CBase;
6150 if ((d2 = sg->sg_DBase) != NULL) {
6151 sg->sg_DBase = NULL;
6152 while ((d = d2) != NULL) {
6154 d->d_DNext = sg->sg_DBase;
6158 if ((d2 = sg->sg_GBase) != NULL) {
6159 sg->sg_GBase = NULL;
6160 while ((d = d2) != NULL) {
6162 d->d_GNext = sg->sg_GBase;
6166 if ((d2 = sg->sg_SRBase) != NULL) {
6167 sg->sg_SRBase = NULL;
6168 while ((d = d2) != NULL) {
6170 d->d_SRNext = sg->sg_SRBase;
6174 sg->sg_TmpBytes = noffset;
6175 sg->sg_GlobalTmpBytes = ngoffset;
6179 * Return non-zero if the method procedure wants the 'this' variable
6180 * to be an lvalue-pointer rather than an lvalue-target-object. In this
6181 * situation we do not want to indirect the pointer.
6185 methodProcThisIsPointer(Type *type)
6191 dassert(type->ty_Op == TY_PROC);
6192 dassert(type->ty_ProcType.et_ArgsType->ty_Op == TY_ARGS);
6193 sg = type->ty_ProcType.et_ArgsType->ty_CompType.et_SemGroup;
6194 d = RUNE_FIRST(&sg->sg_DeclList);
6195 dassert(d->d_Id == String_This);
6196 switch (d->d_StorDecl.ed_Type->ty_Op) {
6205 "methodProcThisIsPointer(): method call through "
6206 "C pointer is illegal\n");
6218 * Calculate SG dependencies
6220 #define SGDEP_HSIZE 1024
6221 #define SGDEP_HMASK (SGDEP_HSIZE - 1)
6223 SGDepend *SGDepHash[SGDEP_HSIZE];
6224 SemGroup *SGCurrentDep;
6228 resolveSGDependHash(SemGroup *src, SemGroup *dst)
6232 hv = ((intptr_t)src >> 7) ^ ((intptr_t)dst >> 5);
6234 return (&SGDepHash[hv & SGDEP_HMASK]);
6239 resolvePushSGDepend(SemGroup *sg)
6245 depp = resolveSGDependHash(SGCurrentDep, sg);
6246 for (dep = *depp; dep; dep = dep->hnext) {
6247 if (dep->src == SGCurrentDep && dep->dst == sg)
6251 dep = zalloc(sizeof(SGDepend));
6253 dep->src = SGCurrentDep;
6257 dep->next = SGCurrentDep->sg_DepFirst;
6258 SGCurrentDep->sg_DepFirst = dep;
6261 last = SGCurrentDep;
6269 resolvePopSGDepend(SemGroup *dep)