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 float128_t resolveGetConstExpFloat128(Exp *exp);
33 static Exp *resolveCompoundExp(SemGroup *isg, SemGroup *sg,
34 Exp *exp, Type *itype, int flags);
35 static Exp *resolveExpCast(SemGroup *isg, SemGroup *sg,
36 Exp *exp, Type *ltype, int flags);
37 static Exp *resolveExpOper(SemGroup *isg, SemGroup *sg,
38 Exp *exp, Type *itype, int flags);
39 static int resolveSemGroup1(SemGroup *sg, int flags);
40 static int resolveSemGroup2(SemGroup *sg, int flags);
41 static void resolveSemGroup3(SemGroup *sg, int flags);
42 static Type *resolveSuperClass(Type *super);
44 static void resolveStorageDeclExpAlign(Declaration *d, runesize_t *expalignp,
46 static void resolveStorageExpAlign(Exp *exp, runesize_t *expalignp,
48 static void resolveStorageTypeExpAlign(Type *type, runesize_t *expalignp,
50 static void resolveStorageSemGroupAlign(SemGroup *sg, int flags);
52 static void resolveStorageDeclExp(Declaration *d,
53 runesize_t *offset, runesize_t *goffset);
54 static runesize_t resolveStorageExpOnly(Exp *exp, runesize_t *offset);
55 static void resolveStorageExpSub(Exp *exp, runesize_t *offset);
56 static void resolveStorageExp(Exp *exp, runesize_t *offset);
58 static Declaration *findOper(Type *btype, string_t id,
59 Type *ltype, Type *rtype, int flags);
60 static Declaration *findExpOper(Exp *exp, int flags);
61 static Declaration *findCast(Type *btype, Type *ltype, Type *rtype, int flags);
62 static void loadExpCopy(Exp *copy, Exp *exp);
63 static void saveExpCopy(Exp *copy, Exp *exp);
64 static Exp *dupExpCopy(Exp *copy, Exp *exp);
65 static void resolveStorageType(Type *type, runesize_t *offset, int isglob);
66 static void resolveStorageSemGroup(SemGroup *sg,
67 runesize_t noffset, runesize_t ngoffset);
68 static int methodProcThisIsPointer(Type *type);
70 static SemGroup *resolvePushSGDepend(SemGroup *sg);
71 static void resolvePopSGDepend(SemGroup *last);
73 #define exLhs copy.ex_Lhs
74 #define exRhs copy.ex_Rhs
75 #define exFlags copy.ex_Flags
76 #define exType copy.ex_Type
77 #define exToken copy.ex_Token
78 #define exDecl copy.ex_Decl
79 #define exVisibility copy.ex_Visibility
80 #define exId copy.ex_Id
81 #define exArgId copy.ex_ArgId
83 #define ADD_LVALUE(type) \
84 resolveType(AddTypeQual((type), SF_LVALUE), NULL, flags)
85 #define DEL_LVALUE(type) \
86 resolveType(DelTypeQual((type), SF_LVALUE), NULL, flags)
87 #define RESOLVETYPE(type) \
88 resolveType((type), NULL, flags)
89 #define RESOLVETYPEADJ(type, adjtype) \
90 resolveType((type), adjtype, flags)
92 #define RESOLVE_AUTOCAST 0x0001 /* autocast to expected type */
93 #define RESOLVE_CONSTEXP 0x0002 /* resolve for const interpretation */
96 ResolveProject(Parse *p, Stmt *st)
100 dassert_stmt(st, st->st_Op == ST_Import);
105 ResolveClasses(st, 0);
106 resolveStmt(st->st_MyGroup, st, 0);
107 ResolveAlignment(st, 0);
108 ResolveStorage(st, 0);
111 * Interpreter or Generator may reference our global internal types
112 * directly, so make sure they are all resolved.
114 for (i = 0; BaseTypeAry[i]; ++i)
115 resolveType(BaseTypeAry[i], NULL, 0);
118 * Resolve all types registered by DLLs
123 RUNE_FOREACH(tr, &TypeRegList, tr_Node)
124 resolveType(tr->tr_Type, NULL, 0);
128 p->p_Format = PFMT_RESOLVED;
134 * ResolveClasses() - Resolve superclasses and do class merge
136 * This code implements the most complex feature of the language:
137 * subclassing and refinement.
139 * The hardest thing we have to do is 'dup' declarations and code in
140 * order to implement subclassing and refinement. For example, a
141 * procedure defined in Integer must be dup'd for each subclass of
142 * Integer. We have to do this because storage requirements will
143 * change due to both subclassing and refinement. Even auto variables
144 * may wind up with different types between superclass and subclass.
146 * We must scan ST_Import and ST_Class statements.
149 ResolveClasses(Stmt *st, int flags)
151 SemGroup *sg = st->st_MyGroup;
154 * Resolver interlock. Assert that we aren't looping. A loop can
155 * occur if class A embeds class B and class B embeds class A
156 * (verses a pointer to A).
158 dassert_stmt(st, (st->st_Flags & STF_RESOLVING) == 0);
159 if (st->st_Flags & STF_RESOLVED)
161 st->st_Flags |= STF_RESOLVING;
164 * If this is a subclass, integrate the superclass into it
166 if (st->st_Op == ST_Class && st->st_ClassStmt.es_Super) {
167 Type *super = st->st_ClassStmt.es_Super;
174 * Locate the superclass. 'super' does not appear in any
175 * other list.. this is a unique Type structure.
177 dassert_stmt(st, super->ty_Op == TY_UNRESOLVED);
179 super = resolveSuperClass(super);
182 "Unable to resolve superclass of %s\n",
183 st->st_ClassStmt.es_Decl->d_Id);
186 } while (super->ty_Op == TY_UNRESOLVED);
188 dassert_stmt(st, super->ty_Op == TY_CLASS);
191 * Cleanup (XXX free qualified segments??)
193 st->st_ClassStmt.es_Super = super;
194 st->st_ClassStmt.es_Decl->d_ClassDecl.ed_Super = super;
197 * Inherit internal unsigned integer and floating point flags
200 sg->sg_Flags |= super->ty_ClassType.et_SemGroup->sg_Flags &
201 (SGF_ISINTEGER | SGF_ISUNSIGNED |
202 SGF_ISFLOATING | SGF_ISBOOL |
203 SGF_HASASS | SGF_GHASASS |
204 SGF_HASLVPTR | SGF_GHASLVPTR);
207 * Locate the class statement associated with the superclass
210 sst = super->ty_ClassType.et_SemGroup->sg_Stmt;
211 dassert_stmt(st, sst != NULL);
212 dassert_stmt(st, sst->st_Op == ST_Class);
214 ResolveClasses(sst, flags);
217 * Assign the sg_Level for the subclass. This is used
218 * for semantic searches when a subclass is passed to a
219 * procedure expecting the superclass.
221 sg->sg_Level = sst->st_MyGroup->sg_Level + 1;
224 * First move all the declarations from sg to tsg so we
225 * can merge the superclass properly (keep all the d_Index's
226 * correct). Note that tsg is not 100% integrated so we can
227 * only use it for search purposes. We absolutely CANNOT
228 * DupDeclaration() into tsg!
230 tsg = AllocSemGroup(SG_CLASS, sg->sg_Parse, NULL, sg->sg_Stmt);
231 while ((d = RUNE_FIRST(&sg->sg_DeclList)) != NULL) {
234 sg->sg_DeclCount = 0; /* reset */
237 * Merge the superclass into this class, in sequence.
238 * Iterate through declarations in the superclass and pull
239 * them into the subclass. Figure out compatibility between
240 * super and subclasses.
242 RUNE_FOREACH(d, &sst->st_MyGroup->sg_DeclList, d_Node) {
246 dassert(d->d_Level != NULL &&
247 d->d_Level->sg_Level < sg->sg_Level);
250 * See if the superclass decl conflicts with a
251 * subclass decl. If there is no conflict pull it
252 * into the subclass and adjust the visibility.
253 * Note that the superclass may have duplicate ids,
254 * but they will be at different levels if so.
256 * The super linkage is required when findDecl()
257 * checks visibility of a declaration hidden relative
258 * to our subclass, but not necessarily hidden
259 * relative to the superclass.
263 rd = FindDeclId(tsg, d->d_Id, &eno);
265 nd = DupDeclaration(sg, d);
266 dassert(d->d_Index == nd->d_Index);
267 nd->d_ScopeFlags &= ~SCOPE_ALL_VISIBLE |
268 super->ty_Visibility;
269 nd->d_ScopeFlags &= ~SCOPE_REFINE;
274 * If there is a conflict and we are not refining
275 * the superclass entity, then pull in the superclass
276 * entity and make it invisible to sg_Level searches.
277 * This could bring in multiple levels of the same id.
279 * Note that this may result in multiple ids, but
280 * they will be at different levels. In this case
281 * rd will be at the current level and nd will be
282 * at some prior level.
284 * Order is important here.
286 if ((rd->d_ScopeFlags & SCOPE_REFINE) == 0) {
287 nd = DupDeclaration(sg, d);
288 dassert(d->d_Index == nd->d_Index);
289 nd->d_ScopeFlags &= ~(SCOPE_ALL_VISIBLE |
292 printf(" conflict, not refined, overload\n");
298 * Ok, we need to refine. But the superclass may
299 * contain multiple levels of the same id. We only
300 * refine the one that is visible to us. None of
301 * these other declarations will be at the same level.
303 if ((d->d_ScopeFlags & SCOPE_ALL_VISIBLE) == 0) {
304 nd = DupDeclaration(sg, d);
305 dassert(d->d_Index == nd->d_Index);
306 nd->d_ScopeFlags &= ~(SCOPE_ALL_VISIBLE |
309 printf(" conflict, refined (skip this one)\n");
315 * Whew! Finally, we found the superclass decl
316 * that we wish to refine. We had better not have
317 * already refined it or there's something wrong
318 * with the algorithm.
320 * Since we inherit the superclass method's level
321 * our method will run in the superclass instead
322 * of the original, but d_Super still must be set
323 * for findDecl() to track down visibility relative
324 * to the superclass methods.
327 dassert_decl(rd, rd->d_Super == NULL);
328 dassert(d->d_Index == rd->d_Index);
329 rd->d_Level = d->d_Level;
333 * This is for the superclass method access special
336 if (d->d_Op == DOP_PROC) {
337 d->d_Flags |= DF_SUPERCOPY;
342 * Deal with any remaining elements in tsg. These are
343 * 'extensions' to the superclass. There may also be
344 * invisible DOP_PROC's to handle the special superclass
345 * method call case descibed above.
347 while ((rd = RUNE_FIRST(&tsg->sg_DeclList)) != NULL) {
348 if (rd->d_ScopeFlags & SCOPE_REFINE) {
349 if (rd->d_Super == NULL) {
351 "Unable to refine %s, it "
364 * We have to special case super.method() for a refined method.
365 * Normally this makes the original method inaccessible (for
366 * storage), but we want it to work for a procedure so we make
367 * a copy in tsg. (we can't dup it directly into sg because it
368 * will screw up the d_Index).
370 * We must not only clear the scope visibility and the
371 * temporary refine flag, we also have to clear
372 * constructor/destructor scope in the copy so only the
373 * refined constructor/destructor is called, not both the
374 * refined and the superclass constructor/destructor.
376 RUNE_FOREACH(d, &sst->st_MyGroup->sg_DeclList, d_Node) {
379 if (d->d_Flags & DF_SUPERCOPY) {
380 d->d_Flags &= ~DF_SUPERCOPY;
381 nd = DupDeclaration(sg, d);
382 nd->d_ScopeFlags &= ~(SCOPE_ALL_VISIBLE |
388 } else if (st->st_Op == ST_Class) {
392 st->st_Flags &= ~STF_RESOLVING;
393 st->st_Flags |= STF_RESOLVED;
396 * If this is an ST_Import we must recurse through it. The only
397 * statements under an Import should be Modules. Well, really just
398 * one module. And under that module we only care about ST_Import
399 * and ST_Class statements.
401 * If this is a shared import the statement list will be empty (later
402 * it may be used for import refinement, I dunno). This is what we
403 * want since we should only resolve a shared import once.
405 if (st->st_Op == ST_Import) {
408 RUNE_FOREACH(scan, &st->st_List, st_Node) {
411 dassert_stmt(scan, scan->st_Op == ST_Module);
412 RUNE_FOREACH(scan2, &scan->st_List, st_Node) {
413 if (scan2->st_Op == ST_Import ||
414 scan2->st_Op == ST_Class) {
415 ResolveClasses(scan2, flags);
419 if (st->st_ImportStmt.es_DLL) {
420 void (*func)(void) = dlsym(st->st_ImportStmt.es_DLL,
429 * resolveStmt() - Resolve all types, declarations, and semantic refs
431 * Resolves all types, declarations, and identifiers. Additionally
432 * this function resolves intermediate types for expressions. Storage
433 * sizes are resolved but offsets are not assigned to declarations.
436 resolveStmt(SemGroup *isg, Stmt *st, int flags)
438 SemGroup *dep = NULL;
441 * Process whether we detached as a thread already or not.
444 st->st_Flags |= st->st_Parent->st_Flags & STF_DIDRESULT;
447 * Deal with unresolved types here
449 if (st->st_Flags & STF_SEMANTIC) {
450 SemGroup *sg = st->st_MyGroup;
453 dep = resolvePushSGDepend(sg);
455 RUNE_FOREACH(type, &sg->sg_ClassList, ty_Node) {
456 if (type->ty_Op == TY_UNRESOLVED) {
457 if (resolveSuperClass(type) == NULL) {
459 type->ty_UnresType.et_DottedId,
460 "Unable to resolve class");
468 * Resolve statements. Don't worry about declarations, those are
469 * handled after this switch.
474 * This will just flag the import declaration as resolved
475 * so the code generator dives it for generation.
477 if (st->st_ImportStmt.es_Decl)
478 resolveDecl(st->st_ImportStmt.es_Decl, flags);
482 * Recursively resolve contents
487 RUNE_FOREACH(scan, &st->st_List, st_Node) {
489 * XXX pass isg for import, st_MyGroup for
492 resolveStmt(st->st_MyGroup, scan, flags);
494 if (st->st_Op == ST_Import &&
495 st->st_ImportStmt.es_DLL) {
497 dlsym(st->st_ImportStmt.es_DLL,
505 resolveDecl(st->st_ClassStmt.es_Decl, flags);
508 resolveDecl(st->st_TypedefStmt.es_Decl, flags);
512 * Resolve declarations, skipping any whos context was
513 * moved to a class (e.g. a declaration at the top level
514 * of a file like Fd.setfd(...) also exists in the Fd class).
517 Declaration *d = st->st_DeclStmt.es_Decl;
520 for (i = 0; i < st->st_DeclStmt.es_DeclCount; ++i) {
521 if (st->st_MyGroup != d->d_MyGroup)
522 /*printf("SKIPA %s\n", d->d_Id)*/;
524 resolveDecl(d, flags);
525 d = RUNE_NEXT(d, d_Node);
533 RUNE_FOREACH(scan, &st->st_List, st_Node) {
534 resolveStmt(isg, scan, flags);
541 if (st->st_LoopStmt.es_Init)
542 resolveStmt(isg, st->st_LoopStmt.es_Init, flags);
543 if (st->st_LoopStmt.es_BCond) {
545 * NOTE: BoolType global implies an rvalue.
547 st->st_LoopStmt.es_BCond =
548 resolveExp(isg, st->st_MyGroup,
549 st->st_LoopStmt.es_BCond,
550 &BoolType, RESOLVE_AUTOCAST);
552 if (st->st_LoopStmt.es_ACond) {
554 * NOTE: BoolType global implies an rvalue.
556 st->st_LoopStmt.es_ACond =
557 resolveExp(isg, st->st_MyGroup,
558 st->st_LoopStmt.es_ACond,
559 &BoolType, RESOLVE_AUTOCAST);
561 if (st->st_LoopStmt.es_AExp) {
563 * NOTE: VoidType global implies an rvalue.
565 st->st_LoopStmt.es_AExp =
566 resolveExp(isg, st->st_MyGroup,
567 st->st_LoopStmt.es_AExp,
568 &VoidType, RESOLVE_AUTOCAST);
570 if (st->st_LoopStmt.es_Body) {
571 resolveStmt(isg, st->st_LoopStmt.es_Body, flags);
573 /* remove handled in resolveDecl DOP_PROC */
574 if ((st->st_LoopStmt.es_Body->st_Flags &
575 STF_RESOLVED) == 0) {
576 ResolveAlignment(st->st_LoopStmt.es_Body,
578 ResolveStorage(st->st_LoopStmt.es_Body, flags);
589 * NOTE: BoolType global implies an rvalue.
591 st->st_IfStmt.es_Exp = resolveExp(isg, st->st_MyGroup,
592 st->st_IfStmt.es_Exp,
593 &BoolType, RESOLVE_AUTOCAST);
594 resolveStmt(isg, st->st_IfStmt.es_TrueStmt, flags);
595 if (st->st_IfStmt.es_FalseStmt)
596 resolveStmt(isg, st->st_IfStmt.es_FalseStmt, flags);
600 * NOTE: lvalue/rvalue depends on return type.
602 st->st_RetStmt.es_ProcRetType =
603 resolveReturnType(st->st_MyGroup, flags);
604 if (st->st_RetStmt.es_Exp) {
605 if (st->st_Flags & STF_DIDRESULT)
606 StmtFatalError(st, TOK_ERR_RESULT_SEQUENCING);
607 st->st_RetStmt.es_Exp =
608 resolveExp(isg, st->st_MyGroup,
609 st->st_RetStmt.es_Exp,
610 st->st_RetStmt.es_ProcRetType,
616 * NOTE: lvalue/rvalue depends on return type.
618 if (st->st_Flags & STF_DIDRESULT)
619 StmtFatalError(st, TOK_ERR_RESULT_SEQUENCING);
620 if ((st->st_Parent->st_Flags & STF_SEMTOP) == 0)
621 StmtFatalError(st, TOK_ERR_RESULT_SEQUENCING);
622 st->st_ResStmt.es_ProcRetType =
623 resolveReturnType(st->st_MyGroup, flags);
624 if (st->st_ResStmt.es_Exp) {
625 st->st_ResStmt.es_Exp =
626 resolveExp(isg, st->st_MyGroup,
627 st->st_ResStmt.es_Exp,
628 st->st_ResStmt.es_ProcRetType,
633 * Flag that we executed result;
637 for (scan = st; scan; scan = scan->st_Parent) {
638 scan->st_Flags |= STF_DIDRESULT;
639 scan->st_MyGroup->sg_Flags |= SGF_DIDRESULT;
640 if (scan->st_Flags & STF_SEMTOP)
647 * NOTE: Switch type must be an rvalue.
649 * NOTE: It is possible to switch on a type. See ST_Case
650 * below for more detail.
652 st->st_SwStmt.es_Exp->ex_Flags |= EXF_REQ_TYPE;
653 st->st_SwStmt.es_Exp = resolveExp(isg, st->st_MyGroup,
654 st->st_SwStmt.es_Exp,
658 * Switch-on-expression() expects an rvalue.
660 if ((st->st_SwStmt.es_Exp->ex_Flags & EXF_RET_TYPE) == 0) {
661 st->st_SwStmt.es_Exp->ex_Type =
662 DEL_LVALUE(st->st_SwStmt.es_Exp->ex_Type);
667 RUNE_FOREACH(scan, &st->st_List, st_Node) {
668 resolveStmt(isg, scan, flags);
674 * Handle a case/default. Note that when switching on a type,
675 * each case expression must return a type.
677 * NOTE: Case type must be an rvalue. We use the switch type
678 * to cast, so it will be.
686 * Set type to cast cases to if we are switching on
687 * an expression, otherwise we are switching on a
688 * type and should not try to coerce the cases (it
689 * doesn't make sense to).
691 dassert_stmt(st, st->st_Parent->st_Op == ST_Switch);
692 if (st->st_Parent->st_SwStmt.es_Exp->ex_Flags & EXF_RET_TYPE)
695 type = st->st_Parent->st_SwStmt.es_Exp->ex_Type;
698 * case: (if es_Exp is NULL, this is a default: )
700 if ((exp = st->st_CaseStmt.es_Exp) != NULL) {
702 exp->ex_Flags |= EXF_REQ_TYPE;
703 exp = resolveExp(isg, st->st_MyGroup,
704 exp, type, RESOLVE_AUTOCAST);
706 dassert(exp->ex_Flags & EXF_RET_TYPE);
707 st->st_CaseStmt.es_Exp = exp;
711 * Elements of the case/default
713 RUNE_FOREACH(scan, &st->st_List, st_Node) {
714 resolveStmt(isg, scan, flags);
720 * NOTE: VoidType global implies an rvalue.
722 * NOTE: If resolveExp() doesn't cast to void for
723 * us, we will do it here.
728 exp = resolveExp(isg, st->st_MyGroup,
729 st->st_ExpStmt.es_Exp,
730 &VoidType, RESOLVE_AUTOCAST);
731 if (exp->ex_Type != &VoidType) {
732 exp = resolveExpCast(isg, st->st_MyGroup,
733 exp, &VoidType, flags);
735 st->st_ExpStmt.es_Exp = exp;
742 RUNE_FOREACH(scan, &st->st_List, st_Node) {
743 resolveStmt(isg, scan, flags);
752 if (st->st_Flags & STF_SEMANTIC)
753 resolvePopSGDepend(dep);
757 * Locate the ST_Proc statement and resolve & return its return type
761 resolveReturnType(SemGroup *sg, int flags __unused)
768 * Locate the ST_Proc statement
770 while (sg && (sg->sg_Stmt == NULL || sg->sg_Stmt->st_Op != ST_Proc))
774 d = st->st_ProcStmt.es_Decl; /* decl is already resolved */
775 dassert_decl(d, d->d_Op == DOP_PROC);
776 dassert_decl(d, d->d_Flags & (DF_RESOLVING|DF_RESOLVED));
777 type = d->d_ProcDecl.ed_Type;
778 dassert_decl(d, type->ty_Op == TY_PROC);
779 return(type->ty_ProcType.et_RetType);
783 resolveArgsType(SemGroup *sg, int flags __unused)
790 * Locate the ST_Proc statement
792 while (sg && (sg->sg_Stmt == NULL || sg->sg_Stmt->st_Op != ST_Proc))
796 d = st->st_ProcStmt.es_Decl; /* decl is already resolved */
797 dassert_decl(d, d->d_Op == DOP_PROC);
798 dassert_decl(d, d->d_Flags & (DF_RESOLVING|DF_RESOLVED));
799 type = d->d_ProcDecl.ed_Type;
800 dassert_decl(d, type->ty_Op == TY_PROC);
801 return(type->ty_ProcType.et_ArgsType);
805 * resolveDecl() - resolve a declaration
807 * Note: we do not resolve d_Offset here.
809 * If the declaration represents a procedure argument, special
810 * processing of LVALUE scope is required to pass the declaration
811 * by reference instead of by value. Note that the size of the
812 * underlying type DOES NOT CHANGE... it may be much larger.
815 resolveDecl(Declaration *d, int flags)
821 if (d->d_Flags & DF_RESOLVED)
823 dassert_decl(d, (d->d_Flags & DF_RESOLVING) == 0);
824 d->d_Flags |= DF_RESOLVING;
828 if (d->d_ClassDecl.ed_Super) {
829 d->d_ClassDecl.ed_Super =
830 RESOLVETYPE(d->d_ClassDecl.ed_Super);
832 sg = d->d_ClassDecl.ed_SemGroup;
833 if (resolveSemGroup1(sg, flags) && resolveSemGroup2(sg, flags))
834 resolveSemGroup3(sg, flags);
835 d->d_Bytes = d->d_ClassDecl.ed_SemGroup->sg_Bytes;
836 d->d_AlignMask = d->d_ClassDecl.ed_SemGroup->sg_AlignMask;
840 * Alias access is a barrier and always returns an rvalue.
842 type = d->d_AliasDecl.ed_Type =
843 RESOLVETYPE(d->d_AliasDecl.ed_Type);
844 if (d->d_AliasDecl.ed_AssExp) {
845 d->d_AliasDecl.ed_AssExp =
846 resolveExp(d->d_ImportSemGroup, d->d_MyGroup,
847 d->d_AliasDecl.ed_AssExp,
849 flags | RESOLVE_AUTOCAST);
851 /* handled in DOT and STRIND resolver */
852 SetDupExp(NULL, d->d_AliasDecl.ed_AssExp);
855 d->d_Flags |= DF_RESOLVED;
856 type = RESOLVETYPE(d->d_TypedefDecl.ed_Type);
857 d->d_Flags &= ~DF_RESOLVED;
858 d->d_TypedefDecl.ed_Type = type;
862 * This only occurs when resolving an import's semantic group.
863 * Since we are scanning statements in that context we do not
864 * have to recurse here, resolveStmt() will do it for us.
869 * XXX global procedure, later on, make the argument a
870 * type instead of storage?
872 d->d_ProcDecl.ed_Type = RESOLVETYPE(d->d_ProcDecl.ed_Type);
875 * Deal with constructor/destructor chaining. The chaining
876 * winds up being reversed and will be corrected by the caller.
878 if (d->d_ScopeFlags & SCOPE_GLOBAL) {
879 if ((d->d_Flags & DF_ONGLIST) == 0 &&
880 (d->d_ScopeFlags & (SCOPE_CONSTRUCTOR |
881 SCOPE_DESTRUCTOR))) {
882 d->d_GNext = d->d_MyGroup->sg_GBase;
883 d->d_MyGroup->sg_GBase = d;
884 d->d_Flags |= DF_ONGLIST;
887 if ((d->d_Flags & DF_ONCLIST) == 0 &&
888 (d->d_ScopeFlags & SCOPE_CONSTRUCTOR)) {
889 d->d_CNext = d->d_MyGroup->sg_CBase;
890 d->d_MyGroup->sg_CBase = d;
891 d->d_Flags |= DF_ONCLIST;
893 if ((d->d_Flags & DF_ONDLIST) == 0 &&
894 (d->d_ScopeFlags & SCOPE_DESTRUCTOR)) {
895 d->d_DNext = d->d_MyGroup->sg_DBase;
896 d->d_MyGroup->sg_DBase = d;
897 d->d_Flags |= DF_ONDLIST;
902 * If this procedure is bound to a DLL we have to resolve
905 if (d->d_ScopeFlags & SCOPE_CLANG) {
906 d->d_ProcDecl.ed_DLLFunc =
907 FindDLLSymbol(NULL, d->d_ImportSemGroup,
911 case DOP_ARGS_STORAGE:
912 case DOP_STACK_STORAGE:
913 case DOP_GLOBAL_STORAGE:
914 case DOP_GROUP_STORAGE:
915 type = RESOLVETYPE(d->d_StorDecl.ed_Type);
916 d->d_StorDecl.ed_Type = type;
919 * Promote the lvalue storage qualifier (e.g. from a typedef)
920 * into the declaration's scope. This is what ultimately
921 * controls lvalue vs rvalue arguments to procedures and such.
923 if ((type->ty_SQFlags & SF_LVALUE) &&
924 (d->d_ScopeFlags & SCOPE_LVALUE) == 0
926 d->d_ScopeFlags |= SCOPE_LVALUE;
930 * Default assignment handling expects an rvalue.
932 if (d->d_StorDecl.ed_AssExp) {
933 d->d_StorDecl.ed_AssExp =
934 resolveExp(d->d_ImportSemGroup, d->d_MyGroup,
935 d->d_StorDecl.ed_AssExp,
937 flags | RESOLVE_AUTOCAST);
939 if (d->d_ScopeFlags & SCOPE_LVALUE) {
941 * Object is passed as a LValueStor structure. Note
942 * that d_Bytes is going to be different then the
943 * underlying type (which represents the actual
946 d->d_Bytes = sizeof(LValueStor);
947 d->d_AlignMask = LVALUE_ALIGN;
950 * Object is passed by value.
952 d->d_AlignMask = type->ty_AlignMask;
953 d->d_Bytes = type->ty_Bytes;
957 * If the declaration represents or contains an
958 * argument-lvalue or a pointer we have to add it to
959 * the SemGroup's SRBase list to properly reference or
960 * dereference the elements. XXX only do this for non-global
963 * If the declaration has LVALUE scope we must do the same
964 * because the ref is tracked.
966 if (d->d_Op != DOP_GLOBAL_STORAGE &&
967 (type->ty_Flags & TF_HASLVPTR)) {
968 d->d_SRNext = d->d_MyGroup->sg_SRBase;
969 d->d_MyGroup->sg_SRBase = d;
970 } else if (d->d_ScopeFlags & SCOPE_LVALUE) {
971 d->d_SRNext = d->d_MyGroup->sg_SRBase;
972 d->d_MyGroup->sg_SRBase = d;
976 * Deal with constructor/destructor chaining. The chaining
977 * winds up being reversed and will be corrected by the
980 if (type->ty_Flags & TF_HASCONSTRUCT) {
981 d->d_CNext = d->d_MyGroup->sg_CBase;
982 d->d_MyGroup->sg_CBase = d;
984 if (type->ty_Flags & TF_HASDESTRUCT) {
985 d->d_DNext = d->d_MyGroup->sg_DBase;
986 d->d_MyGroup->sg_DBase = d;
988 if (type->ty_Flags & (TF_HASGCONSTRUCT|TF_HASGDESTRUCT)) {
989 d->d_GNext = d->d_MyGroup->sg_GBase;
990 d->d_MyGroup->sg_GBase = d;
994 * We set content-locking defaults generically. With no
995 * SCOPE_* flags set the default will be normally-locked
996 * (GENSTAT_LOCK). SCOPE_UNLOCKED means GENSTAT_REFD
997 * (content is always at least referenced), SCOPE_HARD
998 * is for hard-locking (GENSTAT_LOCKH).
1000 * Content-locking is only applicable to an lvalue,
1001 * pointer, or reference object, but we still want to
1002 * set the proper defaults more generically.
1004 * The contents of classes and arrays are never content-
1005 * locked. Compound types (that are not procedure arguments)
1006 * are also not content-locked for now.
1008 if ((d->d_Op & DOPF_STORAGE) &&
1009 (d->d_Scope.s_Flags & SCOPE_LVALUE) == 0) {
1010 if (type->ty_Op == TY_CLASS ||
1011 type->ty_Op == TY_ARYOF ||
1012 type->ty_Op == TY_COMPOUND) {
1013 d->d_ScopeFlags |= SCOPE_UNLOCKED;
1021 d->d_Flags &= ~DF_RESOLVING;
1022 d->d_Flags |= DF_RESOLVED;
1025 * Post resolution flag resolving (to handle recursion)
1030 * Create copies of procedures as they are needed (thus
1031 * avoiding an XxY matrix effect).
1033 if ((st = d->d_ProcDecl.ed_OrigBody) == NULL) {
1034 Declaration *super = d->d_Super;
1035 while (super && super->d_ProcDecl.ed_OrigBody == NULL) {
1036 super = super->d_Super;
1039 st = super->d_ProcDecl.ed_OrigBody;
1040 if (super->d_MyGroup->sg_Stmt->st_Op == ST_Class) {
1042 * Copy-down a procedure from a
1043 * superclass. The procedure must
1044 * still be linked into its superclass
1045 * for semantic searches to work as
1046 * expected, hence the use of super->
1047 * d_MyGroup and st->st_Parent.
1049 * Note that this code is not reached
1050 * in the case of a nested procedure,
1051 * since nested procedures are copied
1054 st = DupStmt(super->d_MyGroup,
1058 * Copy-down a nested procedure.
1059 * The procedure must be linked
1060 * into the copy of the parent
1061 * prodedure, not the original
1062 * parent procedure, or it will
1063 * never be resolved.
1065 st = DupStmt(d->d_Stmt->st_MyGroup,
1070 * Internal procedure (we do not need to do
1071 * anything), there is no statement body
1077 * Procedure is being used in the primary class it
1080 st = DupStmt(d->d_MyGroup, st->st_Parent, st);
1084 * Link the procedure body to the declaration and
1085 * resolve the procedure body.
1087 dassert_stmt(st, d->d_ProcDecl.ed_ProcBody == NULL);
1089 d->d_ProcDecl.ed_ProcBody = st;
1090 st->st_ProcStmt.es_Decl = d;
1091 st->st_ProcStmt.es_Scope = d->d_Scope;
1092 resolveStmt(d->d_ImportSemGroup, st, flags);
1094 ResolveAlignment(st, flags);
1095 ResolveStorage(st, flags);
1104 * __align(%d) scope qualifier, override the type's alignment
1106 if ((d->d_Scope.s_Flags & SCOPE_ALIGN) && d->d_Scope.s_AlignOverride)
1107 d->d_AlignMask = d->d_Scope.s_AlignOverride - 1;
1111 * resolveExp() - resolve expression
1113 * Resolve an expression. We are expected to resolve all ex_Type's
1114 * for the expression tree as well as expected to track down
1115 * operators and base identifiers.
1117 * itype is a type hint. If non-NULL, the caller would like our
1118 * expression to return the specified type. There are a few special
1121 * EXF_REQ_ARRAY - when OBRACKET requests an arry optimization it
1122 * passes a post-array-indexed typehint (as if
1123 * you had done the optimization). You must ignore
1124 * itype if you are unable to do the optimization.
1126 * NOTE: Even rvalues may have refstor side-effects at run-time.
1129 resolveExp(SemGroup *isg, SemGroup *sg, Exp *exp, Type *itype, int flags)
1134 loadExpCopy(©, exp);
1138 * Must resolve cast target type hint.
1141 itype = RESOLVETYPE(itype);
1144 * note: certain cases below call other resolver functions and assume
1145 * that ex* variables are unchanged.
1147 dassert((exFlags & EXF_DUPEXP) || (exFlags & EXF_RESOLVED) == 0);
1152 * An assignment. Note that we optimize void returns
1153 * (such as when an assignment is a statement like 'a = 4;'
1154 * ... the result of the assignment is cast to void.
1156 * NOTE: Left-hand-side must be an LVALUE, return type
1157 * inherits this feature unless the parent turns off
1158 * the bit so the TOK_ASS run-time must deal with that.
1160 exLhs = resolveExp(isg, sg, exLhs, NULL,
1161 flags & ~RESOLVE_AUTOCAST);
1162 dassert_exp(exLhs, exLhs->ex_Type->ty_SQFlags & SF_LVALUE);
1164 exRhs = resolveExp(isg, sg, exRhs,
1165 DEL_LVALUE(exLhs->ex_Type),
1166 flags | RESOLVE_AUTOCAST);
1167 if (exLhs->ex_Type->ty_SQFlags & SF_CONST) {
1168 ExpFatalError(exp, TOK_ERR_READONLY);
1171 /* AssExp handles this optimization */
1172 if (itype == &VoidType) {
1174 exFlags |= EXF_RET_VOID;
1176 exType = exLhs->ex_Type;
1181 * Check @ref assignment compatibility.
1183 if (exLhs->ex_Type->ty_Op == TY_REFTO) {
1184 switch(MatchType(exLhs->ex_Type, exRhs->ex_Type)) {
1185 case SG_COMPAT_FULL:
1186 printf("assign %s compatibility FULL\n",
1189 case SG_COMPAT_PART:
1190 printf("assign %s compatibility PART\n",
1193 case SG_COMPAT_SUBCLASS:
1194 printf("assign %s compatibility SUBCL\n",
1197 case SG_COMPAT_FAIL:
1198 printf("assign %s compatibility FAIL\n",
1207 * NOTE: BoolType global implies an rvalue.
1210 exLhs = resolveExp(isg, sg, exLhs, &BoolType,
1211 flags | RESOLVE_AUTOCAST);
1214 * If left-side can terminate the operation, mark the
1215 * expression as PROBCONST for the interpreter and code
1216 * generator (allowing the rhs to not be a constant).
1218 if (exLhs->ex_Flags & (EXF_CONST | EXF_PROBCONST)) {
1221 exLhs = resolveConstExpBool(isg, sg, exLhs, flags, &ts);
1222 if (ts.ts_Bool == 0)
1223 exFlags |= EXF_PROBCONST;
1227 * Resolve rhs, and we can also flag PROBCONST if both sides
1230 exRhs = resolveExp(isg, sg, exRhs, &BoolType,
1231 flags | RESOLVE_AUTOCAST);
1232 if ((exLhs->ex_Flags & (EXF_CONST | EXF_PROBCONST)) &&
1233 (exRhs->ex_Flags & (EXF_CONST | EXF_PROBCONST))) {
1234 exFlags |= EXF_PROBCONST;
1240 * NOTE: BoolType global implies an rvalue.
1243 exLhs = resolveExp(isg, sg, exLhs, &BoolType,
1244 flags | RESOLVE_AUTOCAST);
1247 * If left-side can terminate the operation, mark the
1248 * expression as PROBCONST for the interpreter and code
1249 * generator (allowing the rhs to not be a constant).
1251 if (exLhs->ex_Flags & (EXF_CONST | EXF_PROBCONST)) {
1254 exLhs = resolveConstExpBool(isg, sg, exLhs, flags, &ts);
1256 exFlags |= EXF_PROBCONST;
1260 * Resolve rhs, and we can also flag PROBCONST if both sides
1263 exRhs = resolveExp(isg, sg, exRhs, &BoolType,
1264 flags | RESOLVE_AUTOCAST);
1265 if ((exLhs->ex_Flags & (EXF_CONST | EXF_PROBCONST)) &&
1266 (exRhs->ex_Flags & (EXF_CONST | EXF_PROBCONST))) {
1267 exFlags |= EXF_PROBCONST;
1273 * This synthesized token occurs when we are able to collapse
1274 * a structural indirection or dotted element into a
1275 * declaration. For example, 'module.routine'.
1277 /* XXX couldconst? */
1282 * Structual field access. The left hand side may be an object
1283 * (class or compound), a class type, or a compound type.
1285 * A dotted access requires an lvalue on the left hand side
1286 * if the left hand side represents storage.
1288 * The result will be an lvalue if the right hand side
1289 * represents storage. We only loop if the right hand side
1290 * is an alias replacement.
1301 int procedureOnly = 0;
1302 int eno = TOK_ERR_ID_NOT_FOUND;
1305 * NOTE: Hint must 'always happen' since we may be
1306 * modifying an expression that will later be
1309 * NOTE: Lhs is always an lvalue for TOK_DOT, but
1310 * does not have to be for TOK_STRIND.
1312 exLhs->ex_Flags |= EXF_REQ_TYPE;
1313 if (exToken == TOK_DOT) {
1315 exFlags & (EXF_REQ_ADDROF | EXF_ADDRUSED);
1317 exLhs = resolveExp(isg, sg, exLhs, NULL,
1318 flags & ~RESOLVE_AUTOCAST);
1321 * The RHS may have been turned into a TOK_SEMGRP_ID
1322 * in a previous duplicate. The change is considered
1325 if (exRhs->ex_Token != TOK_SEMGRP_ID) {
1327 exRhs->ex_Token == TOK_STRUCT_ID);
1328 exRhs = resolveExp(isg, sg, exRhs, NULL,
1329 flags & ~RESOLVE_AUTOCAST);
1332 type = exLhs->ex_Type;
1335 * Calculate scope and SemGroup to search. Note
1336 * that it is legal to do a structural '.' selection
1337 * on a pointer, but it works differently then
1338 * indirecting through a pointer via '->'. In the
1339 * case of '.' on a pointer, we first search the
1340 * system Pointer class.
1342 if (exLhs->ex_Flags & EXF_RET_TYPE) {
1347 * Figure out the base type used to look-up the
1348 * identifier. An identifier that resolves into a
1349 * procedure winds up only being a hint for a
1352 if (exToken == TOK_STRIND) {
1353 switch(type->ty_Op) {
1355 type = type->ty_CPtrType.et_Type;
1358 type = type->ty_PtrType.et_Type;
1361 type = type->ty_RefType.et_Type;
1365 dassert_exp(exp, 0);
1371 switch(type->ty_Op) {
1373 sg2 = type->ty_ClassType.et_SemGroup;
1376 sg2 = type->ty_CompType.et_SemGroup;
1379 sg2 = type->ty_ArgsType.et_SemGroup;
1382 sg2 = type->ty_VarType.et_SemGroup;
1385 sg2 = type->ty_ImportType.et_SemGroup;
1389 dassert_exp(exp, PointerType.ty_Op == TY_CLASS);
1390 sg2 = PointerType.ty_ClassType.et_SemGroup;
1393 dassert_exp(exp, PointerType.ty_Op == TY_CLASS);
1394 sg2 = PointerType.ty_ClassType.et_SemGroup;
1398 dassert_exp(exp, PointerType.ty_Op == TY_CLASS);
1399 sg2 = PointerType.ty_ClassType.et_SemGroup;
1403 * Possibly a pointer, aka ptr.NULL
1407 visibility = exLhs->ex_Visibility;
1410 * Locate the identifier normally, via its type.
1411 * ty_TypeVisbility is the initial visibility (scope)
1412 * that the semantic search should use in locating
1416 string_t ary[2] = { id, NULL };
1419 if (exLhs->ex_Token == TOK_ID ||
1420 exLhs->ex_Token == TOK_DECL) {
1421 if (exLhs->ex_Decl->d_Search) {
1422 level = exLhs->ex_Decl->
1425 level = sg2->sg_Level;
1431 if (exLhs->ex_Flags & EXF_SUPER) {
1433 fprintf(stderr, "Can't super with reference type\n");
1434 dassert_exp(exp, 0);
1437 fprintf(stderr, "No superclass available\n");
1438 dassert_exp(exp, 0);
1443 level = sg2->sg_Level; /* may be -1 */
1445 visibility &= type->ty_Visibility;
1446 d = FindDeclPath(&exp->ex_LexRef, NULL,
1449 &visibility, level, &eno);
1451 * XXX more hack. If the super is visible
1452 * and a procedure we just found our own
1453 * refinement, not the superclass method.
1454 * This is because there is no 'superclass
1455 * method' per say, refinements *REPLACE*
1456 * superclass declarations and inherit the
1457 * superclass's level. However, we still
1458 * want to be able to chain method calls so
1459 * what we do instead is go through and find
1460 * the procedure that we smacked when we did
1461 * the refinement. This procedure has
1462 * already been conveniently brought into
1463 * the subclass context as an 'invisible'
1464 * entity at the same d_Level.
1466 if ((exLhs->ex_Flags & EXF_SUPER) &&
1468 d->d_Op == DOP_PROC &&
1469 (d->d_ScopeFlags & SCOPE_ALL_VISIBLE)
1471 string_t id2 = d->d_Id;
1472 SemGroup *olevel = d->d_Level;
1474 dassert_exp(exp, isRefTo == 0);
1476 while ((d = RUNE_NEXT(d, d_Node)) != NULL) {
1477 if (d->d_Id == id2 &&
1478 d->d_Level == olevel &&
1479 d->d_Op == DOP_PROC) {
1488 if (d && procedureOnly && d->d_Op != DOP_PROC) {
1490 "PTR.ELEMENT may be used for special "
1491 "pointer method calls, but not to "
1492 "access storage elements. "
1493 "Use PTR->ELEMENT instead\n");
1494 dassert_exp(exp, 0);
1498 * If referencing actual storage the storage must be
1501 if (d && globalOnly && (d->d_Op & DOPF_STORAGE) &&
1502 (d->d_ScopeFlags & SCOPE_GLOBAL) == 0
1505 "%s is not global. Only globals "
1506 "can be accessed through a type\n",
1508 dassert_exp(exp, 0);
1513 * Identifier found. Note that if we are
1514 * going through a reference type the
1515 * declaration is not the actual one we
1516 * use at run time. It's just a template.
1518 resolveDecl(d, flags);
1520 exVisibility = visibility;
1523 * XXX this is in wrong place
1525 * ADDROF content-locked storage is not
1526 * allowed, except for the SCOPE_LVALUE case
1527 * if the underlying type is acceptable.
1529 * If we are running through an LValueStor
1530 * UNLOCKED applies to it and not its contents.
1531 * Check to see if the contents are acceptable.
1533 if ((exFlags & EXF_REQ_ADDROF) &&
1534 (d->d_Op & DOPF_STORAGE) &&
1535 (d->d_Scope.s_Flags & SCOPE_UNLOCKED) == 0) {
1536 type = d->d_StorDecl.ed_Type;
1537 if ((type->ty_Flags & TF_HASLVPTR) &&
1538 type->ty_Op != TY_CLASS &&
1539 type->ty_Op != TY_ARYOF) {
1541 TOK_ERR_ILLEGAL_ADDRLOCKED);
1550 exType = d->d_ProcDecl.ed_Type;
1551 if (d->d_ProcDecl.ed_Type->ty_SQFlags & SF_METHOD) {
1553 * Method call, do not
1554 * collapse the expression into
1555 * a direct declaration because
1556 * the object is needed later.
1558 if (exLhs->ex_Flags & EXF_RET_TYPE)
1559 ExpPrintError(exLhs, TOK_ERR_METHOD_REQUIRES_OBJ);
1560 dassert((exLhs->ex_Flags & EXF_RET_TYPE) == 0);
1561 } else if (isRefTo) {
1563 * Call via reference. The
1564 * lhs is required to evaluate
1565 * the actual method call at
1570 * Global method call or normal
1571 * call. For the global method
1572 * case the lhs is not needed
1573 * because the parser entered
1574 * the first argument as a
1577 * Degenerate into a TOK_DECL.
1578 * We depend on this later.
1580 exFlags &= ~EXF_BINARY;
1587 exType = DEL_LVALUE(d->d_AliasDecl.ed_Type);
1588 dassert_decl(d, d->d_AliasDecl.ed_AssExp != NULL);
1590 * NOTE: exLhs must be NULL if exp is
1591 * unresolved. exp tree duplications
1592 * do not duplicate the alias's exLHS
1593 * even though UNARY is set.
1595 dassert_exp(exp, exRhs->ex_Lhs == NULL);
1596 exRhs->ex_Flags |= EXF_ALIAS | EXF_UNARY;
1597 exRhs->ex_Lhs = DupExp(sg2,
1598 d->d_AliasDecl.ed_AssExp);
1599 exRhs->ex_Lhs = resolveExp(isg, sg2,
1602 flags | RESOLVE_AUTOCAST);
1604 case DOP_ARGS_STORAGE:
1605 case DOP_STACK_STORAGE:
1606 case DOP_GLOBAL_STORAGE:
1607 case DOP_GROUP_STORAGE:
1609 * Set type. The Rhs is a STRUCT_ID
1610 * and does not require a type to be
1613 * Return type is always an LVALUE,
1614 * parent may adjust.
1616 exType = ADD_LVALUE(d->d_StorDecl.ed_Type);
1619 * Pull up global constants
1621 if (exToken == TOK_DOT &&
1622 d->d_Op == DOP_GLOBAL_STORAGE &&
1623 (d->d_ScopeFlags & SCOPE_CONSTANT) &&
1624 (exLhs->ex_Flags & EXF_RET_TYPE)) {
1625 exFlags |= EXF_PROBCONST;
1630 * XXX make sure this is only used
1631 * in the lhs of a structural
1634 * XXX what if we went through a
1635 * TY_RETO type? This type will
1638 * collapse the exp node.
1640 exType = d->d_TypedefDecl.ed_Type;
1642 exFlags &= ~EXF_BINARY;
1646 * Do not collapse an import, we
1647 * require more resolution. e.g.
1648 * import.<blah> will be collapsed,
1649 * but 'import' cannot be.
1651 if (exFlags & EXF_REQ_TYPE) {
1654 &d->d_ImportDecl.ed_SemGroup->sg_ClassList,
1655 d->d_ImportDecl.ed_SemGroup,
1657 exFlags |= EXF_RET_TYPE;
1663 * Do not collapse a class, we require
1664 * more resolution. e.g. class.<blah>
1665 * will be collapsed, but 'class'
1668 if (exFlags & EXF_REQ_TYPE) {
1671 &d->d_ClassDecl.ed_SemGroup->sg_ClassList,
1672 d->d_ClassDecl.ed_Super,
1673 d->d_ClassDecl.ed_SemGroup,
1675 exFlags |= EXF_RET_TYPE;
1680 dassert_exp(exp, 0);
1683 if (d->d_Op == DOP_PROC) {
1684 if (d->d_ScopeFlags & SCOPE_PURE)
1686 } else if (exType->ty_SQFlags & SF_CONST) {
1690 } else if ((s = StrTableSpecial(id)) &
1691 SPECIALF_SEMGROUP) {
1693 * Identifier not found, check for a special
1696 exRhs->ex_Token = TOK_SEMGRP_ID;
1697 exRhs->ex_Int32 = s;
1702 dassert(type->ty_Op == TY_PTRTO ||
1703 type->ty_Op == TY_REFTO ||
1704 type->ty_Op == TY_CPTRTO);
1705 /* NULL is not an lvalue */
1706 exType = DEL_LVALUE(type);
1707 exFlags |= EXF_NULL;
1710 dassert(type->ty_Op != TY_PTRTO &&
1711 type->ty_Op != TY_REFTO &&
1712 type->ty_Op != TY_CPTRTO);
1713 exType = &Int32Type;
1717 * typeof(self.__data[]) vs
1718 * (cast)self.__data[]
1720 dassert(type->ty_Op != TY_PTRTO &&
1721 type->ty_Op != TY_REFTO &&
1722 type->ty_Op != TY_CPTRTO);
1723 dassert(exFlags & EXF_REQ_ARRAY);
1724 exFlags |= EXF_RET_ARRAY;
1725 if (exFlags & EXF_REQ_TYPE) {
1726 exFlags |= EXF_RET_TYPE;
1727 exType = &DynamicLValueType;
1732 * dynamic data must be cast
1734 dassert_exp(exp, 0);
1735 exType = &DynamicLValueType;
1738 case SPECIAL_VAR_COUNT:
1739 dassert(type->ty_Op != TY_PTRTO &&
1740 type->ty_Op != TY_REFTO &&
1741 type->ty_Op != TY_CPTRTO);
1742 exType = &Int32Type;
1744 case SPECIAL_VAR_DATA:
1746 * typeof(self.__vardata[]) vs
1747 * (cast)self.__vardata[]
1749 dassert(type->ty_Op != TY_PTRTO &&
1750 type->ty_Op != TY_REFTO &&
1751 type->ty_Op != TY_CPTRTO);
1752 dassert(exFlags & EXF_REQ_ARRAY);
1753 exFlags |= EXF_RET_ARRAY;
1754 if (exFlags & EXF_REQ_TYPE) {
1755 exFlags |= EXF_RET_TYPE;
1756 exType = &DynamicLValueType;
1761 * dynamic data must be cast
1763 dassert_exp(exp, 0);
1764 exType = &DynamicLValueType;
1767 case SPECIAL_TYPEID:
1768 exType = &Int32Type;
1770 case SPECIAL_TYPESTR:
1774 dassert_exp(exRhs, 0);
1779 * This is nasty, I admit. If we have a
1780 * pointer or reference type try again.
1783 if (type->ty_Op == TY_PTRTO) {
1784 type = type->ty_PtrType.et_Type;
1788 if (type->ty_Op == TY_REFTO) {
1789 type = type->ty_RefType.et_Type;
1793 if (type->ty_Op == TY_CPTRTO) {
1794 type = type->ty_CPtrType.et_Type;
1798 ExpFatalError(exRhs, eno);
1802 dassert_exp(exp, exType != NULL);
1806 * NOTE: unresolved identifiers should not have alias
1807 * expression sub-tree duplications attached to them.
1810 dassert_exp(exp, exLhs == NULL);
1814 * NOTE: LVALUE/RVALUE for elements and return type depends
1815 * on the operator. Operator functions normally
1816 * self-optimize the cases at run-time.
1819 saveExpCopy(©, exp);
1820 exp = resolveExpOper(isg, sg, exp, itype,
1821 flags & ~RESOLVE_AUTOCAST);
1822 loadExpCopy(©, exp);
1826 * Indirect through an expression.
1828 * Return type is typically an LVALUE (if representing
1829 * storage). Exp parent might turn it off so run-time
1830 * must test. Lhs may or may not be.
1835 exLhs = resolveExp(isg, sg, exLhs, NULL,
1836 flags & ~RESOLVE_AUTOCAST);
1837 type = exLhs->ex_Type;
1839 switch(type->ty_Op) {
1841 if ((exFlags & EXF_INDREF) == 0) {
1842 fprintf(stderr, "You cannot use '*' on a reference type\n");
1843 dassert_exp(exLhs, 0);
1845 exType = ADD_LVALUE(type->ty_RefType.et_Type);
1848 exType = ADD_LVALUE(type->ty_PtrType.et_Type);
1851 exType = ADD_LVALUE(type->ty_CPtrType.et_Type);
1854 dassert_exp(exLhs, 0);
1861 * Take the address of an (LVALUE) expression. Returns an
1862 * RVALUE. Allow for a short-cut optimization which replaces
1863 * the TOK_ADDR sequence with its argument in the &ary[n]
1870 * Hint must 'always happen' since we may be
1871 * modifying an expression that will later be
1874 * It is sufficient to test EXF_ADDRUSED to determine
1875 * if SRSGET/SRSPUT is needed for the procedure.
1877 exLhs->ex_Flags |= EXF_REQ_ADDROF | EXF_ADDRUSED;
1878 exLhs = resolveExp(isg, sg, exLhs, NULL,
1879 flags & ~RESOLVE_AUTOCAST);
1880 if (exLhs->ex_Flags & EXF_RET_ADDROF) {
1882 loadExpCopy(©, exp);
1884 type = exLhs->ex_Type;
1886 type->ty_SQFlags & SF_LVALUE);
1887 exType = RESOLVETYPE(TypeToPtrType(type));
1888 /* DEL_LVALUE() not needed here */
1894 * Array index, takes an RVALUE, returns an LVALUE.
1896 * Note: we have to convert the special __data[exp] case.
1898 * Note: ex_Flags hints must 'always happen' since we may be
1899 * modifying an expression that will later be Dup'd.
1901 exRhs = resolveExp(isg, sg, exRhs, NULL,
1902 flags & ~RESOLVE_AUTOCAST);
1903 exLhs->ex_Flags |= EXF_REQ_ARRAY | (exFlags & EXF_REQ_TYPE);
1904 exLhs->ex_Flags |= EXF_ADDRUSED;
1905 exLhs->ex_AuxExp = exRhs;
1906 exLhs = resolveExp(isg, sg, exLhs, itype,
1907 flags & ~RESOLVE_AUTOCAST);
1909 if (MatchType(&IntegralType, exRhs->ex_Type) <= SG_COMPAT_PART) {
1910 ExpPrintError(exRhs, TOK_ERR_EXPECTED_INTEGRAL_TYPE);
1911 dassert_exp(exp, 0);
1914 if (exLhs->ex_Flags & EXF_RET_ARRAY) {
1916 * __data and __vardata specials
1918 exp->ex_Token = TOK_ERR_EXP_REMOVED;
1920 } else if (exFlags & EXF_REQ_ADDROF) {
1922 * &ary[i] optimization - allows us to create
1923 * a bounded pointer (returns an RVALUE).
1927 exFlags |= EXF_RET_ADDROF;
1929 dassert((exLhs->ex_Flags & EXF_RET_TYPE) == 0);
1931 exLhs->ex_AuxExp = NULL;
1932 type = exLhs->ex_Type;
1933 switch(type->ty_Op) {
1935 type = type->ty_AryType.et_Type;
1938 type = type->ty_CPtrType.et_Type;
1941 type = type->ty_PtrType.et_Type;
1944 /* Cannot take address of a reference type */
1945 dassert_exp(exp, 0);
1948 exType = RESOLVETYPE(TypeToPtrType(type));
1949 /* returns an RVALUE */
1952 * Unoptimized array lookup, returns an lvalue
1956 dassert((exLhs->ex_Flags & EXF_RET_TYPE) == 0);
1958 exLhs->ex_AuxExp = NULL;
1959 type = exLhs->ex_Type;
1960 switch(type->ty_Op) {
1962 type = type->ty_AryType.et_Type;
1965 type = type->ty_CPtrType.et_Type;
1968 type = type->ty_PtrType.et_Type;
1972 "Cannot index a reference type\n");
1973 dassert_exp(exp, 0);
1976 exType = ADD_LVALUE(type);
1977 /* returns an LVALUE */
1981 dassert_exp(exp, 0); /* XXX */
1986 * XXX we should return a bounded pointer here.
1989 exId = StrTableEscapeQuotedString(exId, strlen(exId), 1);
1990 ReplaceStrTable(&exp->ex_Id, exId);
1994 exFlags |= EXF_CONST;
1995 exType = &UInt8Type; /* XXX make wide? */
1996 exId = StrTableEscapeQuotedString(exId, strlen(exId), 0);
1997 dassert(StrTableLen(exId) == 1);
1998 ReplaceStrTable(&exp->ex_Id, exId);
2006 strtol(exp->ex_Id, &ptr, 0);
2019 size = (size & ~0xFFF) | 1;
2023 size = (size & ~0xFFF) | 2;
2027 size = (size & ~0xFFF) | 4;
2031 size = (size & ~0xFFF) | 8;
2035 size = (size & ~0xFFF) | 16;
2039 size = (size & ~0xFFF) |
2044 TOK_ERR_ILLEGAL_SUFFIX);
2055 exType = &Int16Type;
2058 exType = &Int32Type;
2061 exType = &Int64Type;
2064 exType = &Int128Type;
2067 exType = &UInt8Type;
2070 exType = &UInt16Type;
2073 exType = &UInt32Type;
2076 exType = &UInt64Type;
2079 exType = &UInt128Type;
2082 exType = &Int32Type;
2086 exFlags |= EXF_CONST;
2093 exType = &Float64Type;
2095 strtod(exp->ex_Id, &ptr);
2100 exType = &Float32Type;
2104 exType = &Float64Type;
2108 exType = &Float128Type;
2114 exFlags |= EXF_CONST;
2121 * The self identifier represents the current procedure's
2122 * arguments. A varargs procedure will actually be called
2123 * with an extended version of this type, but for resolution
2124 * purposes we can use this time.
2126 * This is an LVALUE to support things like self.new() XXX.
2128 exType = ADD_LVALUE(resolveArgsType(sg, flags));
2132 * The '$' identifier represents the current procedure's
2135 if (sg->sg_Flags & SGF_DIDRESULT)
2136 ExpFatalError(exp, TOK_ERR_RESULT_SEQUENCING);
2137 exType = ADD_LVALUE(resolveReturnType(sg, flags));
2142 * Lookup the identifier. The returned declaration could
2143 * represent a class, typedef, module, or storage, but for
2144 * this case we only allow storage or a constant. Since
2145 * we are starting from our own semantic group, visibility
2146 * is initially ALL (private, library, and public).
2148 * The identifier might represent something at a higher scoping
2149 * layer. For example, a nested procedure accessing a variable
2150 * in the parent procedure or a method procedure in a class
2151 * accessing an element of the object.
2153 * It is also possible for the current execution scoping layer
2154 * (sg) to have a secondary contextual layer from which global
2155 * constants can be accessed. This is typically set when
2156 * resolving procedure arguments for procedures called through
2157 * objects or types. Only type globals can be accesed via
2160 * This returns an LVALUE if the id represents storage.
2164 int eno = TOK_ERR_ID_NOT_FOUND;
2169 * Special case 'super'. XXX TY_REFTO
2171 * Make an in-place change to the expression
2172 * structure. 'super' is actually 'this' with the
2173 * EXF_SUPER flag set.
2175 if (exId == String_Super) {
2177 ReplaceStrTable(&exp->ex_Id, exId);
2178 exFlags |= EXF_SUPER;
2180 ary[0] = exp->ex_Id;
2183 exDecl = FindDeclPath(&exp->ex_LexRef, isg, sg,
2185 FDC_NULL, &exVisibility,
2187 if (exDecl == NULL) {
2188 exDecl = FindDeclPathAltContext(
2189 &exp->ex_LexRef, isg, sg,
2191 FDC_NULL, &exVisibility,
2194 if (exDecl == NULL) {
2195 ExpPrintError(exp, eno);
2196 dassert_exp(exp, 0);
2200 * The EXF flag is set by TOK_ADDR, possibly
2201 * propagated down via TOK_DOT. Use this to flag
2202 * that the stack context might be used outside of
2203 * its normal life. LValue scoped declarations do
2204 * not count because they have their own RefStor.
2206 * (This code is primarily responsible for causing
2207 * SRSGET and SRSPUT instructions to be emitted).
2209 if ((exFlags & EXF_ADDRUSED) &&
2210 (exDecl->d_Scope.s_Flags & SCOPE_LVALUE) == 0) {
2211 exDecl->d_MyGroup->sg_Flags |= SGF_ADDRUSED;
2216 * Try to delay resolving the procedure declaration
2217 * (which will resolve the procedure body). We cannot
2218 * delay the resolution if resolving a constant
2219 * that the resolver needs immediately.
2221 if (flags & RESOLVE_CONSTEXP) {
2222 resolveDecl(exDecl, flags);
2228 * Taking the address of content-locked storage is illegal.
2230 * If we are running through an LValueStor
2231 * UNLOCKED applies to it and not its contents.
2232 * Check to see if the contents are acceptable.
2234 if ((exFlags & EXF_REQ_ADDROF) &&
2235 (exDecl->d_Scope.s_Flags & SCOPE_UNLOCKED) == 0) {
2236 Type *type = exDecl->d_StorDecl.ed_Type;
2237 if ((type->ty_Flags & TF_HASLVPTR) &&
2238 type->ty_Op != TY_CLASS &&
2239 type->ty_Op != TY_ARYOF) {
2241 TOK_ERR_ILLEGAL_ADDRLOCKED);
2242 dassert_exp(exp, 0);
2246 switch(exDecl->d_Op) {
2247 case DOP_ARGS_STORAGE:
2248 if (sg->sg_Flags & SGF_DIDRESULT)
2249 ExpFatalError(exp, TOK_ERR_RESULT_SEQUENCING);
2251 case DOP_STACK_STORAGE:
2252 case DOP_GLOBAL_STORAGE:
2253 case DOP_GROUP_STORAGE:
2255 * Storage identifiers are lvalues.
2257 * Try to delay this step, giving the language more
2258 * flexibility in avoiding resolver loops from
2259 * interdependencies that can cause it to fail.
2261 * We can't delay this step when resolving an
2262 * expression that the resolver needs an actual
2263 * constant result for.
2265 exType = ADD_LVALUE(exDecl->d_StorDecl.ed_Type);
2266 if (exDecl->d_Op == DOP_STACK_STORAGE &&
2267 (exFlags & EXF_ADDRUSED)) {
2268 exDecl->d_Flags |= DF_ADDRUSED;
2270 if (exType->ty_SQFlags & SF_CONST)
2273 if (flags & RESOLVE_CONSTEXP) {
2274 Exp **asexpp = &exDecl->d_StorDecl.ed_AssExp;
2276 *asexpp = DupExp(sg, *asexpp);
2277 *asexpp = resolveExp(isg, sg, *asexpp,
2279 flags | RESOLVE_AUTOCAST);
2280 *asexpp = SetDupExp(sg, *asexpp);
2287 * Aliases are rvalues (even if they could be lvalues).
2289 exType = DEL_LVALUE(exDecl->d_AliasDecl.ed_Type);
2290 exFlags |= EXF_ALIAS | EXF_UNARY;
2293 * NOTE: exLhs must be NULL if exp is unresolved.
2294 * exp tree duplications do not duplicate
2295 * the alias's exLHS even though UNARY is set.
2297 dassert_exp(exp, exLhs == NULL);
2298 exLhs = DupExp(sg, exDecl->d_AliasDecl.ed_AssExp);
2299 exLhs = resolveExp(isg, sg, exLhs, exType,
2300 flags | RESOLVE_AUTOCAST);
2303 * Inherit EXF_NULL (NULL pointer special) through
2304 * the alias, otherwise it will not be assignable
2305 * to arbitrary pointers.
2307 exFlags |= exLhs->ex_Flags & EXF_NULL;
2312 * A procedural identifier.
2314 * Note: procedural pointers cannot be changed so
2315 * they are not lvalues.
2317 dassert_exp(exp, (exFlags & EXF_REQ_PROC));
2318 exType = exDecl->d_ProcDecl.ed_Type;
2319 if (exDecl->d_ScopeFlags & SCOPE_PURE)
2323 if (exFlags & EXF_REQ_TYPE) {
2324 exType = exDecl->d_TypedefDecl.ed_Type;
2325 exFlags |= EXF_RET_TYPE;
2328 dassert_exp(exp, 0);
2331 if (exFlags & EXF_REQ_TYPE) {
2334 &exDecl->d_ClassDecl.ed_SemGroup->sg_ClassList,
2335 exDecl->d_ClassDecl.ed_Super,
2336 exDecl->d_ClassDecl.ed_SemGroup,
2338 exFlags |= EXF_RET_TYPE;
2341 dassert_exp(exp, 0);
2344 if (exFlags & EXF_REQ_TYPE) {
2347 &exDecl->d_ImportDecl.ed_SemGroup->sg_ClassList,
2348 exDecl->d_ImportDecl.ed_SemGroup,
2350 exFlags |= EXF_RET_TYPE;
2353 dassert_exp(exp, 0);
2356 dassert_exp(exp, 0);
2361 * NOTE: BoolType global implies an rvalue.
2364 exLhs = resolveExp(isg, sg, exLhs, &BoolType,
2365 flags | RESOLVE_AUTOCAST);
2368 if (exFlags & EXF_REQ_TYPE) {
2369 exType = RESOLVETYPE(exType);
2370 exFlags |= EXF_RET_TYPE;
2372 dassert_exp(exp, 0);
2377 * User cast (or maybe the parser inserted it). Try to
2378 * resolve the expression with the requested type hint
2379 * but tell resolveExp() not to force the cast.
2381 * Then check the result. If resolveExp() was not able to
2382 * optimize the requested cast then resolve the cast.
2384 * If the types are compatible we still keep the TOK_CAST
2385 * node in place for the moment. XXX we really need to
2386 * formalized how ex_Type is set Similar vs Exact.
2388 * NOTE: Cast results are always an RVALUE. XXX validate here.
2391 if ((exFlags & EXF_PARSE_TYPE) == 0) {
2392 exRhs->ex_Flags |= EXF_REQ_TYPE;
2393 exRhs = resolveExp(isg, sg, exRhs, NULL,
2394 flags & ~RESOLVE_AUTOCAST);
2395 exType = exRhs->ex_Type;
2397 exLhs = resolveExp(isg, sg, exLhs, exType,
2398 flags & ~RESOLVE_AUTOCAST);
2399 if (SimilarType(exType, exLhs->ex_Type) == 0) {
2400 saveExpCopy(©, exp);
2401 exp = resolveExpCast(isg, sg, exLhs, exType, flags);
2402 loadExpCopy(©, exp);
2405 /* propagate NULL flag to allow cast to any pointer type */
2406 if (exLhs->ex_Flags & EXF_NULL)
2407 printf("LHS NULL\n");
2408 exp->ex_Flags |= exLhs->ex_Flags & EXF_NULL;
2413 * Calls require the RHS to be a compound expression
2414 * representing the procedure arguments.
2416 * XXX deal with pointer-to-function verses function
2417 * XXX the lhs must at the moment resolve to the procedure
2420 * In regards to procedure pointers, the declaration
2421 * will require a pointer to the procedure's statement
2422 * body. XXX this pointer can be the physical storage
2423 * associated with the lhs data but thus requires the
2424 * type to be a pointer. We do not support the 'C'
2425 * (*ptr_to_func)(...) form. You have to use ptr_to_func(...).
2429 Type *atype; /* type for alt context */
2430 SemGroup *save_asg; /* save old alt context */
2432 dassert_exp(exRhs, exRhs->ex_Token == TOK_COMPOUND);
2435 * Note: ex_Flags hints must 'always happen' since
2436 * we may be modifying an expression that will later
2439 exLhs->ex_Flags |= EXF_REQ_PROC;
2440 exLhs->ex_Flags |= EXF_ADDRUSED;
2441 exLhs = resolveExp(isg, sg, exLhs, NULL,
2442 flags & ~RESOLVE_AUTOCAST);
2443 ltype = exLhs->ex_Type;
2445 if (ltype->ty_Op == TY_PTRTO)
2446 ltype = type->ty_PtrType.et_Type; /* XXX */
2449 dassert_exp(exLhs, exLhs->ex_Token == TOK_DECL ||
2450 exLhs->ex_Token == TOK_ID);
2452 dassert_exp(exLhs, ltype != NULL &&
2453 ltype->ty_Op == TY_PROC);
2454 dassert_exp(exLhs, exLhs->ex_Decl != NULL);
2455 dassert_exp(exRhs, exRhs->ex_Token == TOK_COMPOUND);
2458 * If the lhs type indicates a method procedure, then
2459 * it's lhs is the object we wish to pass as the
2460 * first argument to the method. We move the lhs lhs
2461 * exp. For a STRIND TY_PTRTO method call we
2462 * indirect the element and convert it to a TOK_DOT
2463 * lvalue argument of the underlying object.
2465 * A method call via a reference object is a very
2468 * Since the method called through an object winds up
2469 * being a method taylored for that object, and we
2470 * are calling through a reference to an object,
2471 * the actual method will be looked up at run time
2472 * and will match the object. Thus we can safely
2473 * indirect through the reference object for this
2474 * one case. Since (*ref_obj) is not normally
2475 * allowed this will be special-cased at
2478 * Note that this occurs before we evaluate the
2479 * compound expression on the right hand side. Also
2480 * note that since the resolver can be called multiple
2481 * times on a shared expression, we have to be
2482 * careful to shift the arguments around only once.
2484 if ((ltype->ty_SQFlags & SF_METHOD) &&
2485 (exRhs->ex_Flags & EXF_CALL_CONV) == 0
2489 exRhs->ex_Flags |= EXF_CALL_CONV;
2491 switch(exLhs->ex_Token) {
2492 case TOK_STRIND: /* indirect */
2494 * NOTE: Do not set EXF_RESOLVED, we
2495 * need to call the resolver to
2496 * properly propagate ADDRUSED.
2498 obj = exLhs->ex_Lhs;
2499 if (methodProcThisIsPointer(ltype)) {
2501 } else if (obj->ex_Type->ty_Op ==
2503 Exp *nexp = AllocExp(NULL);
2506 nexp->ex_Token = TOK_PTRIND;
2507 nexp->ex_Type = ADD_LVALUE(obj->ex_Type->ty_PtrType.et_Type);
2508 nexp->ex_Flags |= EXF_UNARY;
2509 LexDupRef(&obj->ex_LexRef,
2511 exLhs->ex_Token = TOK_DOT;
2513 } else if (obj->ex_Type->ty_Op ==
2515 Exp *nexp = AllocExp(NULL);
2518 nexp->ex_Token = TOK_PTRIND;
2519 nexp->ex_Type = ADD_LVALUE(obj->ex_Type->ty_CPtrType.et_Type);
2520 nexp->ex_Flags |= EXF_UNARY;
2521 LexDupRef(&obj->ex_LexRef,
2523 exLhs->ex_Token = TOK_DOT;
2525 } else if (obj->ex_Type->ty_Op ==
2527 Exp *nexp = AllocExp(NULL);
2530 nexp->ex_Token = TOK_PTRIND;
2531 nexp->ex_Type = ADD_LVALUE(obj->ex_Type->ty_RefType.et_Type);
2532 nexp->ex_Flags |= EXF_UNARY |
2534 LexDupRef(&obj->ex_LexRef,
2538 dassert_exp(obj, 0);
2543 * Pass directly as an lvalue. If this
2544 * is a pointer or reference only the
2545 * builtin methods for the Pointer
2546 * class are possible. These methods
2547 * require a content-locked pointer.
2549 obj = exLhs->ex_Lhs;
2550 if (obj->ex_Type->ty_Op != TY_PTRTO &&
2551 obj->ex_Type->ty_Op != TY_REFTO) {
2555 if (obj->ex_Decl == NULL ||
2556 (obj->ex_Decl->d_Scope.s_Flags &
2558 exFlags |= EXF_UNLOCKEDMTH;
2562 dassert_exp(exp, 0);
2568 * Leave the lhs intact, but set the
2569 * duplication flag in case things get
2572 exLhs->ex_Lhs = SetDupExp(sg, exLhs->ex_Lhs);
2573 obj->ex_Next = exRhs->ex_Lhs;
2574 exRhs->ex_Lhs = obj;
2576 atype = obj->ex_Type;
2582 * Try to set an alternative search context during
2583 * resolution of the procedure arguments. This context
2584 * is only searched if an identifier cannot be found
2585 * through normal means so local variables and such
2586 * will override it as the programmer should expect.
2587 * Since the local semantic stack is under the
2588 * programmer's control, unexpected collisions should
2589 * either not occur or be easily fixed.
2592 switch(atype->ty_Op) {
2594 atype = atype->ty_PtrType.et_Type;
2597 atype = atype->ty_PtrType.et_Type;
2600 if (atype->ty_Op != TY_CLASS)
2604 save_asg = sg->sg_AltContext;
2605 sg->sg_AltContext = atype->ty_ClassType.et_SemGroup;
2611 * Resolve the right hand side, which are the
2612 * procedure arguments as a compound type. This
2613 * can get tricky. XXX
2615 * NOTE: We inherit the SF_LVALUE flag from the
2616 * return type. Parent might turn it off.
2618 /*d = exLhs->ex_Decl;*/
2619 exRhs = resolveExp(isg, sg, exRhs,
2620 ltype->ty_ProcType.et_ArgsType,
2621 flags | RESOLVE_AUTOCAST);
2622 exType = ltype->ty_ProcType.et_RetType;
2625 * Restore AltContext after resolving rhs.
2627 sg->sg_AltContext = save_asg;
2628 } else if ((exRhs->ex_Flags & (EXF_CONST |
2630 (exLhs->ex_Decl->d_ScopeFlags & SCOPE_PURE)) {
2632 * atype NULL (not method call, which requires
2633 * an object), arguments can become constants,
2634 * pure function, so result can become a
2637 exFlags |= EXF_PROBCONST;
2643 * (NOTE EARLY RETURN)
2645 * A compound expression should always be an RVALUE, but
2646 * might contain LVALUEs (XXX).
2649 exp = resolveCompoundExp(isg, sg, exp, itype, flags);
2654 * The caller must be able to handle a type return when
2657 dassert_exp(exp, exFlags & EXF_REQ_TYPE);
2662 * If an expression was supplied, convert it to a type.
2664 * NOTE: ex_Flags hints must 'always happen' since we may be
2665 * modifying an expression that will later be Dup'd.
2668 if ((exFlags & EXF_RET_TYPE) == 0) {
2669 dassert(exLhs != NULL);
2670 exLhs->ex_Flags |= EXF_REQ_TYPE;
2671 exLhs = resolveExp(isg, sg, exLhs, NULL,
2672 flags & ~RESOLVE_AUTOCAST);
2673 exType = exLhs->ex_Type;
2675 /* do not clear EXF_UNARY, messes up tmp exp storage */
2676 /* exFlags &= ~EXF_UNARY; */
2678 exFlags |= EXF_RET_TYPE;
2679 /* XXX delete the lhs */
2681 exType = RESOLVETYPE(exType);
2685 exId = StrTableInt(exType->ty_Bytes);
2686 exp->ex_Token = exToken = TOK_INTEGER;
2688 exFlags &= ~EXF_RET_TYPE;
2689 exFlags |= EXF_CONST;
2692 dassert_exp(exp, exType->ty_Op == TY_ARYOF);
2693 if (exType->ty_AryType.et_Type->ty_Bytes) {
2694 exId = StrTableInt(exType->ty_Bytes /
2695 exType->ty_AryType.et_Type->ty_Bytes);
2697 exId = StrTableInt(0);
2699 exp->ex_Token = exToken = TOK_INTEGER;
2701 exFlags &= ~EXF_RET_TYPE;
2702 exFlags |= EXF_CONST;
2706 /* type is returned */
2711 dassert_exp(exp, 0);
2716 * Resolve the type and cast-to-type.
2719 exType = RESOLVETYPE(exType);
2720 /* XXX exType was ex_Type */
2723 * Special-case compound compatibility issues so the
2724 * interpreter and code generator do not have to deal with
2727 if ((flags & RESOLVE_AUTOCAST) && itype &&
2728 itype->ty_Op == TY_COMPOUND &&
2729 exType->ty_Op != TY_COMPOUND) {
2731 * The expression parser might have optimized-out
2732 * the TOK_COMPOUND wrapper around single-element
2733 * parenthesized expressions. Add it back in if
2734 * the cast target expects a compound expression.
2736 * XXX Currently hack a SetDupExp() to avoid
2737 * re-resolving the already-resolved component.
2740 saveExpCopy(©, exp);
2741 exp = ExpToCompoundExp(exp, TOK_COMPOUND);
2742 exp = resolveCompoundExp(isg, sg, exp, itype, flags);
2743 loadExpCopy(©, exp);
2745 if ((flags & RESOLVE_AUTOCAST) && itype &&
2746 itype->ty_Op == TY_CLASS &&
2747 exType->ty_Op == TY_CLASS &&
2748 itype != &VoidType &&
2749 (itype->ty_Flags & (TF_ISBOOL | TF_ISINTEGER |
2750 TF_ISFLOATING)) == 0 &&
2751 (exType->ty_Flags & (TF_ISBOOL | TF_ISINTEGER |
2754 * The expression parser might have optimized-out
2755 * the TOK_COMPOUND wrapper around single-element
2756 * parenthesized expressions used in a class iterator
2757 * (in an assignment). Add it back in if the
2758 * itype is a non-core class and exType is a core
2761 * XXX Currently hack a SetDupExp() to avoid
2762 * re-resolving the already-resolved component.
2765 saveExpCopy(©, exp);
2766 exp = ExpToCompoundExp(exp, TOK_COMPOUND);
2767 exp = resolveCompoundExp(isg, sg, exp, itype, flags);
2768 loadExpCopy(©, exp);
2772 * If the type hint did not succeed we may have to cast the
2773 * expression to the requested type. Note that if the itype
2774 * was set as part of an array optimization request which could
2775 * not be handled, we must ignore itype.
2777 * Note that SimilarType() will allow exp->ex_Type to be a
2778 * var-args TY_ARGS, and since the original Rhs of a call
2779 * is set to the procedure arguments type, VarType.et_Type
2780 * should match exactly.
2783 (exFlags & (EXF_REQ_ARRAY|EXF_RET_ARRAY)) != EXF_REQ_ARRAY
2785 if ((itype->ty_Flags & TF_RESOLVED) == 0)
2786 itype = RESOLVETYPE(itype);
2787 if ((itype->ty_SQFlags & SF_LVALUE) &&
2788 (exType->ty_SQFlags & SF_LVALUE) == 0
2791 fprintf(stderr, "Exp must be an lvalue here\n");
2792 dassert_exp(exp, 0);
2795 if (!SimilarType(itype, exType) &&
2796 (flags & RESOLVE_AUTOCAST)) {
2797 if (exp->ex_Flags & EXF_DUPEXP) {
2798 Exp *nexp = AllocExp(NULL);
2801 LexDupRef(&exp->ex_LexRef,
2804 exFlags &= ~EXF_DUPEXP;
2805 /*exp = DupExp(sg, exp);*/
2807 exFlags |= EXF_RESOLVED;
2808 exp = dupExpCopy(©, exp);
2809 exp = resolveExpCast(isg, sg, exp, itype,
2811 loadExpCopy(©, exp);
2817 * Generic constant evaluation flag. Note that EXF_PROBCONST
2818 * could also be set above (TOK_CALL).
2821 (exLhs == NULL || (exLhs->ex_Flags & (EXF_CONST|EXF_PROBCONST))) &&
2822 (exRhs == NULL || (exRhs->ex_Flags & (EXF_CONST|EXF_PROBCONST)))) {
2823 exFlags |= EXF_PROBCONST;
2826 exFlags |= EXF_RESOLVED;
2827 exp = dupExpCopy(©, exp);
2832 * Resolve an expression for which the resolver needs the result
2836 resolveConstExp(SemGroup *isg, SemGroup *sg, Exp *exp, int flags)
2838 runesize_t tmpbytes;
2839 runesize_t tmpalign;
2843 flags &= ~RESOLVE_AUTOCAST;
2845 if ((exp->ex_Flags & EXF_RESOLVED) == 0)
2846 exp = resolveExp(isg, sg, exp, NULL, flags);
2848 oflags = exp->ex_Flags;
2849 ooffset = exp->ex_TmpOffset;
2852 resolveStorageExpAlign(exp, &tmpalign, RESOLVE_CONSTEXP);
2853 resolveStorageExp(exp, &tmpbytes);
2855 if ((exp->ex_Flags & (EXF_CONST | EXF_PROBCONST)) == 0) {
2856 ExpPrintError(exp, TOK_ERR_EXPECTED_INTEGRER_CONST);
2857 dassert_exp(exp, 0);
2861 * Special interpreter execution to resolve the expression.
2867 int64_t tmpbuf[128];
2868 float128_t tmpflt[64];
2871 bzero(&ct, sizeof(ct));
2872 ct.ct_Flags |= CTF_RESOLVING;
2873 if (sg->sg_TmpBytes < (runesize_t)sizeof(u.tmpbuf) &&
2874 sg->sg_TmpAlignMask < (runesize_t)sizeof(float128_t))
2875 ct.ct_TmpData = (char *)u.tmpbuf;
2877 posix_memalign((void *)&ct.ct_TmpData,
2878 sg->sg_TmpAlignMask + 1,
2881 ct.ct_TmpBytes = sg->sg_TmpBytes;
2882 ct.ct_CtxRefStor.rs_Refs = 1;
2883 exp->ex_Run(&ct, &data, exp);
2885 if ((exp->ex_Flags & EXF_CONST) == 0) {
2886 ExpPrintError(exp, TOK_ERR_EXPECTED_INTEGRER_CONST);
2887 dassert_exp(exp, 0);
2889 if (ct.ct_TmpData != (char *)u.tmpbuf)
2890 free(ct.ct_TmpData);
2894 * exp is now a constant, restore the original ex_TmpOffset
2895 * for normal execution/operation (the storage may be needed for
2898 if (oflags & EXF_TMPRESOLVED) {
2899 exp->ex_TmpOffset = ooffset;
2900 resolveStorageExp(exp, &tmpbytes);
2902 exp->ex_TmpOffset = -1;
2903 exp->ex_Flags &= ~EXF_TMPRESOLVED;
2910 resolveConstExpBool(SemGroup *isg, SemGroup *sg, Exp *exp, int flags,
2913 runesize_t tmpbytes;
2914 runesize_t tmpalign;
2918 flags &= ~RESOLVE_AUTOCAST;
2920 if ((exp->ex_Flags & EXF_RESOLVED) == 0) {
2921 exp = resolveExp(isg, sg, exp, NULL, flags);
2925 * [re]-resolve the storage from 0 so we can execute the expression.
2927 oflags = exp->ex_Flags;
2928 ooffset = exp->ex_TmpOffset;
2931 resolveStorageExpAlign(exp, &tmpalign, RESOLVE_CONSTEXP);
2932 resolveStorageExp(exp, &tmpbytes);
2933 if ((exp->ex_Flags & (EXF_CONST | EXF_PROBCONST)) == 0) {
2934 ExpPrintError(exp, TOK_ERR_EXPECTED_INTEGRER_CONST);
2935 dassert_exp(exp, 0);
2939 * Special interpreter execution to resolve the expression.
2946 int64_t tmpbuf[128];
2947 float128_t tmpflt[64];
2950 bzero(&ct, sizeof(ct));
2951 ct.ct_Flags |= CTF_RESOLVING;
2956 if (tmpbytes < (runesize_t)sizeof(u.tmpbuf))
2957 ct.ct_TmpData = (char *)u.tmpbuf;
2959 posix_memalign((void *)&ct.ct_TmpData, 16, tmpbytes);
2960 ct.ct_TmpBytes = tmpbytes;
2961 ct.ct_CtxRefStor.rs_Refs = 1;
2962 exp->ex_Run(&ct, &data, exp);
2965 if ((exp->ex_Flags & EXF_CONST) == 0) {
2966 ExpPrintError(exp, TOK_ERR_EXPECTED_INTEGRER_CONST);
2967 dassert_exp(exp, 0);
2969 ts->ts_Bool = rts->ts_Bool;
2970 if (ct.ct_TmpData != (char *)u.tmpbuf)
2971 free(ct.ct_TmpData);
2975 * exp is now a constant, restore the original ex_TmpOffset
2976 * for normal execution/operation (the storage may be needed for
2979 if (oflags & EXF_TMPRESOLVED) {
2980 exp->ex_TmpOffset = ooffset;
2981 resolveStorageExp(exp, &tmpbytes);
2983 exp->ex_TmpOffset = -1;
2984 exp->ex_Flags &= ~EXF_TMPRESOLVED;
2991 * Extract constant from already-constant-resolved expression.
2992 * resolveConstExp() must have previously been called on exp.
2994 * Expression must have already been constant-optimized, meaning
2995 * that we should be able to execute it without a context to access
2996 * the cached results in exp->u.
3000 resolveGetConstExpInt64(Exp *exp)
3005 dassert_exp(exp, exp->ex_Token == TOK_INTEGER ||
3006 (exp->ex_Flags & EXF_CONST));
3007 exp->ex_Run(NULL, &data, exp);
3009 if (exp->ex_Type->ty_Flags & TF_ISUNSIGNED) {
3010 switch(exp->ex_Type->ty_Bytes) {
3012 value = *(uint8_t *)data.data;
3015 value = *(uint16_t *)data.data;
3018 value = *(uint32_t *)data.data;
3021 value = *(uint64_t *)data.data;
3025 dassert_exp(exp, 0);
3029 switch(exp->ex_Type->ty_Bytes) {
3031 value = *(int8_t *)data.data;
3034 value = *(int16_t *)data.data;
3037 value = *(int32_t *)data.data;
3040 value = *(int64_t *)data.data;
3044 dassert_exp(exp, 0);
3053 resolveGetConstExpFloat128(Exp *exp)
3058 dassert_exp(exp, exp->ex_Token == TOK_FLOAT ||
3059 (exp->ex_Flags & EXF_CONST));
3060 exp->ex_Run(NULL, &data, exp);
3062 switch(exp->ex_Type->ty_Bytes) {
3064 value = (float128_t)*(float32_t *)data.data;
3067 value = (float128_t)*(float64_t *)data.data;
3070 value = *(float128_t *)data.data;
3074 dassert_exp(exp, 0);
3081 * resolveCompoundExp() - resolve a compound expression (called from
3082 * resolveExp() and resolveExpOper()).
3084 * Resolve a compound expression. Compound expressions require
3085 * a compound type to normalize against. This will work for
3086 * direct assignments, return values, casts, and procedure arguments
3089 * NOTE: We can't use itype if EXF_REQ_ARRAY is specified because
3090 * its hinting for the array optimization case, which we cannot do.
3092 * Compound expressions may be used in conjuction with types
3093 * reprsenting classes, compound types, and procedure arguments. The
3094 * compound expression may contain subclasses of the superclasses expected
3095 * by itype. This is only allowed if the procedure's body has not yet been
3096 * generated (for example, a method call in a subclass).
3098 * Partially resolved operators are typically converted into procedure calls
3099 * and method calls are also partially resolved, so some elements may already
3102 * XXX named initialization, missing elements (structural
3103 * initialization), and so forth needs to be dealt with.
3106 resolveCompoundExp(SemGroup *isg, SemGroup *sg, Exp *exp,
3107 Type *itype, int flags)
3118 flags &= ~RESOLVE_AUTOCAST; /* not applicable to this function */
3121 * Expression dup()ing
3123 if (exp->ex_Flags & EXF_DUPEXP) {
3125 static int count; fprintf(stderr, "DUPEXPC %d\n", ++count);
3127 exp = DupExp(sg, exp);
3130 if (itype && (exp->ex_Flags & EXF_REQ_ARRAY) == 0)
3131 exp->ex_Type = itype;
3134 * If we don't have a SemGroup to normalize against, XXX how should
3135 * we normalize the compound expression?
3137 if (exp->ex_Type == NULL) {
3138 dassert_exp(exp, 0);
3142 * Normalize the compound expression based on the
3143 * argument types expected by the procedure. We have
3144 * to resolve the type before we start the scan in order
3145 * to ensure that d_Offset is properly assigned.
3147 * Use the declarations found in the compound type
3148 * semantic group to coerce the procedure arguments to
3149 * generate the correct compound type. Note that resolveExp()
3150 * recursion must still use the SemGroup that was passed to us.
3152 * XXX deal with defaults and pre-resolved arguments. XXX
3154 type = exp->ex_Type = RESOLVETYPE(exp->ex_Type);
3156 switch(type->ty_Op) {
3158 sg2 = type->ty_ArgsType.et_SemGroup;
3161 sg2 = type->ty_VarType.et_SemGroup;
3164 sg2 = type->ty_CompType.et_SemGroup;
3167 sg2 = type->ty_ClassType.et_SemGroup;
3170 dassert_exp(exp, 0);
3171 sg2 = NULL; /* NOT REACHED */
3174 pscan = &exp->ex_Lhs;
3177 * Scan the compound expression and match it up against the compound
3180 d = RUNE_FIRST(&sg2->sg_DeclList);
3181 while ((scan = *pscan) != NULL) {
3182 if (scan->ex_ArgId != NULL) {
3184 * Named argument, find it
3186 * (Overloading not allowed)
3188 int eno = TOK_ERR_ID_NOT_FOUND;
3191 nd = FindDeclId(sg2, scan->ex_ArgId, &eno);
3193 ExpFatalError(scan, eno);
3198 * XXX for now, punt on setting EXF_PROBCONST
3199 * if the named argument skips a declaration.
3201 if (nd != d && nd != RUNE_NEXT(d, d_Node)) {
3207 * Unnamed argument, run through sequentially. Skip
3208 * any non-storage or global storage.
3210 while (d && d->d_Op != DOP_ARGS_STORAGE &&
3211 d->d_Op != DOP_STACK_STORAGE &&
3212 d->d_Op != DOP_GROUP_STORAGE
3214 d = RUNE_NEXT(d, d_Node);
3218 * Ran out of storage declarations. If this is a
3219 * var-args SemGroup then we actually create a new
3220 * SemGroup (and eventually a new type) to represent
3223 * We then extend the varargs SemGroup. This isn't
3228 (sg2->sg_Flags & SGF_VARARGS)) {
3229 sg2 = DupSemGroup(sg2->sg_Parent, NULL, sg2, 1);
3231 if (resolveSemGroup1(sg3, flags) &&
3232 resolveSemGroup2(sg3, flags))
3233 resolveSemGroup3(sg3, flags);
3240 "Too many arguments in "
3242 dassert_exp(scan, 0);
3248 * Unlink the expression from the compound list temporarily
3249 * so we can safely resolve it. Either cast the expression
3250 * to the compound element, or create a compound element
3251 * (e.g. varargs call) to match the expression.
3253 * Due to the resolver moving things around, the elements of
3254 * a compound expression are sometimes resolved multiple times.
3256 *pscan = scan->ex_Next;
3257 scan->ex_Next = NULL;
3259 Type *dtype = d->d_StorDecl.ed_Type;
3265 if (SimilarType(dtype, &PointerType) &&
3266 (dtype->ty_SQFlags & SF_LVALUE) == SF_LVALUE
3269 sflags = flags & ~RESOLVE_AUTOCAST;
3271 sflags = flags | RESOLVE_AUTOCAST;
3275 * LValueStor needs a RS, set ADDRUSED to make sure
3276 * its available to the generator.
3278 if (d->d_ScopeFlags & SCOPE_LVALUE)
3279 scan->ex_Flags |= EXF_ADDRUSED;
3281 if ((scan->ex_Flags & EXF_RESOLVED) == 0) {
3282 scan = resolveExp(isg, sg, scan,
3286 * Since we have already resolved the
3287 * expression we need to do the same sanity
3288 * checking that it would do to cast.
3291 (dtype->ty_SQFlags & SF_LVALUE) == 0 ||
3292 (scan->ex_Type->ty_SQFlags & SF_LVALUE));
3293 if (!SimilarType(dtype, scan->ex_Type)) {
3294 scan = resolveExpCast(isg, sg, scan,
3299 Scope tscope = INIT_SCOPE(0);
3301 if ((scan->ex_Flags & EXF_RESOLVED) == 0)
3302 scan = resolveExp(isg, sg, scan, NULL,
3303 flags & ~RESOLVE_AUTOCAST);
3304 dassert(varargs != 0);
3305 d = AllocDeclaration(sg2, DOP_ARGS_STORAGE, &tscope);
3306 d->d_StorDecl.ed_Type = DEL_LVALUE(scan->ex_Type);
3308 d->d_Bytes = scan->ex_Type->ty_Bytes;
3309 d->d_AlignMask = scan->ex_Type->ty_AlignMask;
3312 * __align(%d) scope qualifier, override the type's
3315 if ((d->d_Scope.s_Flags & SCOPE_ALIGN) &&
3316 d->d_Scope.s_AlignOverride) {
3317 d->d_AlignMask = d->d_Scope.s_AlignOverride - 1;
3321 sg2->sg_Bytes = (sg2->sg_Bytes + d->d_AlignMask) &
3324 d->d_Offset = sg2->sg_Bytes;
3325 d->d_Storage = GENSTAT_LOCK;
3327 sg2->sg_Bytes += d->d_Bytes;
3328 if (sg2->sg_AlignMask < d->d_AlignMask)
3329 sg2->sg_AlignMask = d->d_AlignMask;
3334 * Relink and check if constant
3336 scan->ex_Next = *pscan;
3338 if ((scan->ex_Flags & (EXF_CONST | EXF_PROBCONST)) == 0)
3340 stype = scan->ex_Type;
3343 * If the declaration requires an LVALUE, assert that
3344 * we have an lvalue. Otherwise set the direct-store
3345 * request (also see InterpCompoundExp).
3347 if (d->d_ScopeFlags & SCOPE_LVALUE) {
3348 if ((stype->ty_SQFlags & SF_LVALUE) == 0)
3349 fprintf(stderr, "argument must be an lvalue\n");
3350 dassert_exp(scan, stype->ty_SQFlags & SF_LVALUE);
3355 * Check content locking state against scan. Only matters
3356 * when passing a pointer as an lvalue since only pointers
3357 * can be content-locked.
3359 * We don't have to worry if we are passing a pointer as an
3360 * rvalue since the code generator will fixup the locking in
3363 if ((d->d_ScopeFlags & SCOPE_LVALUE) &&
3364 (stype->ty_Op == TY_PTRTO || stype->ty_Op == TY_REFTO)) {
3368 scope1 = d->d_ScopeFlags & (SCOPE_UNLOCKED |
3370 if (d->d_Id == String_This) {
3371 /* XXX temporarily ignore e.g. ptr.new() */
3373 } else if (scan->ex_Decl) {
3374 scope2 = scan->ex_Decl->d_ScopeFlags &
3375 (SCOPE_UNLOCKED | SCOPE_HARD);
3377 scope2 = SCOPE_UNLOCKED;
3379 if (scope1 != scope2) {
3380 fprintf(stderr, "scopes: %08x, %08x\n",
3382 if (d->d_Id == String_This) {
3384 TOK_ERR_SCOPE_MISMATCH_THIS);
3387 TOK_ERR_SCOPE_MISMATCH);
3396 d = RUNE_NEXT(d, d_Node);
3397 pscan = &scan->ex_Next;
3401 * Make sure the caller knows its a var-args function even if
3402 * we didn't supply any additional args. Otherwise the backend
3403 * may not generate the correct form for calls to the target.
3406 (sg2->sg_Flags & SGF_VARARGS)) {
3407 sg2 = DupSemGroup(sg2->sg_Parent, NULL, sg2, 1);
3412 * Resolve the varargs sg2 after building it.
3415 if (resolveSemGroup1(sg2, flags) &&
3416 resolveSemGroup2(sg2, flags)) {
3417 resolveSemGroup3(sg2, flags);
3419 /* resolveStorageSemGroupAlign(sg2); */
3420 /*resolveStorageSemGroup(sg2, 0, 0);*/
3424 * If we made a var-args call, adjust the expression's type
3427 dassert(type->ty_Op == TY_ARGS);
3428 exp->ex_Type = RESOLVETYPE(TypeToVarType(type, sg2));
3431 exp->ex_Flags |= EXF_PROBCONST;
3433 exp->ex_Flags |= EXF_RESOLVED;
3438 * resolveExpCast() - Cast the expression to the specified type and return
3439 * the cast expression.
3441 * Note that expression nodes depend on their ex_Type being correct,
3442 * and also expressions may be shared, so be careful not to modify the
3443 * ex_Type (or anything else) in the existing expression.
3445 * This code is somewhat different then resolveExpOper() and friends.
3446 * The Exp argument has already been resolved so do not resolve it
3447 * again, and the cast type already has SF_LVALUE set or cleared as
3448 * appropriate (had better be cleared!)
3450 * As with operators we have to locate the cast declaration matching
3451 * the cast we want to do.
3454 resolveExpCast(SemGroup *isg, SemGroup *sg, Exp *exp, Type *ltype, int flags)
3459 flags &= ~RESOLVE_AUTOCAST; /* not applicable to this function */
3461 rtype = exp->ex_Type;
3462 dassert(rtype && ltype);
3464 * XXX attempt to cast from subclass to superclass?
3468 * XXX look in our local semantic hierarchy for a compatible cast ?
3472 * Look in the right hand (source) type for the cast
3474 d = findCast(rtype, ltype, rtype, flags);
3477 * If that fails then look in the left hand (destination) type for
3481 d = findCast(ltype, ltype, rtype, flags);
3484 if (d == NULL && (rtype->ty_Op == TY_PTRTO ||
3485 rtype->ty_Op == TY_REFTO ||
3486 rtype->ty_Op == TY_CPTRTO)) {
3487 d = findCast(&PointerType, ltype, rtype, flags);
3493 * We could not find a specific cast operator. There are
3494 * some inherent casts that we can do. We run through these
3495 * in attempt to come up with matching types.
3497 if (ltype->ty_Op != rtype->ty_Op &&
3498 (ltype->ty_Op == TY_PTRTO || ltype->ty_Op == TY_CPTRTO ||
3499 ltype->ty_Op == TY_ARYOF) &&
3500 (rtype->ty_Op == TY_PTRTO || rtype->ty_Op == TY_CPTRTO ||
3501 rtype->ty_Op == TY_ARYOF)) {
3503 * Pointers, C pointers, or arrays can be cast to
3504 * pointers, C pointers, or arrays of the same type.
3506 * Cast the right hand type to an equivalent
3507 * pointer/cpointer/array of the right hand type
3508 * and re-resolve the cast.
3510 exp = ExpToCastExp(exp,
3511 RESOLVETYPE(ChangeType(rtype, ltype->ty_Op)));
3512 return(resolveExpCast(isg, sg, exp, ltype, flags));
3513 } else if (MatchType(ltype, rtype) <= SG_COMPAT_PART) {
3515 * If the types are compatible (casting rtype->ltype),
3516 * we can cast trivially.
3518 exp = ExpToCastExp(exp, ltype);
3519 } else if (MatchType(&NumericType, ltype) <= SG_COMPAT_PART &&
3520 MatchType(&NumericType, rtype) <= SG_COMPAT_PART) {
3522 * Casting from one numeric type to another must be
3523 * supported by the interpreter/compiler.
3525 exp = ExpToCastExp(exp, ltype);
3526 } else if (SimilarType(&VoidType, ltype)) {
3528 * Casting anything to void is allowed (throwing the
3529 * object away). E.g. statement-expressions.
3531 exp = ExpToCastExp(exp, ltype);
3532 } else if (SimilarType(&VoidPtrType, ltype)) {
3534 * Casting a pointer to a (void *) is trivial, but is
3535 * only allowed if the underlying structure does not
3536 * contain any pointers.
3538 * NOTE: Generally only used when a pointer is being
3539 * cast to an integer. Rune does not allow
3540 * casting back to other pointer types.
3542 * XXX validate integral # of objects fit in pointer
3545 if (rtype->ty_PtrType.et_Type->ty_Flags & TF_HASLVPTR)
3546 ExpFatalError(exp, TOK_ERR_LIMITED_VOIDP_CAST);
3547 exp = ExpToCastExp(exp, ltype);
3548 } else if (SimilarType(&VoidRefType, ltype)) {
3550 * Casting a pointer to a (void @) is trivial.
3552 * NOTE: Generally only used when a pointer is being
3553 * cast to an integer. Rune does not allow
3554 * casting back to other pointer types.
3556 * XXX validate integral # of objects fit in pointer
3559 if (rtype->ty_PtrType.et_Type->ty_Flags & TF_HASLVPTR)
3560 ExpFatalError(exp, TOK_ERR_LIMITED_VOIDP_CAST);
3561 exp = ExpToCastExp(exp, ltype);
3562 } else if (SimilarType(rtype, &VoidPtrType)) {
3564 * Casting from a void pointer may not be trivial
3565 * but we leave it up to the interpreter/compiler.
3567 * Only allow if the target does not contain any
3568 * pointers or if the right-hand-side is NULL.
3570 * XXX validate integral # of objects fit in pointer
3573 switch(ltype->ty_Op) {
3576 if ((exp->ex_Flags & EXF_NULL) == 0 &&
3577 (ltype->ty_PtrType.et_Type->ty_Flags &
3579 ExpFatalError(exp, TOK_ERR_LIMITED_VOIDP_CAST);
3585 exp = ExpToCastExp(exp, ltype);
3586 } else if (SimilarType(rtype, &CVoidPtrType)) {
3587 switch(ltype->ty_Op) {
3589 if ((exp->ex_Flags & EXF_NULL) == 0 &&
3590 (ltype->ty_PtrType.et_Type->ty_Flags &
3592 ExpFatalError(exp, TOK_ERR_LIMITED_VOIDP_CAST);
3598 } else if (SimilarType(ltype, &BoolType) &&
3599 (rtype->ty_Op == TY_PTRTO ||
3600 rtype->ty_Op == TY_REFTO ||
3601 rtype->ty_Op == TY_CPTRTO)) {
3603 * Any pointer can be cast to a boolean, which
3604 * tests against NULL.
3606 exp = ExpToCastExp(exp, ltype);
3607 } else if (ltype->ty_Op == rtype->ty_Op &&
3608 (ltype->ty_Op == TY_PTRTO ||
3609 ltype->ty_Op == TY_CPTRTO ||
3610 ltype->ty_Op == TY_ARYOF)) {
3612 * We allow casts of pointers to similar numeric
3613 * types if they are the same size, though this is
3614 * really rather a hack. This is mainly to handle
3615 * the signed<->unsigned cast case. XXX
3619 switch(ltype->ty_Op) {
3621 if ((ltype->ty_PtrType.et_Type->ty_SQFlags &
3623 (rtype->ty_PtrType.et_Type->ty_SQFlags &
3625 ExpFatalError(exp, TOK_ERR_READONLY);
3628 if (MatchType(&NumericType,
3629 ltype->ty_PtrType.et_Type) <=
3630 SG_COMPAT_SUBCLASS &&
3631 MatchType(&NumericType,
3632 rtype->ty_PtrType.et_Type) <=
3633 SG_COMPAT_SUBCLASS &&
3634 ltype->ty_Bytes == rtype->ty_Bytes
3636 exp = ExpToCastExp(exp, ltype);
3641 if ((ltype->ty_CPtrType.et_Type->ty_SQFlags &
3643 (rtype->ty_CPtrType.et_Type->ty_SQFlags &
3645 ExpFatalError(exp, TOK_ERR_READONLY);
3647 if (MatchType(&NumericType,
3648 ltype->ty_CPtrType.et_Type) <=
3649 SG_COMPAT_SUBCLASS &&
3650 MatchType(&NumericType,
3651 rtype->ty_CPtrType.et_Type) <=
3652 SG_COMPAT_SUBCLASS &&
3653 ltype->ty_Bytes == rtype->ty_Bytes
3655 exp = ExpToCastExp(exp, ltype);
3660 if ((ltype->ty_AryType.et_Type->ty_SQFlags &
3662 (rtype->ty_AryType.et_Type->ty_SQFlags &
3664 ExpFatalError(exp, TOK_ERR_READONLY);
3666 if (MatchType(&NumericType,
3667 ltype->ty_AryType.et_Type) <=
3668 SG_COMPAT_SUBCLASS &&
3669 MatchType(&NumericType,
3670 rtype->ty_AryType.et_Type) <=
3671 SG_COMPAT_SUBCLASS &&
3672 ltype->ty_Bytes == rtype->ty_Bytes
3674 exp = ExpToCastExp(exp, ltype);
3681 "Unable to resolve cast from pointers "
3682 "to dissimilar numeric types "
3684 TypeToStr(rtype, NULL),
3685 TypeToStr(ltype, NULL));
3686 dassert_exp(exp, 0);
3690 "Unable to resolve cast from %s to %s\n",
3691 TypeToStr(rtype, NULL),
3692 TypeToStr(ltype, NULL));
3693 dassert_exp(exp, 0);
3695 } else if (d->d_ScopeFlags & SCOPE_INTERNAL) {
3697 * We found a cast operator and it is an internal operator
3699 exp = ExpToCastExp(exp, ltype);
3703 * We found a cast operator and it is a Rune cast procedure. We
3704 * must convert the cast to a procedure call. If we want
3705 * resolveCompoundExp() to be able to generate a compatible
3706 * procedure (in a subclass) we have to tell it about the
3711 sexp = ExpToCompoundExp(exp, TOK_COMPOUND);
3712 if (d->d_ProcDecl.ed_ProcBody == NULL)
3714 sexp = resolveCompoundExp(isg, sg, sexp,
3715 d->d_ProcDecl.ed_Type->ty_ProcType.et_ArgsType,
3717 exp = AllocExp(NULL);
3718 exp->ex_Lhs = AllocExp(NULL);
3719 exp->ex_Lhs->ex_Token = TOK_DECL;
3720 exp->ex_Lhs->ex_Id = d->d_Id;
3721 exp->ex_Lhs->ex_Decl = d;
3722 exp->ex_Lhs->ex_Type = d->d_ProcDecl.ed_Type;
3723 exp->ex_Lhs->ex_Flags |= EXF_RESOLVED;
3725 exp->ex_Flags |= EXF_BINARY;
3726 exp->ex_Token = TOK_CALL;
3727 /* XXX use ltype or procedure's rettype? */
3728 exp->ex_Type = ltype;
3729 LexDupRef(&sexp->ex_LexRef, &exp->ex_LexRef);
3730 LexDupRef(&sexp->ex_LexRef, &exp->ex_Lhs->ex_LexRef);
3732 exp->ex_Flags |= EXF_RESOLVED;
3738 findCast(Type *btype, Type *ltype, Type *rtype, int flags)
3743 flags &= ~RESOLVE_AUTOCAST; /* not applicable to this function */
3746 * Locate the base type. If the base type does not have a SemGroup
3747 * there are no casts. (XXX put system operators here)
3749 sg = BaseType(&btype);
3755 * Look for the cast in the SemGroup
3757 RUNE_FOREACH(d, &sg->sg_DeclList, d_Node) {
3758 if (d->d_Op == DOP_PROC && (d->d_ScopeFlags & SCOPE_CAST)) {
3759 if (MatchCastTypes(d, ltype, rtype))
3765 * Failed. If the base type is a compound type, look for the
3766 * cast in the SemGroup for each element making up the compound
3767 * type. e.g. so (mycustomtype, double) would find the cast
3770 if (btype->ty_Op == TY_COMPOUND) {
3771 RUNE_FOREACH(d, &sg->sg_DeclList, d_Node) {
3773 if (d->d_Op & DOPF_STORAGE) {
3774 d2 = findCast(d->d_StorDecl.ed_Type,
3775 ltype, rtype, flags);
3776 } else if (d->d_Op == DOP_TYPEDEF) {
3777 d2 = findCast(d->d_TypedefDecl.ed_Type,
3778 ltype, rtype, flags);
3791 * resolveExpOper() - resolve an operator
3793 * This is complex enough that it is broken out into its own procedure.
3794 * Normally we just look the operator up but we have to special case
3795 * pointer arithmatic because we do will not know until now that we
3798 * itype is a return-type hint only. resolveExpOper() can ignore it
3799 * if it wishes. We currently use it to detect cast-to-void, such as
3800 * when an expression like "++i" is used in a for() loop or as a
3801 * standalone statement. This allows us to optimize the case.
3804 resolveExpOper(SemGroup *isg, SemGroup *sg, Exp *exp, Type *itype, int flags)
3807 int isPointerOp = 0;
3810 flags &= ~RESOLVE_AUTOCAST; /* not applicable to this function */
3812 loadExpCopy(©, exp);
3813 dassert_exp(exp, exp->ex_Id != NULL);
3814 if (exFlags & EXF_BINARY) {
3815 exLhs = resolveExp(isg, sg, exLhs, NULL, flags);
3816 exRhs = resolveExp(isg, sg, exRhs, NULL, flags);
3817 } else if (exFlags & EXF_UNARY) {
3818 exLhs = resolveExp(isg, sg, exLhs, NULL, flags);
3820 dassert_exp(exp, 0);
3824 * If the lhs is a pointer look the operator up in the Pointer
3825 * class first. Operators in the Pointer class are special-cased.
3826 * A second pointer argument or a pointer return value must match
3829 * If this fails, or if the ltype is not a pointer, then look
3830 * the operator up normally.
3832 if (exLhs->ex_Type->ty_Op == TY_PTRTO ||
3833 exLhs->ex_Type->ty_Op == TY_REFTO ||
3834 exLhs->ex_Type->ty_Op == TY_CPTRTO
3839 if (exFlags & EXF_BINARY) {
3840 rtype = exRhs->ex_Type;
3841 ltype = exLhs->ex_Type;
3843 dassert(exFlags & EXF_UNARY);
3845 ltype = exLhs->ex_Type;
3847 d = findOper(&PointerType, exp->ex_Id, ltype, rtype, flags);
3851 d = findExpOper(©, flags);
3853 d = findExpOper(©, flags);
3857 * Fall through to finish up resolving the operator. We just set
3858 * ex_Decl for internal operators, and construct a call for
3859 * non-internal procedural operators.
3867 dassert_exp(exp, d != NULL);
3868 dassert_exp(exp, d->d_Op == DOP_PROC);
3869 dassert_exp(exp, d->d_ProcDecl.ed_Type->ty_Op == TY_PROC);
3870 type = d->d_ProcDecl.ed_Type;
3871 exType = type->ty_ProcType.et_RetType;
3874 * Special case for internal Pointer ops. The return type is
3875 * the left-hand type (we may still optimize it to void later).
3878 (d->d_ScopeFlags & SCOPE_INTERNAL) &&
3879 SimilarType(&VoidRefType, exType)
3881 if (exType->ty_SQFlags & SF_LVALUE)
3882 exType = ADD_LVALUE(exLhs->ex_Type);
3884 exType = DEL_LVALUE(exLhs->ex_Type);
3887 type = d->d_ProcDecl.ed_Type->ty_ProcType.et_ArgsType;
3888 dassert(type->ty_Op == TY_ARGS);
3889 sg2 = type->ty_ArgsType.et_SemGroup;
3892 * Assert that LVALUE requirements are met. XXX MatchType()
3893 * code should disallow the non-lvalue-cast-to-lvalue case
3894 * so we don't have to do a check here.
3896 RUNE_FOREACH(d2, &sg2->sg_DeclList, d_Node) {
3897 if ((d2->d_Op & DOPF_STORAGE) &&
3898 d2->d_Op != DOP_GLOBAL_STORAGE) {
3900 if ((d2->d_ScopeFlags & SCOPE_LVALUE) &&
3901 (exLhs->ex_Type->ty_SQFlags &
3905 "lhs of exp must be "
3907 dassert_exp(exp, 0);
3909 } else if (count == 1) {
3910 if ((d2->d_ScopeFlags & SCOPE_LVALUE) &&
3911 (exRhs->ex_Type->ty_SQFlags &
3915 "rhs of exp must be "
3917 dassert_exp(exp, 0);
3924 if (d->d_ScopeFlags & SCOPE_INTERNAL) {
3926 * Internal operator. Optimize any cast to void
3927 * by having the internal function deal with it.
3928 * (since we aren't setting exType the optimization
3929 * currently doesn't do anything, see ST_Exp)
3932 if (itype == &VoidType) {
3934 exFlags |= EXF_RET_VOID;
3938 * Normal procedural operator. Convert the left and
3939 * right hand sides to a compound expression and
3940 * convert exp to a TOK_CALL. NOTE! ex_Rhs may be
3943 * The compound expression may need to rewrite a
3944 * subclass procedure, which it can do if the
3945 * procedure's body has not yet been created (or
3946 * duplicated from the superclass). ex_Decl must
3947 * be set in this case.
3949 * Note that the expression structure may be shared.
3950 * The conversion is permanent so that is ok.
3952 * XXX keep the type intact?
3954 exLhs->ex_Next = exRhs;
3956 exRhs = ExpToCompoundExp(exRhs, TOK_COMPOUND);
3957 if (d->d_ProcDecl.ed_ProcBody == NULL)
3959 exRhs = resolveCompoundExp(isg, sg, exRhs, type, flags);
3960 exLhs = AllocExp(NULL);
3961 LexDupRef(&exp->ex_LexRef, &exLhs->ex_LexRef);
3962 exLhs->ex_Token = TOK_ID;
3963 exLhs->ex_Id = d->d_Id;
3965 exLhs->ex_Type = d->d_ProcDecl.ed_Type;
3966 exLhs->ex_Flags |= EXF_RESOLVED;
3967 exToken = exp->ex_Token = TOK_CALL;
3968 exFlags = EXF_BINARY;
3973 "Unable to resolve operator: %s\n", exp->ex_Id);
3974 dassert_exp(exp, 0);
3978 * Flag a pure operator whos arguments are constants as probably
3981 if (d->d_ScopeFlags & SCOPE_PURE) {
3982 if ((exLhs->ex_Flags & (EXF_CONST | EXF_PROBCONST)) &&
3984 (exRhs->ex_Flags & (EXF_CONST | EXF_PROBCONST)))) {
3985 exFlags |= EXF_PROBCONST;
3989 exFlags |= EXF_RESOLVED;
3990 return(dupExpCopy(©, exp));
3994 loadExpCopy(Exp *copy, Exp *exp)
3996 copy->ex_Lhs = exp->ex_Lhs;
3997 copy->ex_Rhs = exp->ex_Rhs;
3998 copy->ex_Flags = exp->ex_Flags;
3999 copy->ex_Type = exp->ex_Type;
4000 copy->ex_Decl = exp->ex_Decl;
4001 copy->ex_Token = exp->ex_Token;
4002 copy->ex_Visibility = exp->ex_Visibility;
4003 copy->ex_Id = exp->ex_Id;
4004 copy->ex_ArgId = exp->ex_ArgId;
4005 copy->ex_AuxExp = exp->ex_AuxExp;
4009 saveExpCopy(Exp *copy, Exp *exp)
4011 exp->ex_Lhs = copy->ex_Lhs;
4012 exp->ex_Rhs = copy->ex_Rhs;
4013 exp->ex_Flags = copy->ex_Flags;
4014 exp->ex_Type = copy->ex_Type;
4015 exp->ex_Decl = copy->ex_Decl;
4016 exp->ex_Token = copy->ex_Token;
4017 exp->ex_Visibility = copy->ex_Visibility;
4018 exp->ex_Id = copy->ex_Id;
4019 exp->ex_ArgId = copy->ex_ArgId;
4020 exp->ex_AuxExp = copy->ex_AuxExp;
4023 #define EXF_DUPSHAREFLAGS -1
4026 dupExpCopy(Exp *copy, Exp *exp)
4030 if ((exp->ex_Flags & EXF_DUPEXP) == 0) {
4031 saveExpCopy(copy, exp);
4036 * We can share the expression or subexpression across duplicated
4037 * elements in distinct subclasses if these conditions are met.
4039 * Note: 0x80000000 for ex_Visibility simply means that the visibility
4040 * was never modified and can be changed for the first time.
4041 * Superclasses are resolved first so we should be ok.
4043 if (exp->ex_Lhs == copy->ex_Lhs &&
4044 exp->ex_Rhs == copy->ex_Rhs &&
4045 ((exp->ex_Flags ^ copy->ex_Flags) & ~EXF_DUPSHAREFLAGS) == 0 &&
4046 (exp->ex_Type == copy->ex_Type || exp->ex_Type == NULL) &&
4047 exp->ex_Token == copy->ex_Token &&
4048 (exp->ex_Decl == copy->ex_Decl || exp->ex_Decl == NULL) &&
4049 (exp->ex_Id == copy->ex_Id || exp->ex_Id == NULL) &&
4050 (exp->ex_ArgId == copy->ex_ArgId || exp->ex_ArgId == NULL) &&
4051 (exp->ex_AuxExp == copy->ex_AuxExp || exp->ex_AuxExp == NULL) &&
4052 (exp->ex_Visibility == copy->ex_Visibility ||
4053 (exp->ex_Visibility & 0x80000000))
4057 fprintf(stderr, "DUPEXPB COMPARE %d %p\n", ++count, exp);
4059 saveExpCopy(copy, exp);
4063 nexp = AllocExp(NULL);
4064 LexDupRef(&exp->ex_LexRef, &nexp->ex_LexRef);
4070 "DUPEXPB %d %p lhs (%p,%p) rhs (%p,%p) "
4071 "flags (%08x,%08x) types (%p, %p) "
4072 "tokens (%04x, %04x), decl (%p, %p) "
4076 exp->ex_Lhs, copy->ex_Lhs,
4077 exp->ex_Rhs, copy->ex_Rhs,
4078 exp->ex_Flags & ~EXF_DUPSHAREFLAGS,
4079 copy->ex_Flags & ~EXF_DUPSHAREFLAGS,
4080 exp->ex_Type, copy->ex_Type,
4081 exp->ex_Token, copy->ex_Token,
4082 exp->ex_Decl, copy->ex_Decl,
4083 exp->ex_Visibility, copy->ex_Visibility
4085 ExpPrintError(exp, 0);
4089 copy->ex_Flags &= ~EXF_DUPEXP;
4090 saveExpCopy(copy, nexp);
4096 * resolveType() - Resolve a type
4098 * This routine is responsible for resolving the size and alignment
4099 * features of a type. Note that we do not special-case LVALUE
4100 * qualified types here.
4102 * This routine is also rsponsible for resolving the visibility of
4103 * a type's elements. Visibility is inherited from sub-types. Base
4104 * classes's visibility should already be set by resolveSuperClass()
4107 resolveType(Type *type, Type *adjtype, int flags)
4109 SemGroup *sg = NULL;
4113 flags &= ~RESOLVE_AUTOCAST; /* not applicable to this function */
4115 if (type->ty_Flags & TF_RESOLVED)
4118 dassert_type(type, (type->ty_Flags & TF_RESOLVING) == 0);
4119 type->ty_Flags |= TF_RESOLVING;
4121 switch(type->ty_Op) {
4124 * NOTE: TF_HASLVPTR inherited as appropriate after switch.
4126 * NOTE: Special case, PointerType fields not in classes XXX
4127 * (force alignment and bytes)?
4129 dassert(type->ty_SQList ==
4130 &type->ty_ClassType.et_SemGroup->sg_ClassList);
4131 sg = type->ty_ClassType.et_SemGroup;
4132 do2 = resolveSemGroup1(sg, flags);
4133 if (type != &PointerType) {
4134 type->ty_Bytes = sg->sg_Bytes;
4135 type->ty_AlignMask = sg->sg_AlignMask;
4137 /* visibility already determined by resolveSuperClass? */
4139 if (type->ty_ClassType.et_Super &&
4140 type->ty_ClassType.et_Super->ty_Op == TY_UNRESOLVED) {
4141 type->ty_ClassType.et_Super =
4142 resolveSuperClass(type->ty_ClassType.et_Super);
4146 * Type inherits ISUNSIGNED from class. This is a special
4147 * flag helper for the interpreter and code generator.
4149 if (sg->sg_Flags & SGF_ISINTEGER)
4150 type->ty_Flags |= TF_ISINTEGER;
4151 if (sg->sg_Flags & SGF_ISUNSIGNED)
4152 type->ty_Flags |= TF_ISUNSIGNED;
4153 if (sg->sg_Flags & SGF_ISFLOATING)
4154 type->ty_Flags |= TF_ISFLOATING;
4155 if (sg->sg_Flags & SGF_ISBOOL)
4156 type->ty_Flags |= TF_ISBOOL;
4157 if (sg->sg_Flags & SGF_HASASS)
4158 type->ty_Flags |= TF_HASASS;
4159 dassert(type->ty_Visibility != 0);
4163 * NOTE: Do not set TF_HASLVPTR, C pointers are not tracked.
4165 type->ty_Bytes = sizeof(void *);
4166 type->ty_AlignMask = POINTER_ALIGN;
4167 type->ty_CPtrType.et_Type =
4168 RESOLVETYPEADJ(type->ty_CPtrType.et_Type, type);
4169 type->ty_Visibility = type->ty_CPtrType.et_Type->ty_Visibility;
4173 * Set TF_HASLVPTR, pointers are tracked.
4175 type->ty_Bytes = sizeof(PointerStor);
4176 type->ty_AlignMask = POINTER_ALIGN;
4177 type->ty_PtrType.et_Type =
4178 RESOLVETYPEADJ(type->ty_PtrType.et_Type, type);
4179 type->ty_Visibility = type->ty_PtrType.et_Type->ty_Visibility;
4180 type->ty_Flags |= TF_HASLVPTR;
4184 * Set TF_HASLVPTR, references are tracked.
4186 type->ty_Bytes = sizeof(PointerStor);
4187 type->ty_AlignMask = POINTER_ALIGN;
4188 type->ty_RefType.et_Type =
4189 RESOLVETYPEADJ(type->ty_RefType.et_Type, type);
4190 type->ty_Visibility = type->ty_RefType.et_Type->ty_Visibility;
4191 type->ty_Flags |= TF_HASLVPTR;
4195 * Inherit TF_HASLVPTR (if array type is or contains something
4196 * which needs to be tracked).
4198 * XXX allow ArySize resolve to local expression?
4199 * XXX use interpreter to resolve constant expression?
4200 * XXX SemGroup passed as NULL.
4202 * XXX hack, ex_ArySize can be shared amoungst qualified
4203 * array types. Only resolve it once. XXX
4205 * YYY hack what is our ImportSemGroup ???
4208 Exp *exp = type->ty_AryType.et_ArySize;
4209 if ((exp->ex_Flags & EXF_RESOLVED) == 0) {
4210 exp = resolveConstExp(NULL,
4211 type->ty_AryType.et_SemGroup,
4214 type->ty_AryType.et_ArySize = exp;
4215 type->ty_AryType.et_Type =
4216 RESOLVETYPEADJ(type->ty_AryType.et_Type, type);
4217 type->ty_AryType.et_Count = resolveGetConstExpInt64(exp);
4218 type->ty_AlignMask =
4219 type->ty_AryType.et_Type->ty_AlignMask;
4221 type->ty_AryType.et_Type->ty_Bytes *
4222 type->ty_AryType.et_Count;
4224 type->ty_Visibility = type->ty_AryType.et_Type->ty_Visibility;
4225 type->ty_Flags |= type->ty_AryType.et_Type->ty_Flags &
4226 (TF_HASLVPTR | TF_HASCONSTRUCT |
4227 TF_HASDESTRUCT | TF_HASGCONSTRUCT |
4228 TF_HASGDESTRUCT | TF_HASASS);
4232 * NOTE: TF_HASLVPTR inherited as appropriate after switch.
4234 sg = type->ty_CompType.et_SemGroup;
4235 do2 = resolveSemGroup1(sg, flags);
4236 type->ty_Bytes = sg->sg_Bytes;
4237 type->ty_AlignMask = sg->sg_AlignMask;
4238 type->ty_Visibility = SCOPE_ALL_VISIBLE;
4242 * NOTE: TF_HASLVPTR inherited as appropriate after switch.
4244 sg = type->ty_VarType.et_SemGroup;
4245 do2 = resolveSemGroup1(sg, flags);
4246 type->ty_Bytes = sg->sg_Bytes;
4247 type->ty_AlignMask = sg->sg_AlignMask;
4248 type->ty_Visibility = SCOPE_ALL_VISIBLE;
4252 * NOTE: TF_HASLVPTR inherited as appropriate after switch.
4254 sg = type->ty_ArgsType.et_SemGroup;
4255 do2 = resolveSemGroup1(sg, flags);
4256 type->ty_Bytes = sg->sg_Bytes;
4257 type->ty_AlignMask = sg->sg_AlignMask;
4258 type->ty_Visibility = SCOPE_ALL_VISIBLE;
4262 * NOTE: Storage not tracked.
4264 type->ty_ProcType.et_ArgsType =
4265 RESOLVETYPE(type->ty_ProcType.et_ArgsType);
4266 type->ty_ProcType.et_RetType =
4267 RESOLVETYPEADJ(type->ty_ProcType.et_RetType, type);
4269 type->ty_AlignMask = 0;
4270 type->ty_Visibility = SCOPE_ALL_VISIBLE;
4274 * NOTE: Base storage is not tracked.
4276 type->ty_Bytes = type->ty_StorType.et_Bytes;
4277 /* XXX check pwr of 2 */
4279 type->ty_AlignMask = type->ty_Bytes - 1;
4280 type->ty_Visibility = SCOPE_ALL_VISIBLE;
4284 * NOTE: Tracking set by resolveType().
4286 type->ty_Flags &= ~TF_RESOLVING;
4287 type = resolveSuperClass(type);
4289 errorDottedId(otype->ty_UnresType.et_DottedId,
4290 "Unable to resolve class");
4294 type = RESOLVETYPE(type);
4295 type->ty_Flags |= TF_RESOLVING;
4296 /* visibility set by resolveSuperClass() */
4300 * NOTE: Tracking unknown (must be handled at run-time).
4302 type->ty_Visibility = SCOPE_ALL_VISIBLE;
4306 * NOTE: Storage is persistent, so wrapper is not tracked.
4308 type->ty_Visibility = SCOPE_ALL_VISIBLE; /* XXX */
4311 dpanic("Unknown type %d (type=%p)", type->ty_Op, type);
4314 type->ty_Flags &= ~TF_RESOLVING;
4315 type->ty_Flags |= TF_RESOLVED;
4317 do2 = resolveSemGroup2(sg, flags);
4319 resolveSemGroup3(sg, flags);
4323 * Resolve tracking flags so the run-time can take appropriate
4327 if (sg->sg_Flags & SGF_HASASS)
4328 type->ty_Flags |= TF_HASASS;
4330 type->ty_Flags |= TF_HASLVPTR;
4331 if (sg->sg_Flags & SGF_VARARGS)
4332 type->ty_Flags |= TF_HASLVPTR; /* XXX TF_VARARGS */
4334 type->ty_Flags |= TF_HASCONSTRUCT;
4336 type->ty_Flags |= TF_HASDESTRUCT;
4338 * Combine constructor/destructor hint flags for globals
4339 * because we have just one linked list for global constructors
4340 * and destructors (no need to optimize heavily).
4343 type->ty_Flags |= TF_HASGCONSTRUCT|TF_HASGDESTRUCT;
4347 * Resolve the default expression for the type, if any.
4349 * XXX qualified types just copy the exp. bad bad YYY
4351 * YYY resolveExp() no ISG (import sem group)
4353 if (type->ty_AssExp) {
4354 if ((type->ty_AssExp->ex_Flags & EXF_RESOLVED) == 0) {
4355 type->ty_AssExp = resolveExp(NULL, sg, type->ty_AssExp,
4357 flags | RESOLVE_AUTOCAST);
4359 type->ty_Flags |= TF_HASASS;
4363 * If adjtype is non-NULL it must be moved to the new type's QList.
4365 if (adjtype && type != otype) {
4366 if (adjtype->ty_SQList)
4367 RUNE_REMOVE(adjtype->ty_SQList, adjtype, ty_Node);
4368 adjtype->ty_SQList = &type->ty_QList;
4369 RUNE_INSERT_TAIL(adjtype->ty_SQList, adjtype, ty_Node);
4373 * ty_DynamicVector is nominally used when a Rune binary is run, but
4374 * we also need to set up enough of it such that mixed interpretation
4375 * and execution, or even just straight interpretation, works. This
4376 * is because the interpreter calls into libruntime.
4378 type->ty_DynamicVector = DefaultDynamicVector;
4381 * Internal types may be implied during resolution, be sure to
4382 * completely resolve its alignment too.
4384 * (If not internal we have to wait because there might be recursive
4385 * dependencies on the type).
4387 if (type->ty_Flags & TF_ISINTERNAL) {
4388 runesize_t dummy = 0;
4389 resolveStorageTypeExpAlign(type, &dummy, 0);
4396 * resolveSuperClass() - resolve an unresolved dotted id sequence into a class
4398 * Unresolved type identifier sequences must be resolved. We are also
4399 * responsible for setting the visibility of the type's elements.
4402 resolveSuperClass(Type *super)
4407 int visibility = SCOPE_ALL_VISIBLE;
4410 dassert_type(super, super->ty_Op == TY_UNRESOLVED);
4412 dottedId = super->ty_UnresType.et_DottedId;
4413 sg = super->ty_UnresType.et_SemGroup;
4415 d = FindDeclPath(NULL, super->ty_UnresType.et_ImportSemGroup,
4417 dottedId, FDC_NULL, &visibility, -1, &eno);
4422 * Resolve the unresolved type. Note that this occurs during class
4423 * resolution and we can't call resolveType() here without getting into
4424 * a loop, so we do not yet know storage requirements (ty_Bytes and
4429 sg = d->d_ClassDecl.ed_SemGroup;
4430 super->ty_Op = TY_CLASS;
4431 super->ty_ClassType.et_SemGroup = sg;
4432 super->ty_ClassType.et_Super = d->d_ClassDecl.ed_Super;
4433 super->ty_Visibility = visibility;
4434 if (super->ty_SQList)
4435 RUNE_REMOVE(super->ty_SQList, super, ty_Node);
4436 super->ty_SQList = &sg->sg_ClassList;
4437 RUNE_INSERT_TAIL(super->ty_SQList, super, ty_Node);
4438 dassert(visibility);
4440 * XXX should we move the class from the unresolved list to
4441 * the new SemGroup's actual list?
4446 * Adjust super instead of allocating a new super, so all
4447 * other references to super using this class path get
4451 dassert_type(super, d->d_TypedefDecl.ed_Type != super);
4453 d->d_TypedefDecl.ed_Type,
4456 d->d_TypedefDecl.ed_Type->ty_SQFlags,
4460 super->ty_Visibility = visibility;
4463 errorDottedId(dottedId, "identifier is not a class or typedef");
4464 dassert_type(super, 0);
4470 * Resolve the declarations in a semantic group. We have to do this if
4471 * (a) The declaration(s) would not otherwise be resolved by our statement
4472 * scan, or (b) We need definitive size/alignment information now rather
4475 * Also resolve SemGroup global initialization dependencies via SemGroupDepend.
4477 * SemGroup resolution occurs in three stages in order to deal with
4478 * resolver loops. The first stage does just enough to figure out
4479 * how large the non-global part of the SemGroup is (e.g. doesn't run
4480 * through pointers). The second stage handles global elements, and the
4481 * third stage completes the process.
4483 * NOTE! This code does not resolve declarations related to executable
4484 * semantic groups, such as sub-blocks within a procedure, but it does
4485 * have to resolve procedure definitions found in Class's and such.
4487 * NOTE! This code handles the last stage of subclass refinement, by
4488 * checking the validity of the refinement and setting sg_Compat properly.
4492 resolveSemGroup1(SemGroup *sg, int flags)
4498 flags &= ~RESOLVE_AUTOCAST; /* not applicable to this function */
4500 dep = resolvePushSGDepend(sg);
4501 if (sg->sg_Flags & SGF_RESOLVED) {
4502 resolvePopSGDepend(dep);
4505 if (sg->sg_Flags & SGF_RESOLVING) {
4507 "Unable to resolve embedded recursive reference\n");
4508 dassert_semgrp(sg, (sg->sg_Flags & SGF_RESOLVING) == 0);
4510 sg->sg_Flags |= SGF_RESOLVING;
4513 * First pass - resolve storage only. Note that this specifically
4514 * does not try to handle the multiple semantic layers inside a
4515 * procedure. See ResolveStorage() for that.
4517 RUNE_FOREACH(d, &sg->sg_DeclList, d_Node) {
4526 * Deal with constructor/destructor chaining.
4528 if (d->d_ScopeFlags & SCOPE_GLOBAL) {
4529 if ((d->d_Flags & DF_ONGLIST) == 0 &&
4530 (d->d_ScopeFlags & (SCOPE_CONSTRUCTOR |
4531 SCOPE_DESTRUCTOR))) {
4532 d->d_GNext = d->d_MyGroup->sg_GBase;
4533 d->d_MyGroup->sg_GBase = d;
4534 d->d_Flags |= DF_ONGLIST;
4537 if ((d->d_Flags & DF_ONCLIST) == 0 &&
4538 (d->d_ScopeFlags & SCOPE_CONSTRUCTOR)) {
4539 d->d_CNext = d->d_MyGroup->sg_CBase;
4540 d->d_MyGroup->sg_CBase = d;
4541 d->d_Flags |= DF_ONCLIST;
4543 if ((d->d_Flags & DF_ONDLIST) == 0 &&
4544 (d->d_ScopeFlags & SCOPE_DESTRUCTOR)) {
4545 d->d_DNext = d->d_MyGroup->sg_DBase;
4546 d->d_MyGroup->sg_DBase = d;
4547 d->d_Flags |= DF_ONDLIST;
4551 case DOP_STACK_STORAGE:
4553 * can't happen. Stack storage is only used in
4554 * executable contexts.
4557 case DOP_ARGS_STORAGE:
4558 case DOP_GROUP_STORAGE:
4559 type = d->d_StorDecl.ed_Type;
4561 switch(type->ty_Op) {
4563 d->d_Bytes = sizeof(void *);
4564 d->d_AlignMask = POINTER_ALIGN;
4565 if ((d->d_Scope.s_Flags & SCOPE_ALIGN) &&
4566 d->d_Scope.s_AlignOverride) {
4568 d->d_Scope.s_AlignOverride - 1;
4573 if (d->d_ScopeFlags & SCOPE_LVALUE) {
4575 * NOTE: d->d_Bytes is different from
4576 * the size of the underlying
4577 * type that the LValueStor
4580 dassert(d->d_Op == DOP_ARGS_STORAGE);
4581 d->d_Bytes = sizeof(LValueStor);
4582 d->d_AlignMask = LVALUE_ALIGN;
4584 d->d_Bytes = sizeof(PointerStor);
4585 d->d_AlignMask = POINTER_ALIGN;
4587 if ((d->d_Scope.s_Flags & SCOPE_ALIGN) &&
4588 d->d_Scope.s_AlignOverride) {
4590 d->d_Scope.s_AlignOverride - 1;
4594 resolveDecl(d, flags);
4597 if (sg->sg_AlignMask < d->d_AlignMask)
4598 sg->sg_AlignMask = d->d_AlignMask;
4599 sg->sg_Bytes = (sg->sg_Bytes + d->d_AlignMask) &
4601 d->d_Offset = sg->sg_Bytes;
4602 if (d->d_Op == DOP_ARGS_STORAGE) {
4603 if (d->d_ScopeFlags & SCOPE_UNLOCKED)
4604 d->d_Storage = GENSTAT_REFD;
4605 else if (d->d_ScopeFlags & SCOPE_HARD)
4606 d->d_Storage = GENSTAT_LOCKH;
4608 d->d_Storage = GENSTAT_LOCK;
4610 d->d_Storage = GENSTAT_REFD;
4612 sg->sg_Bytes += d->d_Bytes;
4613 if (d->d_StorDecl.ed_AssExp)
4614 sg->sg_Flags |= SGF_HASASS;
4615 if (type->ty_Flags & TF_HASASS)
4616 sg->sg_Flags |= SGF_HASASS;
4617 if (type->ty_Flags & TF_HASLVPTR)
4618 sg->sg_Flags |= SGF_HASLVPTR;
4620 case DOP_GLOBAL_STORAGE:
4621 /* handled in pass2 */
4624 dassert_semgrp(sg, 0);
4629 * Rollup &obj into a SemGroup flag.
4631 if (d->d_Flags & DF_ADDRUSED) {
4632 sg->sg_Flags |= SGF_ADDRUSED;
4633 fprintf(stderr, "RESOLVER ADDRUSED %s\n", d->d_Id);
4641 sg->sg_Bytes = (sg->sg_Bytes + sg->sg_AlignMask) & ~sg->sg_AlignMask;
4642 sg->sg_Flags |= SGF_RESOLVED;
4643 resolvePopSGDepend(dep);
4649 * Followup - resolve globals
4653 resolveSemGroup2(SemGroup *sg, int flags)
4658 flags &= ~RESOLVE_AUTOCAST; /* not applicable to this function */
4660 if (sg->sg_Flags & SGF_GRESOLVED)
4662 if (sg->sg_Flags & SGF_GRESOLVING) {
4664 "Unable to resolve embedded recursive reference\n");
4665 dassert_semgrp(sg, (sg->sg_Flags & SGF_GRESOLVING) == 0);
4667 sg->sg_Flags |= SGF_GRESOLVING;
4670 * First pass - resolve storage only. Note that this specifically
4671 * does not try to handle the multiple semantic layers inside a
4672 * procedure. See ResolveStorage() for that.
4674 RUNE_FOREACH(d, &sg->sg_DeclList, d_Node) {
4682 case DOP_STACK_STORAGE:
4684 * can't happen. Stack storage is only used in
4685 * executable contexts.
4688 case DOP_ARGS_STORAGE:
4689 case DOP_GROUP_STORAGE:
4691 * Non-globals were handled in pass-1
4694 case DOP_GLOBAL_STORAGE:
4696 * Global storage must be handled in pass-2
4698 type = d->d_StorDecl.ed_Type;
4700 switch(type->ty_Op) {
4702 d->d_Bytes = sizeof(void *);
4703 d->d_AlignMask = POINTER_ALIGN;
4704 if ((d->d_Scope.s_Flags & SCOPE_ALIGN) &&
4705 d->d_Scope.s_AlignOverride) {
4707 d->d_Scope.s_AlignOverride - 1;
4712 d->d_Bytes = sizeof(PointerStor);
4713 d->d_AlignMask = POINTER_ALIGN;
4714 if ((d->d_Scope.s_Flags & SCOPE_ALIGN) &&
4715 d->d_Scope.s_AlignOverride) {
4717 d->d_Scope.s_AlignOverride - 1;
4721 resolveDecl(d, flags);
4724 if (sg->sg_GlobalAlignMask < d->d_AlignMask)
4725 sg->sg_GlobalAlignMask = d->d_AlignMask;
4726 sg->sg_GlobalBytes = (sg->sg_GlobalBytes +
4727 d->d_AlignMask) & ~d->d_AlignMask;
4728 d->d_Offset = sg->sg_GlobalBytes;
4729 d->d_Storage = GENSTAT_REFD;
4730 sg->sg_GlobalBytes += d->d_Bytes;
4731 if (d->d_StorDecl.ed_AssExp)
4732 sg->sg_Flags |= SGF_GHASASS;
4733 if (type->ty_Flags & TF_HASASS)
4734 sg->sg_Flags |= SGF_GHASASS;
4735 if (type->ty_Flags & TF_HASLVPTR)
4736 sg->sg_Flags |= SGF_GHASLVPTR;
4739 dassert_semgrp(sg, 0);
4747 sg->sg_GlobalBytes = (sg->sg_GlobalBytes + sg->sg_GlobalAlignMask) &
4748 ~sg->sg_GlobalAlignMask;
4749 sg->sg_Flags |= SGF_GRESOLVED;
4755 resolveSemGroup3(SemGroup *sg, int flags)
4760 flags &= ~RESOLVE_AUTOCAST; /* not applicable to this function */
4763 * 0 - reserved for dynamic initialization
4764 * 1 - reserved for dynamic destructor
4769 * Third pass, resolve non-storage entities after setting
4770 * SGF_RESOLVED, these entities may legally embed this class (if
4773 * Resolve pointers that were only partially resolved in the first
4776 * Refinements have been resolved but we have to check them for
4777 * legality and set sg_Compat.
4779 * Note that this is what allows us to typedef a subclass in its
4780 * superclass. The typedef itself is safe.
4782 * Also resolve storage pointer entities that were skipped in the
4783 * first pass. Such pointers could point to ourselves.
4785 * Finally, set SCOPE_UNLOCKED on any entity which does not
4786 * contain any lockable data (like int's).
4788 RUNE_FOREACH(d, &sg->sg_DeclList, d_Node) {
4790 * Final resolution of refinements.
4792 if (d->d_ScopeFlags & SCOPE_REFINE) {
4793 resolveDecl(d->d_Super, flags);
4794 resolveDecl(d, flags);
4795 RefineDeclaration(sg, d->d_Super, d);
4806 resolveDecl(d, flags);
4809 resolveDecl(d, flags);
4812 * For now internal generation does not need a
4813 * dynamic component (and doesn't generate external
4814 * code so the function wouldn't exist anyway).
4816 if (d->d_ScopeFlags & SCOPE_INTERNAL)
4820 * Assign the dynamic index. There may be multiple
4821 * entries for the same d_Id, they are ordered such
4822 * that refinements use the same DynIndex as in
4823 * the superclass which is what allows dynamic method
4824 * calls to work properly. All non-refined subclass
4825 * elements are ordered after all refined/non=refined
4826 * superclass elements (replacing the superclass
4827 * element and using the same DynIndex when refined).
4829 d->d_DynIndex = dyncount;
4832 case DOP_ARGS_STORAGE:
4833 case DOP_GROUP_STORAGE:
4834 /*case DOP_STACK_STORAGE:*/
4835 case DOP_GLOBAL_STORAGE:
4836 switch(d->d_StorDecl.ed_Type->ty_Op) {
4840 resolveDecl(d, flags);
4845 dassert_semgrp(sg, 0);
4851 * If no dynamic methods and no dynamic initialization or destruction
4852 * required, set dyncount to 0.
4854 if (dyncount == 2 &&
4855 (sg->sg_Flags & SGF_HASASS) == 0 &&
4856 sg->sg_SRBase == NULL &&
4857 sg->sg_CBase == NULL &&
4858 sg->sg_DBase == NULL) {
4861 sg->sg_DynCount = dyncount;
4862 sg->sg_Flags &= ~SGF_RESOLVING;
4866 * findExpOper() - Find operator declaration matching expression
4868 * Locate the operator declaration (a DOP_PROCDEF) that matches
4869 * the expression or NULL if no match could be found. The expression's
4870 * left and right hand sides must already be resolved.
4872 * NOTE! A temporary 'copy' Exp may be passed, not all fields are valid.
4874 static Declaration *testIConstantForType(Declaration *d, Type *type, Exp *exp);
4875 static Declaration *testFConstantForType(Declaration *d, Type *type, Exp *exp);
4879 findExpOper(Exp *exp, int flags)
4885 flags &= ~RESOLVE_AUTOCAST; /* not applicable to this function */
4887 if (exp->ex_Flags & EXF_BINARY) {
4888 rtype = exp->ex_Rhs->ex_Type;
4889 ltype = exp->ex_Lhs->ex_Type;
4891 dassert(exp->ex_Flags & EXF_UNARY);
4893 ltype = exp->ex_Lhs->ex_Type;
4897 * XXX look in our local semantic hierarchy for a compatible operator ?
4901 * Attempt to find a matching operator from the left hand side
4904 d = findOper(ltype, exp->ex_Id, ltype, rtype, flags);
4906 if (d || (exp->ex_Flags & EXF_BINARY) == 0)
4910 * Attempt to find a matching binary operator from the right hand
4913 d = findOper(rtype, exp->ex_Id, ltype, rtype, flags);
4916 * If that fails but either the left or right-hand sides are
4917 * constants, see if we can find an operator by casting the
4918 * constant to the non-constant.
4921 if (exp->ex_Rhs->ex_Token == TOK_INTEGER &&
4922 exp->ex_Lhs->ex_Token != TOK_INTEGER &&
4923 exp->ex_Lhs->ex_Token != TOK_FLOAT &&
4924 (ltype->ty_Flags & TF_ISINTEGER)) {
4925 d = findOper(ltype, exp->ex_Id, ltype, ltype, flags);
4927 d = testIConstantForType(d, ltype, exp->ex_Rhs);
4929 if (exp->ex_Lhs->ex_Token == TOK_INTEGER &&
4930 exp->ex_Rhs->ex_Token != TOK_INTEGER &&
4931 exp->ex_Rhs->ex_Token != TOK_FLOAT &&
4932 (rtype->ty_Flags & TF_ISINTEGER)) {
4933 d = findOper(rtype, exp->ex_Id, rtype, rtype, flags);
4935 d = testIConstantForType(d, rtype, exp->ex_Rhs);
4937 if (exp->ex_Rhs->ex_Token == TOK_FLOAT &&
4938 exp->ex_Lhs->ex_Token != TOK_INTEGER &&
4939 exp->ex_Lhs->ex_Token != TOK_FLOAT &&
4940 (ltype->ty_Flags & TF_ISFLOATING)) {
4941 d = findOper(ltype, exp->ex_Id, ltype, ltype, flags);
4943 d = testFConstantForType(d, ltype, exp->ex_Rhs);
4945 if (exp->ex_Lhs->ex_Token == TOK_FLOAT &&
4946 exp->ex_Rhs->ex_Token != TOK_INTEGER &&
4947 exp->ex_Rhs->ex_Token != TOK_FLOAT &&
4948 (rtype->ty_Flags & TF_ISFLOATING)) {
4949 d = findOper(rtype, exp->ex_Id, rtype, rtype, flags);
4951 d = testFConstantForType(d, rtype, exp->ex_Rhs);
4959 * Calculate whether the constant can be safely cast. If it can,
4960 * cast the constant and return d. Otherwise complain and return
4965 testIConstantForType(Declaration *d, Type *type, Exp *exp)
4967 int64_t v = resolveGetConstExpInt64(exp);
4969 if (type->ty_Flags & TF_ISUNSIGNED) {
4970 switch(type->ty_Bytes) {
4972 if (v != (int64_t)(uint8_t)v)
4976 if (v != (int64_t)(uint16_t)v)
4980 if (v != (int64_t)(uint32_t)v)
4989 switch(type->ty_Bytes) {
4991 if (v != (int64_t)(int8_t)v)
4995 if (v != (int64_t)(int16_t)v)
4999 if (v != (int64_t)(int32_t)v)
5010 * If successful change the constant's type and reset the
5011 * interpreter to re-evaluate it.
5014 exp->ex_Type = type;
5015 exp->ex_Run = RunUnresolvedExp;
5016 exp->ex_Run64 = Run64DefaultExp;
5018 ExpPrintError(exp, TOK_ERR_AUTOCAST_VALUE);
5025 testFConstantForType(Declaration *d, Type *type, Exp *exp)
5027 float128_t v = resolveGetConstExpFloat128(exp);
5029 switch(type->ty_Bytes) {
5031 if (v != (float32_t)v)
5035 if (v != (float64_t)v)
5043 * If successful change the constant's type and reset the
5044 * interpreter to re-evaluate it.
5047 exp->ex_Type = type;
5048 exp->ex_Run = RunUnresolvedExp;
5049 exp->ex_Run64 = Run64DefaultExp;
5051 ExpPrintError(exp, TOK_ERR_AUTOCAST_VALUE);
5058 findOper(Type *btype, string_t id, Type *ltype, Type *rtype, int flags)
5062 int args = (rtype != NULL) ? 2 : 1;
5064 flags &= ~RESOLVE_AUTOCAST; /* not applicable to this function */
5067 * Locate the base type. If the base type does not have a SemGroup
5068 * there are no operators. (XXX put system operators here)
5070 sg = BaseType(&btype);
5076 * Look for the operator in the SemGroup
5078 for (d = FindOperId(sg, id, args); d; d = d->d_ONext) {
5079 resolveDecl(d, flags);
5080 if (d->d_MyGroup == sg &&
5081 d->d_Op == DOP_PROC &&
5082 d->d_ProcDecl.ed_OperId == id &&
5083 MatchOperatorTypes(d, ltype, rtype)
5090 * Failed. If the base type is a compound type, look for the
5091 * operator in the SemGroup for each element making up the compound
5092 * type. e.g. so (mycustomtype, double) would find the operator
5095 if (btype->ty_Op == TY_COMPOUND) {
5096 RUNE_FOREACH(d, &sg->sg_DeclList, d_Node) {
5098 if (d->d_Op & DOPF_STORAGE) {
5099 d2 = findOper(d->d_StorDecl.ed_Type, id,
5100 ltype, rtype, flags);
5101 } else if (d->d_Op == DOP_TYPEDEF) {
5102 d2 = findOper(d->d_TypedefDecl.ed_Type, id,
5103 ltype, rtype, flags);
5115 errorDottedId(string_t *ary, const char *ctl, ...)
5121 vfprintf(stderr, ctl, va);
5123 fprintf(stderr, ": %s", ary[0]);
5124 for (i = 1; ary[i]; ++i)
5125 fprintf(stderr, ".%s", ary[i]);
5126 fprintf(stderr, "\n");
5130 * Resolve the alignment requirements for SemGroups related to
5131 * statements, including the alignment requirements needed for
5132 * temporary expression space.
5135 ResolveAlignment(Stmt *st, int flags)
5137 SemGroup *sg = st->st_MyGroup;
5140 if (st->st_Flags & STF_ALIGNRESOLVED)
5142 st->st_Flags |= STF_ALIGNRESOLVED;
5145 * If this is an executable semantic layer or an import layer then
5146 * assign storage to declarations up-front. Of the various
5147 * DOP_*_STORAGE ops, we should only see DOP_STACK_STORAGE and
5148 * DOP_GLOBAL_STORAGE.
5150 * Note: if this is the root ST_Import STF_SEMANTIC is *NOT* set and
5153 if ((st->st_Flags & STF_SEMANTIC) && st->st_Op != ST_Class) {
5157 * Pre-scan for alignment. Don't try to propagate the
5158 * alignment to the parent for now as that would require
5159 * recalculating the parent(s).
5161 RUNE_FOREACH(d, &sg->sg_DeclList, d_Node) {
5163 case DOP_STACK_STORAGE:
5164 case DOP_ARGS_STORAGE:
5165 case DOP_GROUP_STORAGE:
5166 if (sg->sg_AlignMask < d->d_AlignMask)
5167 sg->sg_AlignMask = d->d_AlignMask;
5169 case DOP_GLOBAL_STORAGE:
5170 if (sg->sg_GlobalAlignMask < d->d_AlignMask)
5171 sg->sg_GlobalAlignMask = d->d_AlignMask;
5190 d = st->st_TypedefStmt.es_Decl;
5191 resolveStorageDeclExpAlign(d,
5192 &sg->sg_TmpAlignMask,
5198 * NOTE: Don't calculate for declarations that belong in
5199 * a different context.
5205 d = st->st_DeclStmt.es_Decl;
5207 for (i = 0; i < st->st_DeclStmt.es_DeclCount; ++i) {
5208 if (st->st_MyGroup == d->d_MyGroup)
5209 resolveStorageDeclExpAlign(d,
5210 &sg->sg_TmpAlignMask,
5212 d = RUNE_NEXT(d, d_Node);
5224 if (st->st_LoopStmt.es_BCond) {
5225 resolveStorageExpAlign(st->st_LoopStmt.es_BCond,
5226 &sg->sg_TmpAlignMask,
5229 if (st->st_LoopStmt.es_ACond) {
5230 resolveStorageExpAlign(st->st_LoopStmt.es_ACond,
5231 &sg->sg_TmpAlignMask,
5234 if (st->st_LoopStmt.es_AExp) {
5235 resolveStorageExpAlign(st->st_LoopStmt.es_AExp,
5236 &sg->sg_TmpAlignMask,
5246 resolveStorageExpAlign(st->st_IfStmt.es_Exp,
5247 &sg->sg_TmpAlignMask,
5251 if (st->st_RetStmt.es_Exp)
5252 resolveStorageExpAlign(st->st_RetStmt.es_Exp,
5253 &sg->sg_TmpAlignMask,
5257 if (st->st_ResStmt.es_Exp)
5258 resolveStorageExpAlign(st->st_ResStmt.es_Exp,
5259 &sg->sg_TmpAlignMask,
5264 * The switch expression's temporary data must be saved while
5265 * we are executing the sub-statements (the cases).
5267 resolveStorageExpAlign(st->st_SwStmt.es_Exp,
5268 &sg->sg_TmpAlignMask,
5272 if (st->st_CaseStmt.es_Exp)
5273 resolveStorageExpAlign(st->st_CaseStmt.es_Exp,
5274 &sg->sg_TmpAlignMask,
5278 resolveStorageExpAlign(st->st_ExpStmt.es_Exp,
5279 &sg->sg_TmpAlignMask,
5282 case ST_ThreadSched:
5285 dassert_stmt(st, 0);
5289 * Calculate storage requirements for substatements. offset
5290 * acts as our base. We union the storage for the substatements
5291 * together. Note that often scan->sg_MyGroup == sg.
5293 RUNE_FOREACH(scan, &st->st_List, st_Node) {
5294 if (scan->st_Op == ST_Class) {
5295 ResolveAlignment(scan, flags);
5296 } else if (scan->st_Op == ST_Decl &&
5297 scan->st_DeclStmt.es_Decl->d_MyGroup !=
5303 } else if (scan->st_Op == ST_Decl &&
5304 (scan->st_DeclStmt.es_Decl->d_Flags & DF_RESOLVED)) {
5306 * See prior comments, skip declarations that
5307 * were moved to another context
5309 * (already resolved so can use junk offsets)
5311 resolveStorageDeclExpAlign(scan->st_DeclStmt.es_Decl,
5312 &sg->sg_TmpAlignMask,
5314 } else if (scan->st_Op == ST_Proc &&
5315 scan->st_ProcStmt.es_Decl->d_ProcDecl.ed_OrigBody == scan
5317 /* Do not resolve template procedures! */
5318 } else if (scan->st_Flags & STF_SEMTOP) {
5319 ResolveAlignment(scan, flags);
5321 ResolveAlignment(scan, flags);
5326 * If this is a new semantic level call resolveStorageSemGroup() to
5327 * do the final cleanup of SemGroup issues. This will redundantly
5328 * calculate temporary space requirements. Also, due to type/class
5329 * references the temporary space for a class may have already been
5330 * resolved. Since a class can only contain declarations it had
5331 * better match what we calculate here.
5333 * Note that for non-Class executable SemGroup's TmpBytes is
5334 * incorporated in a downward fashion while sg_Bytes is incorporated
5335 * in an upward fashion. It can become quite confusing. Don't ask
5336 * me why I did it that way.
5338 if (st->st_Flags & STF_SEMANTIC) {
5339 if ((sg->sg_Flags & SGF_TMPRESOLVED) == 0) {
5340 resolveStorageSemGroupAlign(sg, flags);
5345 * Propagate alignment requirements upward.
5347 if ((st->st_Flags & (STF_SEMANTIC|STF_SEMTOP)) == STF_SEMANTIC) {
5348 if (sg->sg_Parent->sg_AlignMask < sg->sg_AlignMask)
5349 sg->sg_Parent->sg_AlignMask = sg->sg_AlignMask;
5350 if (sg->sg_Parent->sg_TmpAlignMask < sg->sg_TmpAlignMask)
5351 sg->sg_Parent->sg_TmpAlignMask = sg->sg_TmpAlignMask;
5356 * ResolveStorage() - Final storage resolution pass
5358 * This pass carefully scans the SemGroup hierarchy and assigns
5359 * offsets to declarations.
5361 * PROCEDURES - all the various 'executable' semantic layers in
5362 * a procedure are collapsed together for efficiency, so we only
5363 * have to manage one context. This means that the d_Offset
5364 * assigned to declarations in sub-blocks may exceed the sg_ size
5365 * of the sub-block's SemGroup. We do not attempt to resolve
5366 * procedure body templates (d_ProcDecl.ed_OrigBody).
5368 * CLASSES - are given offsets in their SemGroup's relative to 0, if
5369 * not already resolved.
5371 * IMPORTS - are given offsets in their SemGroup's relative to 0
5373 * COMPOUND TYPES - (such as procedure arguments) are given offsets
5374 * in their SemGroup's relative to 0.
5376 * TEMPORARY STORAGE - expressions may require temporary storage
5377 * for intermediate results. That space is reserved here.
5379 * We specifically do not resolve unrelated storage.
5383 ResolveStorage(Stmt *st, int flags)
5388 runesize_t ngoffset;
5389 SemGroup *sg = st->st_MyGroup;
5394 if (st->st_Op != ST_Class) {
5395 dassert((st->st_Flags & STF_RESOLVING) == 0);
5396 if (st->st_Flags & STF_RESOLVED) {
5399 st->st_Flags |= STF_RESOLVING;
5402 dassert(st->st_Flags & STF_ALIGNRESOLVED);
5403 if (st->st_Flags & STF_TMPRESOLVED)
5405 st->st_Flags |= STF_TMPRESOLVED;
5408 * If this is an executable semantic layer or an import layer then
5409 * assign storage to declarations up-front. Of the various
5410 * DOP_*_STORAGE ops, we should only see DOP_STACK_STORAGE and
5411 * DOP_GLOBAL_STORAGE.
5413 * Note: if this is the root ST_Import STF_SEMANTIC is *NOT* set and
5416 if ((st->st_Flags & STF_SEMANTIC) && st->st_Op != ST_Class) {
5419 dassert((sg->sg_Flags & (SGF_FRESOLVED|SGF_FRESOLVING)) == 0);
5421 sg->sg_Flags |= SGF_FRESOLVING;
5424 * The base offset for sub-semantic-blocks must match the
5425 * alignment they require in order to allow us to do an
5426 * aligned BZEROing of the space. We do not include the
5427 * temporary space here (it does not need to be BZERO'd).
5429 * NOTE: sg_TmpAlignMask is taken into accoun when the
5430 * top-level frame is allocated.
5432 if (st->st_Flags & STF_SEMTOP) {
5433 dassert(sg->sg_Bytes == 0);
5436 offset = sg->sg_Parent->sg_Bytes;
5437 offset = (offset + sg->sg_AlignMask) &
5441 sg->sg_BlkOffset = offset;
5443 RUNE_FOREACH(d, &sg->sg_DeclList, d_Node) {
5445 case DOP_STACK_STORAGE:
5446 case DOP_ARGS_STORAGE:
5447 case DOP_GROUP_STORAGE:
5448 type = d->d_StorDecl.ed_Type;
5449 offset = (offset + d->d_AlignMask) &
5451 dassert_decl(d, d->d_Offset == (runesize_t)-1);
5452 d->d_Offset = offset;
5453 if (d->d_Op == DOP_STACK_STORAGE ||
5454 d->d_Op == DOP_ARGS_STORAGE) {
5455 if (d->d_ScopeFlags & SCOPE_UNLOCKED)
5456 d->d_Storage = GENSTAT_REFD;
5457 else if (d->d_ScopeFlags & SCOPE_HARD)
5458 d->d_Storage = GENSTAT_LOCKH;
5460 d->d_Storage = GENSTAT_LOCK;
5462 d->d_Storage = GENSTAT_REFD;
5464 offset += d->d_Bytes;
5465 if (d->d_StorDecl.ed_AssExp)
5466 sg->sg_Flags |= SGF_HASASS;
5467 if (type->ty_Flags & TF_HASASS)
5468 sg->sg_Flags |= SGF_HASASS;
5469 if (type->ty_Flags & TF_HASLVPTR)
5470 sg->sg_Flags |= SGF_HASLVPTR;
5472 case DOP_GLOBAL_STORAGE:
5473 type = d->d_StorDecl.ed_Type;
5474 sg->sg_GlobalBytes =
5475 (sg->sg_GlobalBytes + d->d_AlignMask) &
5477 dassert_decl(d, d->d_Offset == (runesize_t)-1);
5478 d->d_Offset = sg->sg_GlobalBytes;
5479 d->d_Storage = GENSTAT_REFD;
5480 sg->sg_GlobalBytes += d->d_Bytes;
5481 if (d->d_StorDecl.ed_AssExp)
5482 sg->sg_Flags |= SGF_GHASASS;
5483 if (type->ty_Flags & TF_HASASS)
5484 sg->sg_Flags |= SGF_GHASASS;
5485 if (type->ty_Flags & TF_HASLVPTR)
5486 sg->sg_Flags |= SGF_GHASLVPTR;
5494 * The byte size of the block does not have to be aligned,
5495 * but aligning it (within reason) might provide a benefit.
5497 sg->sg_Bytes = offset;
5500 if (sg->sg_AlignMask < 256) {
5501 sg->sg_Bytes = (offset + sg->sg_AlignMask) &
5504 if (sg->sg_GlobalAlignMask < 256) {
5505 sg->sg_GlobalBytes =
5506 (sg->sg_GlobalBytes + sg->sg_GlobalAlignMask) &
5507 ~sg->sg_GlobalAlignMask;
5510 sg->sg_BlkBytes = sg->sg_Bytes - sg->sg_BlkOffset;
5511 sg->sg_Flags |= SGF_FRESOLVED;
5512 sg->sg_Flags &= ~SGF_FRESOLVING;
5516 * Figure out how much temporary space we need to be able to execute
5517 * statements and expressions. Temporary space, like the main
5518 * procedural space, must be inherited from and consolidated into
5519 * the top-level SemGroup
5522 offset = sg->sg_TmpBytes;
5524 goffset = sg->sg_GlobalTmpBytes;
5528 * Root ST_Import. avoid compiler warnings
5538 if (st->st_ImportStmt.es_DLL) {
5539 void (*func)(void) = dlsym(st->st_ImportStmt.es_DLL,
5550 resolveStorageDeclExp(st->st_TypedefStmt.es_Decl,
5551 &noffset, &ngoffset);
5556 * Temporary space for declarations are handled here.
5558 * Resolve declarations, skipping any whos context was
5559 * moved to a class (e.g. a declaration at the top level
5560 * of a file like Fd.setfd(...) also exists in the Fd class).
5566 d = st->st_DeclStmt.es_Decl;
5568 if (d->d_Op == DOP_GLOBAL_STORAGE)
5569 st->st_DeclStmt.es_TmpOffset = goffset;
5571 st->st_DeclStmt.es_TmpOffset = offset;
5572 printf("STDECLTMPOFFSET %zd\n", offset);
5573 for (i = 0; i < st->st_DeclStmt.es_DeclCount; ++i) {
5574 runesize_t xoffset = offset;
5575 runesize_t xgoffset = goffset;
5578 if (st->st_MyGroup != d->d_MyGroup) {
5579 /*printf("SKIPB %s\n", d->d_Id)*/;
5580 resolveStorageDeclExp(d, &xoffset, &xgoffset);
5581 } else if (d->d_Flags & DF_RESOLVED) {
5582 resolveStorageDeclExp(d, &xoffset, &xgoffset);
5586 resolveStorageDeclExp(
5591 if (noffset < xoffset)
5593 if (ngoffset < xgoffset)
5594 ngoffset = xgoffset;
5595 d = RUNE_NEXT(d, d_Node);
5609 if (st->st_LoopStmt.es_BCond) {
5611 resolveStorageExp(st->st_LoopStmt.es_BCond,
5613 if (noffset < xoffset)
5616 if (st->st_LoopStmt.es_ACond) {
5618 resolveStorageExp(st->st_LoopStmt.es_ACond,
5620 if (noffset < xoffset)
5623 if (st->st_LoopStmt.es_AExp) {
5625 resolveStorageExp(st->st_LoopStmt.es_AExp,
5627 if (noffset < xoffset)
5637 resolveStorageExp(st->st_IfStmt.es_Exp, &noffset);
5640 if (st->st_RetStmt.es_Exp)
5641 resolveStorageExp(st->st_RetStmt.es_Exp, &noffset);
5644 if (st->st_ResStmt.es_Exp)
5645 resolveStorageExp(st->st_ResStmt.es_Exp, &noffset);
5649 * The switch expression's temporary data must be saved while
5650 * we are executing the sub-statements (the cases).
5652 resolveStorageExp(st->st_SwStmt.es_Exp, &noffset);
5657 if (st->st_CaseStmt.es_Exp)
5658 resolveStorageExp(st->st_CaseStmt.es_Exp, &noffset);
5661 resolveStorageExp(st->st_ExpStmt.es_Exp, &noffset);
5663 case ST_ThreadSched:
5666 dassert_stmt(st, 0);
5670 * Calculate storage requirements for substatements. offset
5671 * acts as our base. We union the storage for the substatements
5672 * together. Note that often scan->sg_MyGroup == sg.
5674 RUNE_FOREACH(scan, &st->st_List, st_Node) {
5675 dassert(scan->st_Op != ST_Proc);
5676 if (scan->st_Op == ST_Class) {
5677 ResolveStorage(scan, flags);
5679 } else if (scan->st_Op == ST_Decl &&
5680 scan->st_DeclStmt.es_Decl->d_MyGroup !=
5683 * See prior comments, skip declarations that
5684 * were moved to another context.
5686 * (does not belong in context so can use
5689 runesize_t junk1 = 0;
5690 runesize_t junk2 = 0;
5692 printf("SKIPC %s\n",
5693 scan->st_DeclStmt.es_Decl->d_Id);
5695 resolveStorageDeclExp(scan->st_DeclStmt.es_Decl,
5697 } else if (scan->st_Op == ST_Decl &&
5698 (scan->st_DeclStmt.es_Decl->d_Flags & DF_RESOLVED)) {
5700 * See prior comments, skip declarations that
5701 * were moved to another context
5703 * (already resolved so can use junk offsets)
5705 runesize_t junk1 = 0;
5706 runesize_t junk2 = 0;
5708 printf("SKIPD %s\n",
5709 scan->st_DeclStmt.es_Decl->d_Id);
5711 runesize_t save_offset;
5712 runesize_t save_goffset;
5713 save_offset = scan->st_MyGroup->sg_TmpBytes;
5714 save_goffset = scan->st_MyGroup->sg_GlobalTmpBytes;
5715 scan->st_MyGroup->sg_TmpBytes = offset;
5716 scan->st_MyGroup->sg_GlobalTmpBytes = goffset;
5717 resolveStorageDeclExp(scan->st_DeclStmt.es_Decl,
5719 if (scan->st_MyGroup->sg_TmpBytes < save_offset)
5720 scan->st_MyGroup->sg_TmpBytes = save_offset;
5721 if (scan->st_MyGroup->sg_GlobalTmpBytes < save_goffset) {
5722 scan->st_MyGroup->sg_GlobalTmpBytes = save_goffset;
5724 if (noffset < scan->st_MyGroup->sg_TmpBytes)
5725 noffset = scan->st_MyGroup->sg_TmpBytes;
5726 if (ngoffset < scan->st_MyGroup->sg_GlobalTmpBytes)
5727 ngoffset = scan->st_MyGroup->sg_GlobalTmpBytes;
5729 } else if (scan->st_Op == ST_Proc) {
5730 /* Do not resolve template procedures! */
5731 fprintf(stderr, "STORAGE %s\n", scan->st_ProcStmt.es_Decl->d_Id);
5732 if (scan->st_ProcStmt.es_Decl->d_ProcDecl.ed_OrigBody == scan) {
5735 } else if (scan->st_Flags & STF_SEMTOP) {
5736 assert(scan->st_MyGroup != sg);
5737 ResolveStorage(scan, flags);
5740 * This is a bit of a mess. The baseline
5741 * sg_TmpBytes needs to be set so calculated
5742 * temporary offsets are relative to it, and
5743 * then restored. Otherwise we might blow
5744 * away the SGF_TMPRESOLVED SemGroup
5748 runesize_t save_offset;
5749 runesize_t save_goffset;
5750 save_offset = scan->st_MyGroup->sg_TmpBytes;
5751 save_goffset = scan->st_MyGroup->sg_GlobalTmpBytes;
5752 scan->st_MyGroup->sg_TmpBytes = offset;
5753 scan->st_MyGroup->sg_GlobalTmpBytes = goffset;
5754 ResolveStorage(scan, flags);
5756 if (scan->st_MyGroup->sg_TmpBytes < save_offset)
5757 scan->st_MyGroup->sg_TmpBytes = save_offset;
5758 if (scan->st_MyGroup->sg_GlobalTmpBytes < save_goffset) {
5759 scan->st_MyGroup->sg_GlobalTmpBytes = save_goffset;
5761 if (noffset < scan->st_MyGroup->sg_TmpBytes)
5762 noffset = scan->st_MyGroup->sg_TmpBytes;
5763 if (ngoffset < scan->st_MyGroup->sg_GlobalTmpBytes)
5764 ngoffset = scan->st_MyGroup->sg_GlobalTmpBytes;
5769 * If this is a new semantic level call resolveStorageSemGroup() to
5770 * do the final cleanup of SemGroup issues. This will redundantly
5771 * calculate temporary space requirements. Also, due to type/class
5772 * references the temporary space for a class may have already been
5773 * resolved. Since a class can only contain declarations it had
5774 * better match what we calculate here.
5776 * Note that for non-Class executable SemGroup's TmpBytes is
5777 * incorporated in a downward fashion while sg_Bytes is incorporated
5778 * in an upward fashion. It can become quite confusing. Don't ask
5779 * me why I did it that way.
5781 if (st->st_Flags & STF_SEMANTIC) {
5782 if ((sg->sg_Flags & SGF_TMPRESOLVED) == 0) {
5783 resolveStorageSemGroup(sg, noffset, ngoffset);
5785 dassert(sg->sg_TmpBytes == noffset &&
5786 sg->sg_GlobalTmpBytes == ngoffset);
5789 sg->sg_TmpBytes = noffset;
5790 sg->sg_GlobalTmpBytes = ngoffset;
5791 } /* else this is the Root st_Import */
5793 if ((st->st_Flags & (STF_SEMANTIC|STF_SEMTOP)) == STF_SEMANTIC) {
5794 sg->sg_Parent->sg_Bytes = sg->sg_Bytes;
5799 * resolveStorageDeclExp() - resolve the storage reservation required to
5800 * process an expression.
5802 * This is an expression tree traversal storage resolution procedure.
5803 * We have to traverse through declarations to get to default assignments
5806 * If a declaration has no assigned default the underlying type may
5807 * itself have an assigned default which must be dealt with.
5810 resolveStorageDeclExpAlign(Declaration *d, runesize_t *expalignp, int flags)
5814 /* recursion already dealt with */
5816 case DOP_ARGS_STORAGE:
5817 case DOP_STACK_STORAGE:
5818 case DOP_GROUP_STORAGE:
5820 Type *type = d->d_StorDecl.ed_Type;
5822 resolveStorageTypeExpAlign(type, expalignp, flags);
5823 if (d->d_StorDecl.ed_AssExp) {
5824 resolveStorageExpAlign(d->d_StorDecl.ed_AssExp,
5830 case DOP_GLOBAL_STORAGE:
5832 Type *type = d->d_StorDecl.ed_Type;
5834 resolveStorageTypeExpAlign(type, expalignp, flags);
5835 if (d->d_StorDecl.ed_AssExp) {
5836 resolveStorageExpAlign(d->d_StorDecl.ed_AssExp,
5844 * Never try to resolve storage considerations for an
5845 * alias's assignment in the declaration itself. The
5846 * run-time context depends on who and how many other
5847 * parts of the program reference the alias and the expression
5848 * tree will be duplicated for each.
5851 resolveStorageExpExp(d->d_AliasDecl.ed_AssExp, expalignp);
5855 /* XXX what about ty_AssExp ? should be in global space */
5858 /* recursion already dealt with */
5862 * Resolution of procedure declarations might have been
5863 * deferred (see TOK_ID in resolveExp()).
5869 if ((st = d->d_ProcDecl.ed_ProcBody) != NULL) {
5870 ResolveAlignment(st, 0);
5880 resolveStorageDeclExp(Declaration *d, runesize_t *offset, runesize_t *goffset)
5884 /* recursion already dealt with */
5886 case DOP_ARGS_STORAGE:
5887 case DOP_STACK_STORAGE:
5888 case DOP_GROUP_STORAGE:
5890 Type *type = d->d_StorDecl.ed_Type;
5891 runesize_t save_offset = *offset;
5893 resolveStorageType(type, &save_offset, 0);
5894 if (d->d_StorDecl.ed_AssExp) {
5895 resolveStorageExp(d->d_StorDecl.ed_AssExp,
5898 if (*offset < save_offset)
5899 *offset = save_offset;
5902 case DOP_GLOBAL_STORAGE:
5904 Type *type = d->d_StorDecl.ed_Type;
5905 runesize_t save_offset = *goffset;
5907 resolveStorageType(type, &save_offset, 1);
5908 if (d->d_StorDecl.ed_AssExp) {
5909 resolveStorageExp(d->d_StorDecl.ed_AssExp,
5912 if (*goffset < save_offset)
5913 *goffset = save_offset;
5918 * Never try to resolve storage considerations for an
5919 * alias's assignment in the declaration itself. The
5920 * run-time context depends on who and how many other
5921 * parts of the program reference the alias and the expression
5922 * tree will be duplicated for each.
5925 if (d->d_ScopeFlags & SCOPE_GLOBAL)
5926 resolveStorageExp(d->d_AliasDecl.ed_AssExp, NULL, NULL);
5928 resolveStorageExp(d->d_AliasDecl.ed_AssExp, NULL, NULL);
5932 /* XXX what about ty_AssExp ? should be in global space */
5935 /* recursion already dealt with */
5941 if ((st = d->d_ProcDecl.ed_ProcBody) != NULL) {
5942 ResolveStorage(st, 0);
5952 * resolveStorageExp() - resolve the temporary storage required to
5953 * support the expression, if any.
5955 * We do not need to assign storage for expressions which return
5956 * lvalues, because they will simply return a pointer into
5957 * non-temporary storage.
5960 resolveStorageExpOnly(Exp *exp, runesize_t *offset)
5965 * Stop if the expression resolves to a type rather then a value,
5966 * e.g. when you do something like switch (typeof(int)) { ... }
5967 * Types are handled as thin pointers.
5969 exp->ex_Flags |= EXF_TMPRESOLVED;
5970 if (exp->ex_Flags & EXF_RET_TYPE) {
5971 *offset = (*offset + POINTER_ALIGN - 1) & ~(POINTER_ALIGN - 1);
5972 exp->ex_TmpOffset = *offset;
5973 *offset += sizeof(void *);
5979 * Assign temporary offset. This offset does not overlap temporary
5980 * space reserved for sub-expressions.
5982 * We must have an assigned type. Expression sequences like:
5983 * 'module.blah' are collapsed into 'blah' long before we get
5984 * here, or they should be. We should not encounter any
5985 * TOK_TCMV_ID expression tokens. Structural id's (the right hand
5986 * side of X.Y) are resolved by their parent expression node and
5987 * no typing or temporary space is required.
5989 * Expressions that return lvalues do not need temporary space.
5991 type = exp->ex_Type;
5993 switch(exp->ex_Token) {
5998 printf("EXP %p %04x %p\n",
5999 exp, exp->ex_Token, exp->ex_Decl);
6000 dassert_exp(exp, 0);
6003 exp->ex_TmpOffset = -3;
6004 } else if (type->ty_SQFlags & SF_LVALUE) {
6006 * Expressive elements which return lvalues do not get
6007 * temporary space. Note that this also prevents lvalues
6008 * such as large arrays (int ary[999999999]) from reserving
6009 * unnecessary stack space.
6011 * NOTE: SF_LVALUE is unrelated to SCOPE_LVALUE. SCOPE_LVALUE
6012 * applies to SemGroup storage (LValueStor). SF_LVALUE
6013 * merely flags the type for an expression as expecting
6014 * or not expecting an lvalue.
6018 * XXX removeme, LValueStor only applies to semgroups
6020 runesize_t lvmask = sizeof(LValueStor) - 1;
6021 *offset = (*offset + lvmask) & ~lvmask;
6022 exp->ex_TmpOffset = *offset;
6023 *offset = *offset + (lvmask + 1);
6025 exp->ex_TmpOffset = -2;
6028 * Reserve temporary space for potential intermediate
6031 * Compound expressions may need extra space to default-init
6032 * the compound value, it is expected to be available to the
6033 * generator right after the nominal type in the TmpOffset.
6034 * XXX also make available to the interpreter?
6036 * Procedure calls also may need extra space to default-init
6037 * the return value. XXX also make available to the
6040 *offset = (*offset + type->ty_AlignMask) & ~type->ty_AlignMask;
6041 exp->ex_TmpOffset = *offset;
6042 *offset = *offset + type->ty_Bytes;
6043 if (exp->ex_Token == TOK_COMPOUND) {
6045 * NOTE: type might not yet be changed to compound,
6046 * but single-element compound will use the
6047 * same temporary space.
6049 /**offset += type->ty_TmpBytes;*/
6050 resolveStorageType(type, offset, 0);
6051 } else if (exp->ex_Token == TOK_CALL) {
6052 *offset += type->ty_TmpBytes;
6053 resolveStorageType(type, offset, 0);
6056 dassert(exp->ex_TmpOffset != -1);
6061 resolveStorageExpSub(Exp *exp, runesize_t *offset)
6065 * Early term. XXX don't do this. For the moment we have an issue
6066 * with how typeof() processes temporary expression storage. This
6067 * needs to be comprehensively fixed but it can be an issue if the
6068 * content is a dynamic type (via a ref or a var-args element)
6069 * so it is not trivial.
6071 if (exp->ex_Flags & EXF_RET_TYPE)
6075 resolveStorageType(exp->ex_Type, offset, 0);
6078 * Make sure resolved declarations have resolved temporary
6079 * storage for assigned expressions. XXX
6081 if (exp->ex_Token == TOK_ID || exp->ex_Token == TOK_CLASSID) {
6085 if (d && (d->d_Flags & DF_RESOLVED)) {
6086 resolveStorageDeclExp(d, offset, offset);
6088 /* note: UNARY can be set for aliases */
6092 * Calculate the overlapping temporary space for sub-trees.
6094 if (exp->ex_Flags & EXF_BINARY) {
6096 * Ensure lhs's NON-RECURSIVE temporary storage on-return
6097 * does not intefere with rhs's, or vise-versa.
6099 * To do this offset the rhs storage by the non-recursive
6107 resolveStorageExp(exp->ex_Lhs, &xoffset);
6108 if (*offset < xoffset)
6110 if (exp->ex_Lhs->ex_TmpOffset >= 0) {
6111 xoffset = exp->ex_Lhs->ex_TmpOffset +
6112 exp->ex_Lhs->ex_Type->ty_Bytes;
6116 resolveStorageExp(exp->ex_Rhs, &xoffset);
6117 if (*offset < xoffset)
6119 } else if (exp->ex_Flags & EXF_UNARY) {
6120 resolveStorageExp(exp->ex_Lhs, offset);
6121 dassert_exp(exp, exp->ex_Lhs->ex_Next == NULL);
6122 } else if (exp->ex_Flags & EXF_COMPOUND) {
6124 * each element will be copied into the compound storage
6125 * in turn, so we can union the temporary storage required
6132 for (scan = exp->ex_Lhs; scan; scan = scan->ex_Next) {
6133 runesize_t xoffset = *offset;
6135 dassert_exp(scan, scan->ex_Type != NULL);
6137 resolveStorageExp(scan, &xoffset);
6138 if (noffset < xoffset)
6145 if (exp->ex_Token == TOK_CALL && exp->ex_Lhs->ex_Decl) {
6146 Declaration *d = exp->ex_Lhs->ex_Decl;
6147 fprintf(stderr, "FIXUP CALL %s type %p\n", d->d_Id, d->d_ProcDecl.ed_Type);
6148 dassert(d->d_Op == DOP_PROC);
6149 resolveStorageType(d->d_ProcDecl.ed_Type, offset, 0);
6154 /* XXX what about alias assign-expressions */
6155 else if (exp->ex_Flags & EXF_ALIAS) {
6157 dassert_decl(exp->ex_Decl,
6158 (exp->ex_Decl->d_ScopeFlags & SCOPE_GLOBAL) == 0);
6160 resolveStorageExp(exp->ex_Decl->d_AliasDecl.ed_AssExp, offset);
6166 * [re]resolve temporary storage requirements.
6168 * WARNING! This may be called more than once if an expression requires
6169 * resolve-time interpretation to generate a constant. In this
6170 * ex_TmpOffset for the sub-chain may be regenerated from 0,
6171 * and then just the top-level (post-constant-resolved)
6172 * ex_TmpOffset will be restored by the caller.
6175 resolveStorageExp(Exp *exp, runesize_t *offset)
6181 noffset = resolveStorageExpOnly(exp, &xoffset);
6183 resolveStorageExpSub(exp, &xoffset);
6184 if (*offset < xoffset)
6189 resolveStorageExpAlign(Exp *exp, runesize_t *expalignp, int flags)
6193 if (exp->ex_Flags & EXF_RET_TYPE) {
6194 if (*expalignp < POINTER_ALIGN)
6195 *expalignp = POINTER_ALIGN;
6199 resolveDecl(exp->ex_Decl, 0);
6203 type = exp->ex_Type;
6209 if (type->ty_SQFlags & SF_LVALUE) {
6210 if (*expalignp < POINTER_ALIGN)
6211 *expalignp = POINTER_ALIGN;
6213 if (*expalignp < type->ty_AlignMask)
6214 *expalignp = type->ty_AlignMask;
6216 resolveStorageTypeExpAlign(type, expalignp, flags);
6220 * This typically only occurs when the resolver needs to
6221 * evaluate a constant expression. The declaration is
6222 * typically not resolved at that time.
6224 if (exp->ex_Token == TOK_ID || exp->ex_Token == TOK_CLASSID) {
6229 if (d && ((flags & RESOLVE_CONSTEXP) || (d->d_Flags & DF_RESOLVED))) {
6230 if (d && (d->d_Flags & DF_RESOLVED) == 0)
6231 resolveDecl(exp->ex_Decl, flags);
6232 resolveStorageDeclExpAlign(d, expalignp, flags);
6234 /* note: UNARY can be set for aliases */
6240 if (exp->ex_Flags & EXF_BINARY) {
6241 resolveStorageExpAlign(exp->ex_Lhs, expalignp, flags);
6242 resolveStorageExpAlign(exp->ex_Rhs, expalignp, flags);
6243 } else if (exp->ex_Flags & EXF_UNARY) {
6244 resolveStorageExpAlign(exp->ex_Lhs, expalignp, flags);
6245 } else if (exp->ex_Flags & EXF_COMPOUND) {
6248 for (scan = exp->ex_Lhs; scan; scan = scan->ex_Next) {
6249 resolveStorageExpAlign(scan, expalignp, flags);
6255 * resolveStorageType() - temporary space required to initialize type defaults
6257 * Figure out the temporary space required to initialize a type's
6258 * defaults. Note that the space will be figured independantly
6259 * for any SemGroup's.
6263 resolveStorageTypeExpAlign(Type *type, runesize_t *expalignp, int flags)
6265 SemGroup *sg = NULL;
6266 Type *subtype1 = NULL;
6267 Type *subtype2 = NULL;
6269 if (type->ty_Flags & TF_ALIGNRESOLVED) {
6270 if (*expalignp < type->ty_TmpAlignMask)
6271 *expalignp = type->ty_TmpAlignMask;
6274 type->ty_Flags |= TF_ALIGNRESOLVED;
6276 switch(type->ty_Op) {
6278 sg = type->ty_ClassType.et_SemGroup;
6281 subtype1 = type->ty_AryType.et_Type;
6284 sg = type->ty_CompType.et_SemGroup;
6287 subtype1 = type->ty_ProcType.et_ArgsType;
6288 subtype2 = type->ty_ProcType.et_RetType;
6291 sg = type->ty_ImportType.et_SemGroup;
6294 sg = type->ty_ArgsType.et_SemGroup;
6297 sg = type->ty_VarType.et_SemGroup;
6300 /* has nothing to do with initializing the pointer */
6301 /* subtype1 = type->ty_CPtrType.et_Type; */
6304 /* has nothing to do with initializing the pointer */
6305 /* subtype1 = type->ty_PtrType.et_Type; */
6308 /* has nothing to do with initializing the pointer */
6309 /* subtype1 = type->ty_RefType.et_Type; */
6314 * nothing to be done here.
6317 case TY_UNRESOLVED: /* should be no unresolved types at this stage */
6319 dassert_type(type, 0);
6323 resolveStorageTypeExpAlign(subtype1,
6324 &subtype1->ty_TmpAlignMask,
6326 if (subtype1->ty_AssExp) {
6327 resolveStorageExpAlign(subtype1->ty_AssExp,
6328 &subtype1->ty_TmpAlignMask,
6331 if (type->ty_TmpAlignMask < subtype1->ty_TmpAlignMask)
6332 type->ty_TmpAlignMask = subtype1->ty_TmpAlignMask;
6335 resolveStorageTypeExpAlign(subtype2,
6336 &subtype2->ty_TmpAlignMask,
6338 if (subtype2->ty_AssExp) {
6339 resolveStorageExpAlign(subtype2->ty_AssExp,
6340 &subtype2->ty_TmpAlignMask,
6343 if (type->ty_TmpAlignMask < subtype2->ty_TmpAlignMask)
6344 type->ty_TmpAlignMask = subtype2->ty_TmpAlignMask;
6346 if (type->ty_AssExp) {
6347 resolveStorageExpAlign(type->ty_AssExp,
6348 &type->ty_TmpAlignMask,
6352 if (resolveSemGroup1(sg, 0) && resolveSemGroup2(sg, 0))
6353 resolveSemGroup3(sg, 0);
6354 resolveStorageSemGroupAlign(sg, flags);
6355 if (type->ty_TmpAlignMask < sg->sg_TmpAlignMask)
6356 type->ty_TmpAlignMask = sg->sg_TmpAlignMask;
6358 if (*expalignp < type->ty_TmpAlignMask)
6359 *expalignp = type->ty_TmpAlignMask;
6364 resolveStorageType(Type *type, runesize_t *offset, int isglob)
6366 SemGroup *sg = NULL;
6367 Type *subtype1 = NULL;
6368 Type *subtype2 = NULL;
6369 runesize_t save_offset1;
6370 runesize_t save_offset2;
6371 runesize_t save_offset3;
6372 runesize_t save_offsetx;
6374 dassert(type->ty_Flags & TF_ALIGNRESOLVED);
6375 if (type->ty_Flags & TF_TMPRESOLVED) {
6376 *offset += type->ty_TmpBytes;
6379 type->ty_Flags |= TF_TMPRESOLVED;
6381 switch(type->ty_Op) {
6383 sg = type->ty_ClassType.et_SemGroup;
6386 subtype1 = type->ty_AryType.et_Type;
6389 sg = type->ty_CompType.et_SemGroup;
6392 subtype1 = type->ty_ProcType.et_ArgsType;
6393 subtype2 = type->ty_ProcType.et_RetType;
6396 sg = type->ty_ImportType.et_SemGroup;
6399 sg = type->ty_ArgsType.et_SemGroup;
6402 sg = type->ty_VarType.et_SemGroup;
6405 /* has nothing to do with initializing the pointer */
6406 /* subtype1 = type->ty_CPtrType.et_Type; */
6409 /* has nothing to do with initializing the pointer */
6410 /* subtype1 = type->ty_PtrType.et_Type; */
6413 /* has nothing to do with initializing the pointer */
6414 /* subtype1 = type->ty_RefType.et_Type; */
6419 * nothing to be done here.
6422 case TY_UNRESOLVED: /* should be no unresolved types at this stage */
6424 dassert_type(type, 0);
6427 save_offset1 = *offset;
6428 save_offset2 = *offset;
6429 save_offset3 = *offset;
6430 save_offsetx = *offset;
6432 /*resolveType(subtype1, NULL, 0);*/
6433 resolveStorageType(subtype1, &subtype1->ty_TmpBytes, 0);
6434 if (subtype1->ty_AssExp) {
6435 resolveStorageExp(subtype1->ty_AssExp,
6436 &subtype1->ty_TmpBytes);
6438 save_offset1 += subtype1->ty_TmpBytes;
6439 if (type->ty_TmpAlignMask < subtype1->ty_TmpAlignMask)
6440 type->ty_TmpAlignMask = subtype1->ty_TmpAlignMask;
6443 /*resolveType(subtype2, NULL, 0);*/
6444 resolveStorageType(subtype2, &subtype2->ty_TmpBytes, 0);
6445 if (subtype2->ty_AssExp) {
6446 resolveStorageExp(subtype2->ty_AssExp,
6447 &subtype2->ty_TmpBytes);
6449 save_offset2 += subtype2->ty_TmpBytes;
6450 if (type->ty_TmpAlignMask < subtype2->ty_TmpAlignMask)
6451 type->ty_TmpAlignMask = subtype2->ty_TmpAlignMask;
6453 if (type->ty_AssExp) {
6454 resolveStorageExp(type->ty_AssExp, &type->ty_TmpBytes);
6457 if (resolveSemGroup1(sg, 0) && resolveSemGroup2(sg, 0))
6458 resolveSemGroup3(sg, 0);
6459 resolveStorageSemGroup(sg, 0, 0);
6461 save_offset3 += sg->sg_GlobalTmpBytes;
6463 save_offset3 += sg->sg_TmpBytes;
6467 * Re-resolve the type flags. XXX mostly fixed once I handled
6468 * CBase/DBase/GBase in resolveSemGroup1().
6470 if (sg->sg_Flags & SGF_HASASS)
6471 type->ty_Flags |= TF_HASASS;
6473 type->ty_Flags |= TF_HASLVPTR;
6474 if (sg->sg_Flags & SGF_VARARGS)
6475 type->ty_Flags |= TF_HASLVPTR; /* XXX TF_VARARGS */
6477 type->ty_Flags |= TF_HASCONSTRUCT;
6479 type->ty_Flags |= TF_HASDESTRUCT;
6482 if (*offset < save_offset1)
6483 *offset = save_offset1;
6484 if (*offset < save_offset2)
6485 *offset = save_offset2;
6486 if (*offset < save_offset3)
6487 *offset = save_offset3;
6488 type->ty_TmpBytes = *offset - save_offsetx;
6492 * This is used to resolve temporary storage requirements for
6493 * SemGroup's related to classes and compound types. Temporary storage
6494 * requirements are calculated on a SemGroup-by-SemGroup basis and not
6495 * aggregated into any parent.
6497 * In the final pass we also reverse the constructor and destructor lists
6498 * (sg_CBase and sg_DBase), and the pointer/lvalue list (SRBase). These
6499 * lists were originally constructed by prepending and are thus in the
6504 resolveStorageSemGroupAlign(SemGroup *sg, int flags)
6508 if (sg->sg_Flags & SGF_ALIGNRESOLVED)
6510 sg->sg_Flags |= SGF_ALIGNRESOLVED;
6513 * SGF_RESOLVED might not be set. This can only happen because we
6514 * allow individual declarations in global SemGroups to be resolved
6515 * without having to resolve the whole group. This allows unused
6516 * declarations to be omitted by the code generator.
6518 if ((sg->sg_Flags & SGF_RESOLVED) == 0)
6519 sg->sg_Flags |= SGF_RESOLVED;
6521 RUNE_FOREACH(d, &sg->sg_DeclList, d_Node) {
6522 resolveStorageDeclExpAlign(d, &sg->sg_TmpAlignMask, flags);
6523 if (d->d_ScopeFlags & SCOPE_GLOBAL) {
6524 if (sg->sg_GlobalAlignMask < d->d_AlignMask)
6525 sg->sg_GlobalAlignMask = d->d_AlignMask;
6527 if (sg->sg_AlignMask < d->d_AlignMask)
6528 sg->sg_AlignMask = d->d_AlignMask;
6535 resolveStorageSemGroup(SemGroup *sg, runesize_t noffset, runesize_t ngoffset)
6541 if ((sg->sg_Flags & SGF_RESOLVED) == 0) {
6542 if (resolveSemGroup1(sg, 0) && resolveSemGroup2(sg, 0))
6543 resolveSemGroup3(sg, 0);
6546 dassert(sg->sg_Flags & SGF_ALIGNRESOLVED);
6547 if (sg->sg_Flags & SGF_TMPRESOLVED)
6549 sg->sg_Flags |= SGF_TMPRESOLVED;
6554 RUNE_FOREACH(d, &sg->sg_DeclList, d_Node) {
6555 runesize_t offset = 0;
6556 runesize_t goffset = 0;
6558 resolveStorageDeclExp(d, &offset, &goffset);
6559 if (noffset < offset)
6561 if (ngoffset < goffset)
6568 if ((d2 = sg->sg_CBase) != NULL) {
6569 sg->sg_CBase = NULL;
6570 while ((d = d2) != NULL) {
6572 d->d_CNext = sg->sg_CBase;
6576 if ((d2 = sg->sg_DBase) != NULL) {
6577 sg->sg_DBase = NULL;
6578 while ((d = d2) != NULL) {
6580 d->d_DNext = sg->sg_DBase;
6584 if ((d2 = sg->sg_GBase) != NULL) {
6585 sg->sg_GBase = NULL;
6586 while ((d = d2) != NULL) {
6588 d->d_GNext = sg->sg_GBase;
6592 if ((d2 = sg->sg_SRBase) != NULL) {
6593 sg->sg_SRBase = NULL;
6594 while ((d = d2) != NULL) {
6596 d->d_SRNext = sg->sg_SRBase;
6600 sg->sg_TmpBytes = noffset;
6601 sg->sg_GlobalTmpBytes = ngoffset;
6605 * Return non-zero if the method procedure wants the 'this' variable
6606 * to be an lvalue-pointer rather than an lvalue-target-object. In this
6607 * situation we do not want to indirect the pointer.
6611 methodProcThisIsPointer(Type *type)
6617 dassert(type->ty_Op == TY_PROC);
6618 dassert(type->ty_ProcType.et_ArgsType->ty_Op == TY_ARGS);
6619 sg = type->ty_ProcType.et_ArgsType->ty_CompType.et_SemGroup;
6620 d = RUNE_FIRST(&sg->sg_DeclList);
6621 dassert(d->d_Id == String_This);
6622 switch (d->d_StorDecl.ed_Type->ty_Op) {
6631 "methodProcThisIsPointer(): method call through "
6632 "C pointer is illegal\n");
6644 * Calculate SG dependencies
6646 #define SGDEP_HSIZE 1024
6647 #define SGDEP_HMASK (SGDEP_HSIZE - 1)
6649 static SGDepend *SGDepHash[SGDEP_HSIZE];
6650 static SemGroup *SGCurrentDep;
6654 resolveSGDependHash(SemGroup *src, SemGroup *dst)
6658 hv = ((intptr_t)src >> 7) ^ ((intptr_t)dst >> 5);
6660 return (&SGDepHash[hv & SGDEP_HMASK]);
6665 resolvePushSGDepend(SemGroup *sg)
6671 depp = resolveSGDependHash(SGCurrentDep, sg);
6672 for (dep = *depp; dep; dep = dep->hnext) {
6673 if (dep->src == SGCurrentDep && dep->dst == sg)
6677 dep = zalloc(sizeof(SGDepend));
6679 dep->src = SGCurrentDep;
6683 dep->next = SGCurrentDep->sg_DepFirst;
6684 SGCurrentDep->sg_DepFirst = dep;
6687 last = SGCurrentDep;
6695 resolvePopSGDepend(SemGroup *dep)