Rune - Features (scripting, constants, main)
[rune.git] / librune / resolve.c
1 /*
2  * RESOLVE.C    - Resolve parser tree
3  *
4  * (c)Copyright 1993-2014, Matthew Dillon, All Rights Reserved.  See the  
5  *    COPYRIGHT file at the base of the distribution.
6  *
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.
10  *
11  * We can reach the entire tree by resolving the top-level import
12  * statement's DeclBlock.
13  */
14
15 #include "defs.h"
16 #include <dlfcn.h>
17
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, ...);
22
23 static void resolveStmt(SemGroup *isg, Stmt *st, int flags);
24 static Type *resolveReturnType(SemGroup *sg, int flags);
25 static Type *resolveArgsType(SemGroup *sg, int flags);
26 static void resolveDecl(Declaration *d, int flags);
27 static Exp *resolveExp(SemGroup *isg, SemGroup *sg,
28                         Exp *exp, Type *itype, int flags);
29 static Exp *resolveConstExp(SemGroup *isg, SemGroup *sg, Exp *exp, int flags);
30 static Exp *resolveConstExpBool(SemGroup *isg, SemGroup *sg, Exp *exp, int flags, RunTmpStor *ts);
31 static int64_t resolveGetConstExpInt64(Exp *exp);
32 static Exp *resolveCompoundExp(SemGroup *isg, SemGroup *sg,
33                         Exp *exp, Type *itype, int flags);
34 static Exp *resolveExpCast(SemGroup *isg, SemGroup *sg,
35                         Exp *exp, Type *ltype, int flags);
36 static Exp *resolveExpOper(SemGroup *isg, SemGroup *sg,
37                         Exp *exp, Type *itype, int flags);
38 static int resolveSemGroup1(SemGroup *sg, int flags);
39 static int resolveSemGroup2(SemGroup *sg, int flags);
40 static void resolveSemGroup3(SemGroup *sg, int flags);
41 static Type *resolveSuperClass(Type *super);
42
43 static void resolveStorageDeclExpAlign(Declaration *d, runesize_t *expalignp);
44 static void resolveStorageExpAlign(Exp *exp, runesize_t *expalignp);
45 static void resolveStorageTypeExpAlign(Type *type, runesize_t *expalignp);
46 static void resolveStorageSemGroupAlign(SemGroup *sg);
47
48 static void resolveStorageDeclExp(Declaration *d,
49                         runesize_t *offset, runesize_t *goffset);
50 static runesize_t resolveStorageExpOnly(Exp *exp, runesize_t *offset);
51 static void resolveStorageExpSub(Exp *exp, runesize_t *offset);
52 static void resolveStorageExp(Exp *exp, runesize_t *offset);
53
54 static Declaration *findOper(Type *btype, string_t id,
55                         Type *ltype, Type *rtype, int flags);
56 static Declaration *findExpOper(Exp *exp, int flags);
57 static Declaration *findCast(Type *btype, Type *ltype, Type *rtype, int flags);
58 static void loadExpCopy(Exp *copy, Exp *exp);
59 static void saveExpCopy(Exp *copy, Exp *exp);
60 static Exp *dupExpCopy(Exp *copy, Exp *exp);
61 static void resolveStorageType(Type *type, runesize_t *offset, int isglob);
62 static void resolveStorageSemGroup(SemGroup *sg,
63                         runesize_t noffset, runesize_t ngoffset);
64 static int methodProcThisIsPointer(Type *type);
65
66 static SemGroup *resolvePushSGDepend(SemGroup *sg);
67 static void resolvePopSGDepend(SemGroup *last);
68
69 #define exLhs           copy.ex_Lhs
70 #define exRhs           copy.ex_Rhs
71 #define exFlags         copy.ex_Flags
72 #define exType          copy.ex_Type
73 #define exToken         copy.ex_Token
74 #define exDecl          copy.ex_Decl
75 #define exVisibility    copy.ex_Visibility
76 #define exId            copy.ex_Id
77 #define exArgId         copy.ex_ArgId
78
79 #define ADD_LVALUE(type)                \
80                 resolveType(AddTypeQual((type), SF_LVALUE), NULL, flags)
81 #define DEL_LVALUE(type)                \
82                 resolveType(DelTypeQual((type), SF_LVALUE), NULL, flags)
83 #define RESOLVETYPE(type)               \
84                 resolveType((type), NULL, flags)
85 #define RESOLVETYPEADJ(type, adjtype)   \
86                 resolveType((type), adjtype, flags)
87
88 #define RESOLVE_AUTOCAST        0x0001  /* autocast to expected type */
89 #define RESOLVE_CONSTEXP        0x0002  /* resolve for const interpretation */
90
91 void
92 ResolveProject(Parse *p, Stmt *st)
93 {
94         int i;
95
96         dassert_stmt(st, st->st_Op == ST_Import);
97
98         /*
99          * General project
100          */
101         ResolveClasses(st, 0);
102         resolveStmt(st->st_MyGroup, st, 0);
103         ResolveAlignment(st, 0);
104         ResolveStorage(st, 0);
105
106         /*
107          * Interpreter or Generator may reference our global internal types
108          * directly, so make sure they are all resolved.
109          */
110         for (i = 0; BaseTypeAry[i]; ++i)
111                 resolveType(BaseTypeAry[i], NULL, 0);
112
113         /*
114          * Resolve all types registered by DLLs
115          */
116         {
117                 TypeRegNode *tr;
118
119                 RUNE_FOREACH(tr, &TypeRegList, tr_Node)
120                         resolveType(tr->tr_Type, NULL, 0);
121         }
122
123
124         p->p_Format = PFMT_RESOLVED;
125
126         CollapseProject(st);
127 }
128
129 /*
130  * ResolveClasses() -   Resolve superclasses and do class merge 
131  *
132  *      This code implements the most complex feature of the language:
133  *      subclassing and refinement.  
134  *
135  *      The hardest thing we have to do is 'dup' declarations and code in
136  *      order to implement subclassing and refinement.  For example, a
137  *      procedure defined in Integer must be dup'd for each subclass of
138  *      Integer.  We have to do this because storage requirements will
139  *      change due to both subclassing and refinement.  Even auto variables
140  *      may wind up with different types between superclass and subclass.
141  *
142  *      We must scan ST_Import and ST_Class statements.
143  */
144 static void
145 ResolveClasses(Stmt *st, int flags)
146 {
147         SemGroup *sg = st->st_MyGroup;
148
149         /*
150          * Resolver interlock.  Assert that we aren't looping.  A loop can
151          * occur if class A embeds class B and class B embeds class A
152          * (verses a pointer to A).
153          */
154         dassert_stmt(st, (st->st_Flags & STF_RESOLVING) == 0);
155         if (st->st_Flags & STF_RESOLVED)
156                 return;
157         st->st_Flags |= STF_RESOLVING;
158
159         /*
160          * If this is a subclass, integrate the superclass into it
161          */
162         if (st->st_Op == ST_Class && st->st_ClassStmt.es_Super) {
163                 Type *super = st->st_ClassStmt.es_Super;
164                 Stmt *sst;
165                 Declaration *d;
166                 Declaration *rd;
167                 SemGroup *tsg;
168
169                 /*
170                  * Locate the superclass.  'super' does not appear in any
171                  * other list.. this is a unique Type structure.
172                  */
173                 dassert_stmt(st, super->ty_Op == TY_UNRESOLVED);
174                 do {
175                         super = resolveSuperClass(super);
176                         if (super == NULL) {
177                                 fprintf(stderr,
178                                         "Unable to resolve superclass of %s\n",
179                                         st->st_ClassStmt.es_Decl->d_Id);
180                                 dassert_stmt(st, 0);
181                         }
182                 } while (super->ty_Op == TY_UNRESOLVED);
183
184                 dassert_stmt(st, super->ty_Op == TY_CLASS);
185
186                 /*
187                  * Cleanup (XXX free qualified segments??)
188                  */
189                 st->st_ClassStmt.es_Super = super;
190                 st->st_ClassStmt.es_Decl->d_ClassDecl.ed_Super = super;
191
192                 /*
193                  * Inherit internal unsigned integer and floating point flags
194                  * and a few others.
195                  */
196                 sg->sg_Flags |= super->ty_ClassType.et_SemGroup->sg_Flags &
197                                 (SGF_ISINTEGER | SGF_ISUNSIGNED |
198                                  SGF_ISFLOATING | SGF_ISBOOL |
199                                  SGF_HASASS | SGF_GHASASS |
200                                  SGF_HASLVPTR | SGF_GHASLVPTR);
201
202                 /*
203                  * Locate the class statement associated with the superclass
204                  * and resolve it.
205                  */
206                 sst = super->ty_ClassType.et_SemGroup->sg_Stmt;
207                 dassert_stmt(st, sst != NULL);
208                 dassert_stmt(st, sst->st_Op == ST_Class);
209
210                 ResolveClasses(sst, flags);
211
212                 /*
213                  * Assign the sg_Level for the subclass.  This is used
214                  * for semantic searches when a subclass is passed to a
215                  * procedure expecting the superclass.
216                  */
217                 sg->sg_Level = sst->st_MyGroup->sg_Level + 1;
218
219                 /*
220                  * First move all the declarations from sg to tsg so we
221                  * can merge the superclass properly (keep all the d_Index's
222                  * correct).  Note that tsg is not 100% integrated so we can
223                  * only use it for search purposes.  We absolutely CANNOT
224                  * DupDeclaration() into tsg!
225                  */
226                 tsg = AllocSemGroup(SG_CLASS, sg->sg_Parse, NULL, sg->sg_Stmt);
227                 while ((d = RUNE_FIRST(&sg->sg_DeclList)) != NULL) {
228                         RenameDecl(d, tsg);
229                 }
230                 sg->sg_DeclCount = 0;   /* reset */
231
232                 /*
233                  * Merge the superclass into this class, in sequence.
234                  * Iterate through declarations in the superclass and pull
235                  * them into the subclass.  Figure out compatibility between
236                  * super and subclasses.
237                  */
238                 RUNE_FOREACH(d, &sst->st_MyGroup->sg_DeclList, d_Node) {
239                         Declaration *nd;
240                         int eno = 0;
241
242                         dassert(d->d_Level != NULL &&
243                                 d->d_Level->sg_Level < sg->sg_Level);
244
245                         /*
246                          * See if the superclass decl conflicts with a
247                          * subclass decl.  If there is no conflict pull it
248                          * into the subclass and adjust the visibility.
249                          * Note that the superclass may have duplicate ids,
250                          * but they will be at different levels if so.
251                          *
252                          * The super linkage is required when findDecl()
253                          * checks visibility of a declaration hidden relative
254                          * to our subclass, but not necessarily hidden
255                          * relative to the superclass.
256                          *
257                          * XXX overloading
258                          */
259                         rd = FindDeclId(tsg, d->d_Id, &eno);
260                         if (rd == NULL) {
261                                 nd = DupDeclaration(sg, d);
262                                 dassert(d->d_Index == nd->d_Index);
263                                 nd->d_ScopeFlags &= ~SCOPE_ALL_VISIBLE |
264                                                     super->ty_Visibility;
265                                 nd->d_ScopeFlags &= ~SCOPE_REFINE;
266                                 continue;
267                         }
268
269                         /*
270                          * If there is a conflict and we are not refining
271                          * the superclass entity, then pull in the superclass
272                          * entity and make it invisible to sg_Level searches.
273                          * This could bring in multiple levels of the same id.
274                          *
275                          * Note that this may result in multiple ids, but
276                          * they will be at different levels.  In this case
277                          * rd will be at the current level and nd will be
278                          * at some prior level.
279                          *
280                          * Order is important here.
281                          */
282                         if ((rd->d_ScopeFlags & SCOPE_REFINE) == 0) {
283                                 nd = DupDeclaration(sg, d);
284                                 dassert(d->d_Index == nd->d_Index);
285                                 nd->d_ScopeFlags &= ~(SCOPE_ALL_VISIBLE |
286                                                       SCOPE_REFINE);
287 #if 0
288                                 printf(" conflict, not refined, overload\n");
289 #endif
290                                 continue;
291                         }
292
293                         /*
294                          * Ok, we need to refine.  But the superclass may
295                          * contain multiple levels of the same id.  We only
296                          * refine the one that is visible to us.  None of
297                          * these other declarations will be at the same level.
298                          */
299                         if ((d->d_ScopeFlags & SCOPE_ALL_VISIBLE) == 0) {
300                                 nd = DupDeclaration(sg, d);
301                                 dassert(d->d_Index == nd->d_Index);
302                                 nd->d_ScopeFlags &= ~(SCOPE_ALL_VISIBLE |
303                                                       SCOPE_REFINE);
304 #if 0
305                                 printf(" conflict, refined (skip this one)\n");
306 #endif
307                                 continue;
308                         }
309
310                         /*
311                          * Whew!  Finally, we found the superclass decl
312                          * that we wish to refine.  We had better not have
313                          * already refined it or there's something wrong
314                          * with the algorithm.
315                          *
316                          * Since we inherit the superclass method's level
317                          * our method will run in the superclass instead
318                          * of the original, but d_Super still must be set
319                          * for findDecl() to track down visibility relative
320                          * to the superclass methods.
321                          */
322                         RenameDecl(rd, sg);
323                         dassert_decl(rd, rd->d_Super == NULL);
324                         dassert(d->d_Index == rd->d_Index);
325                         rd->d_Level = d->d_Level;
326                         rd->d_Super = d;
327
328                         /*
329                          * This is for the superclass method access special
330                          * case below.
331                          */
332                         if (d->d_Op == DOP_PROC) {
333                                 d->d_Flags |= DF_SUPERCOPY;
334                         }
335                 }
336
337                 /*
338                  * Deal with any remaining elements in tsg.  These are
339                  * 'extensions' to the superclass.  There may also be
340                  * invisible DOP_PROC's to handle the special superclass
341                  * method call case descibed above.
342                  */
343                 while ((rd = RUNE_FIRST(&tsg->sg_DeclList)) != NULL) {
344                         if (rd->d_ScopeFlags & SCOPE_REFINE) {
345                                 if (rd->d_Super == NULL) {
346                                         fprintf(stderr,
347                                                 "Unable to refine %s, it "
348                                                 "does not exist in "
349                                                 "superclass\n",
350                                                 rd->d_Id);
351                                         dassert_decl(rd, 0);
352                                 }
353                         }
354                         RenameDecl(rd, sg);
355                 }
356
357                 FreeSemGroup(tsg);
358
359                 /*
360                  * We have to special case super.method() for a refined method.
361                  * Normally this makes the original method inaccessible (for
362                  * storage), but we want it to work for a procedure so we make
363                  * a copy in tsg.  (we can't dup it directly into sg because it
364                  * will screw up the d_Index).
365                  *
366                  * We must not only clear the scope visibility and the
367                  * temporary refine flag, we also have to clear
368                  * constructor/destructor scope in the copy so only the
369                  * refined constructor/destructor is called, not both the
370                  * refined and the superclass constructor/destructor.
371                  */
372                 RUNE_FOREACH(d, &sst->st_MyGroup->sg_DeclList, d_Node) {
373                         Declaration *nd;
374
375                         if (d->d_Flags & DF_SUPERCOPY) {
376                                 d->d_Flags &= ~DF_SUPERCOPY;
377                                 nd = DupDeclaration(sg, d);
378                                 nd->d_ScopeFlags &= ~(SCOPE_ALL_VISIBLE |
379                                                       SCOPE_REFINE |
380                                                       SCOPE_CONSTRUCTOR |
381                                                       SCOPE_DESTRUCTOR);
382                         }
383                 }
384         } else if (st->st_Op == ST_Class) {
385                 sg->sg_Level = 0;
386         }
387
388         st->st_Flags &= ~STF_RESOLVING;
389         st->st_Flags |= STF_RESOLVED;
390
391         /*
392          * If this is an ST_Import we must recurse through it.  The only
393          * statements under an Import should be Modules.  Well, really just
394          * one module.  And under that module we only care about ST_Import
395          * and ST_Class statements.
396          *
397          * If this is a shared import the statement list will be empty (later
398          * it may be used for import refinement, I dunno).  This is what we
399          * want since we should only resolve a shared import once.
400          */
401         if (st->st_Op == ST_Import) {
402                 Stmt *scan;
403
404                 RUNE_FOREACH(scan, &st->st_List, st_Node) {
405                         Stmt *scan2;
406
407                         dassert_stmt(scan, scan->st_Op == ST_Module);
408                         RUNE_FOREACH(scan2, &scan->st_List, st_Node) {
409                                 if (scan2->st_Op == ST_Import ||
410                                     scan2->st_Op == ST_Class) {
411                                         ResolveClasses(scan2, flags);
412                                 }
413                         }
414                 }
415                 if (st->st_ImportStmt.es_DLL) {
416                         void (*func)(void) = dlsym(st->st_ImportStmt.es_DLL,
417                                                    "resolveClasses");
418                         if (func)
419                                 func();
420                 }
421         }
422 }
423
424 /*
425  * resolveStmt() - Resolve all types, declarations, and semantic refs
426  *
427  *      Resolves all types, declarations, and identifiers.  Additionally
428  *      this function resolves intermediate types for expressions.  Storage
429  *      sizes are resolved but offsets are not assigned to declarations.
430  */
431 void
432 resolveStmt(SemGroup *isg, Stmt *st, int flags)
433 {
434         SemGroup *dep = NULL;
435
436         /*
437          * Deal with unresolved types here
438          */
439         if (st->st_Flags & STF_SEMANTIC) {
440                 SemGroup *sg = st->st_MyGroup;
441                 Type *type;
442
443                 dep = resolvePushSGDepend(sg);
444
445                 RUNE_FOREACH(type, &sg->sg_ClassList, ty_Node) {
446                         if (type->ty_Op == TY_UNRESOLVED) {
447                                 if (resolveSuperClass(type) == NULL) {
448                                         errorDottedId(
449                                                 type->ty_UnresType.et_DottedId,
450                                                 "Unable to resolve class");
451                                         dassert_stmt(st, 0);
452                                 }
453                         }
454                 }
455         }
456
457         /*
458          * Resolve statements.  Don't worry about declarations, those are
459          * handled after this switch.
460          */
461         switch(st->st_Op) {
462         case ST_Import:
463                 /*
464                  * This will just flag the import declaration as resolved
465                  * so the code generator dives it for generation.
466                  */
467                 if (st->st_ImportStmt.es_Decl)
468                         resolveDecl(st->st_ImportStmt.es_Decl, flags);
469                 /* fall through */
470         case ST_Module:
471                 /*
472                  * Recursively resolve contents
473                  */
474                 {
475                         Stmt *scan;
476
477                         RUNE_FOREACH(scan, &st->st_List, st_Node) {
478                                 /*
479                                  * XXX pass isg for import, st_MyGroup for
480                                  * module??
481                                  */
482                                 resolveStmt(st->st_MyGroup, scan, flags);
483                         }
484                         if (st->st_Op == ST_Import &&
485                             st->st_ImportStmt.es_DLL) {
486                                 void (*func)(void) =
487                                         dlsym(st->st_ImportStmt.es_DLL,
488                                               "resolveTypes");
489                                 if (func)
490                                         func();
491                         }
492                 }
493                 break;
494         case ST_Class:
495                 resolveDecl(st->st_ClassStmt.es_Decl, flags);
496                 break;
497         case ST_Typedef:
498                 resolveDecl(st->st_TypedefStmt.es_Decl, flags);
499                 break;
500         case ST_Decl:
501                 /*
502                  * Resolve declarations, skipping any whos context was
503                  * moved to a class (e.g. a declaration at the top level
504                  * of a file like Fd.setfd(...) also exists in the Fd class).
505                  */
506                 {
507                         Declaration *d = st->st_DeclStmt.es_Decl;
508                         int i;
509
510                         for (i = 0; i < st->st_DeclStmt.es_DeclCount; ++i) {
511                                 if (st->st_MyGroup != d->d_MyGroup)
512                                         /*printf("SKIPA %s\n", d->d_Id)*/;
513                                 else
514                                         resolveDecl(d, flags);
515                                 d = RUNE_NEXT(d, d_Node);
516                         }
517                 }
518                 break;
519         case ST_Block:
520                 {
521                         Stmt *scan;
522
523                         RUNE_FOREACH(scan, &st->st_List, st_Node) {
524                                 resolveStmt(isg, scan, flags);
525                         }
526                 }
527                 break;
528         case ST_Nop:
529                 break;
530         case ST_Loop:
531                 if (st->st_LoopStmt.es_Init)
532                         resolveStmt(isg, st->st_LoopStmt.es_Init, flags);
533                 if (st->st_LoopStmt.es_BCond) {
534                         /*
535                          * NOTE: BoolType global implies an rvalue.
536                          */
537                         st->st_LoopStmt.es_BCond =
538                                 resolveExp(isg, st->st_MyGroup,
539                                            st->st_LoopStmt.es_BCond,
540                                            &BoolType, RESOLVE_AUTOCAST);
541                 }
542                 if (st->st_LoopStmt.es_ACond) {
543                         /*
544                          * NOTE: BoolType global implies an rvalue.
545                          */
546                         st->st_LoopStmt.es_ACond =
547                                 resolveExp(isg, st->st_MyGroup,
548                                            st->st_LoopStmt.es_ACond,
549                                            &BoolType, RESOLVE_AUTOCAST);
550                 }
551                 if (st->st_LoopStmt.es_AExp) {
552                         /*
553                          * NOTE: VoidType global implies an rvalue.
554                          */
555                         st->st_LoopStmt.es_AExp =
556                                 resolveExp(isg, st->st_MyGroup,
557                                            st->st_LoopStmt.es_AExp,
558                                            &VoidType, RESOLVE_AUTOCAST);
559                 }
560                 if (st->st_LoopStmt.es_Body) {
561                         resolveStmt(isg, st->st_LoopStmt.es_Body, flags);
562 #if 0
563                         /* remove handled in resolveDecl DOP_PROC */
564                         if ((st->st_LoopStmt.es_Body->st_Flags &
565                              STF_RESOLVED) == 0) {
566                                 ResolveAlignment(st->st_LoopStmt.es_Body,
567                                                  flags);
568                                 ResolveStorage(st->st_LoopStmt.es_Body, flags);
569                         }
570 #endif
571                 }
572                 break;
573         case ST_BreakCont:
574                 break;
575         case ST_Bad:
576                 break;
577         case ST_IfElse:
578                 /*
579                  * NOTE: BoolType global implies an rvalue.
580                  */
581                 st->st_IfStmt.es_Exp = resolveExp(isg, st->st_MyGroup,
582                                                   st->st_IfStmt.es_Exp,
583                                                   &BoolType, RESOLVE_AUTOCAST);
584                 resolveStmt(isg, st->st_IfStmt.es_TrueStmt, flags);
585                 if (st->st_IfStmt.es_FalseStmt)
586                         resolveStmt(isg, st->st_IfStmt.es_FalseStmt, flags);
587                 break;
588         case ST_Return:
589                 /*
590                  * NOTE: lvalue/rvalue depends on return type.
591                  */
592                 st->st_RetStmt.es_ProcRetType =
593                                 resolveReturnType(st->st_MyGroup, flags);
594                 if (st->st_RetStmt.es_Exp) {
595                         st->st_RetStmt.es_Exp =
596                                 resolveExp(isg, st->st_MyGroup,
597                                            st->st_RetStmt.es_Exp,
598                                            st->st_RetStmt.es_ProcRetType,
599                                            RESOLVE_AUTOCAST);
600                 }
601                 break;
602         case ST_Result:
603                 /*
604                  * NOTE: lvalue/rvalue depends on return type.
605                  */
606                 st->st_ResStmt.es_ProcRetType =
607                                 resolveReturnType(st->st_MyGroup, flags);
608                 if (st->st_ResStmt.es_Exp) {
609                         st->st_ResStmt.es_Exp =
610                                 resolveExp(isg, st->st_MyGroup,
611                                            st->st_ResStmt.es_Exp,
612                                            st->st_ResStmt.es_ProcRetType,
613                                            RESOLVE_AUTOCAST);
614                 }
615                 break;
616         case ST_Switch:
617                 /*
618                  * NOTE: Switch type must be an rvalue.
619                  *
620                  * NOTE: It is possible to switch on a type.  See ST_Case
621                  *       below for more detail.
622                  */
623                 st->st_SwStmt.es_Exp->ex_Flags |= EXF_REQ_TYPE;
624                 st->st_SwStmt.es_Exp = resolveExp(isg, st->st_MyGroup,
625                                                   st->st_SwStmt.es_Exp,
626                                                   NULL, 0);
627
628                 /*
629                  * Switch-on-expression() expects an rvalue.
630                  */
631                 if ((st->st_SwStmt.es_Exp->ex_Flags & EXF_RET_TYPE) == 0) {
632                         st->st_SwStmt.es_Exp->ex_Type =
633                                 DEL_LVALUE(st->st_SwStmt.es_Exp->ex_Type);
634                 }
635                 {
636                         Stmt *scan;
637
638                         RUNE_FOREACH(scan, &st->st_List, st_Node) {
639                                 resolveStmt(isg, scan, flags);
640                         }
641                 }
642                 break;
643         case ST_Case:
644                 /*
645                  * Handle a case/default.  Note that when switching on a type,
646                  * each case expression must return a type.
647                  *
648                  * NOTE: Case type must be an rvalue.  We use the switch type
649                  *       to cast, so it will be.
650                  */
651                 {
652                         Stmt *scan;
653                         Exp *exp;
654                         Type *type;
655
656                         /*
657                          * Set type to cast cases to if we are switching on
658                          * an expression, otherwise we are switching on a
659                          * type and should not try to coerce the cases (it
660                          * doesn't make sense to).
661                          */
662                         dassert_stmt(st, st->st_Parent->st_Op == ST_Switch);
663                         if (st->st_Parent->st_SwStmt.es_Exp->ex_Flags & EXF_RET_TYPE)
664                                 type = NULL;
665                         else
666                                 type = st->st_Parent->st_SwStmt.es_Exp->ex_Type;
667
668                         /*
669                          * case: (if es_Exp is NULL, this is a default: )
670                          */
671                         if ((exp = st->st_CaseStmt.es_Exp) != NULL) {
672                                 if (type == NULL)
673                                         exp->ex_Flags |= EXF_REQ_TYPE;
674                                 exp = resolveExp(isg, st->st_MyGroup,
675                                                  exp, type, RESOLVE_AUTOCAST);
676                                 if (type == NULL)
677                                         dassert(exp->ex_Flags & EXF_RET_TYPE);
678                                 st->st_CaseStmt.es_Exp = exp;
679                         }
680
681                         /*
682                          * Elements of the case/default
683                          */
684                         RUNE_FOREACH(scan, &st->st_List, st_Node) {
685                                 resolveStmt(isg, scan, flags);
686                         }
687                 }
688                 break;
689         case ST_Exp:
690                 /*
691                  * NOTE: VoidType global implies an rvalue.
692                  *
693                  * NOTE: If resolveExp() doesn't cast to void for
694                  *       us, we will do it here.
695                  */
696                 {
697                         Exp *exp;
698
699                         exp = resolveExp(isg, st->st_MyGroup,
700                                          st->st_ExpStmt.es_Exp,
701                                          &VoidType, RESOLVE_AUTOCAST);
702                         if (exp->ex_Type != &VoidType) {
703                                 exp = resolveExpCast(isg, st->st_MyGroup,
704                                                      exp, &VoidType, flags);
705                         }
706                         st->st_ExpStmt.es_Exp = exp;
707                 }
708                 break;
709         case ST_Proc:
710                 {
711                         Stmt *scan;
712
713                         RUNE_FOREACH(scan, &st->st_List, st_Node) {
714                                 resolveStmt(isg, scan, flags);
715                         }
716                 }
717                 break;
718         case ST_ThreadSched:
719                 break;
720         default:
721                 dassert_stmt(st, 0);
722         }
723         if (st->st_Flags & STF_SEMANTIC)
724                 resolvePopSGDepend(dep);
725 }
726
727 /*
728  * Locate the ST_Proc statement and resolve & return its return type
729  */
730 static
731 Type *
732 resolveReturnType(SemGroup *sg, int flags __unused)
733 {
734         Declaration *d;
735         Type *type;
736         Stmt *st;
737
738         /*
739          * Locate the ST_Proc statement
740          */
741         while (sg && (sg->sg_Stmt == NULL || sg->sg_Stmt->st_Op != ST_Proc))
742                 sg = sg->sg_Parent;
743         dassert(sg != NULL);
744         st = sg->sg_Stmt;
745         d = st->st_ProcStmt.es_Decl;    /* decl is already resolved */
746         dassert_decl(d, d->d_Op == DOP_PROC);
747         dassert_decl(d, d->d_Flags & (DF_RESOLVING|DF_RESOLVED));
748         type = d->d_ProcDecl.ed_Type;
749         dassert_decl(d, type->ty_Op == TY_PROC);
750         return(type->ty_ProcType.et_RetType);
751 }
752
753 Type *
754 resolveArgsType(SemGroup *sg, int flags __unused)
755 {
756         Declaration *d;
757         Type *type;
758         Stmt *st;
759
760         /*
761          * Locate the ST_Proc statement
762          */
763         while (sg && (sg->sg_Stmt == NULL || sg->sg_Stmt->st_Op != ST_Proc))
764                 sg = sg->sg_Parent;
765         dassert(sg != NULL);
766         st = sg->sg_Stmt;
767         d = st->st_ProcStmt.es_Decl;    /* decl is already resolved */
768         dassert_decl(d, d->d_Op == DOP_PROC);
769         dassert_decl(d, d->d_Flags & (DF_RESOLVING|DF_RESOLVED));
770         type = d->d_ProcDecl.ed_Type;
771         dassert_decl(d, type->ty_Op == TY_PROC);
772         return(type->ty_ProcType.et_ArgsType);
773 }
774
775 /*
776  * resolveDecl() - resolve a declaration
777  *
778  *      Note: we do not resolve d_Offset here.
779  *
780  *      If the declaration represents a procedure argument, special
781  *      processing of LVALUE scope is required to pass the declaration
782  *      by reference instead of by value.  Note that the size of the
783  *      underlying type DOES NOT CHANGE... it may be much larger.
784  */
785 void
786 resolveDecl(Declaration *d, int flags)
787 {
788         Type *type;
789         Stmt *st;
790         SemGroup *sg = NULL;
791
792         if (d->d_Flags & DF_RESOLVED)
793                 return;
794         dassert_decl(d, (d->d_Flags & DF_RESOLVING) == 0);
795         d->d_Flags |= DF_RESOLVING;
796
797         switch(d->d_Op) {
798         case DOP_CLASS:
799                 if (d->d_ClassDecl.ed_Super) {
800                         d->d_ClassDecl.ed_Super =
801                                 RESOLVETYPE(d->d_ClassDecl.ed_Super);
802                 }
803                 sg = d->d_ClassDecl.ed_SemGroup;
804                 if (resolveSemGroup1(sg, flags) && resolveSemGroup2(sg, flags))
805                         resolveSemGroup3(sg, flags);
806                 d->d_Bytes = d->d_ClassDecl.ed_SemGroup->sg_Bytes;
807                 d->d_AlignMask = d->d_ClassDecl.ed_SemGroup->sg_AlignMask;
808                 break;
809         case DOP_ALIAS:
810                 /*
811                  * Alias access is a barrier and always returns an rvalue.
812                  */
813                 type = d->d_AliasDecl.ed_Type =
814                                 RESOLVETYPE(d->d_AliasDecl.ed_Type);
815                 if (d->d_AliasDecl.ed_AssExp) {
816                         d->d_AliasDecl.ed_AssExp =
817                                 resolveExp(d->d_ImportSemGroup, d->d_MyGroup,
818                                            d->d_AliasDecl.ed_AssExp,
819                                            DEL_LVALUE(type),
820                                            flags | RESOLVE_AUTOCAST);
821                 }
822                 /* handled in DOT and STRIND resolver */
823                 SetDupExp(NULL, d->d_AliasDecl.ed_AssExp);
824                 break;
825         case DOP_TYPEDEF:
826                 d->d_Flags |= DF_RESOLVED;
827                 type = RESOLVETYPE(d->d_TypedefDecl.ed_Type); 
828                 d->d_Flags &= ~DF_RESOLVED;
829                 d->d_TypedefDecl.ed_Type = type;
830                 break;
831         case DOP_IMPORT:
832                 /*
833                  * This only occurs when resolving an import's semantic group.
834                  * Since we are scanning statements in that context we do not
835                  * have to recurse here, resolveStmt() will do it for us.
836                  */
837                 break;
838         case DOP_PROC:
839                 /*
840                  * XXX global procedure, later on, make the argument a
841                  * type instead of storage?
842                  */
843                 d->d_ProcDecl.ed_Type = RESOLVETYPE(d->d_ProcDecl.ed_Type);
844
845                 /*
846                  * Deal with constructor/destructor chaining.  The chaining
847                  * winds up being reversed and will be corrected by the caller.
848                  */
849                 if (d->d_ScopeFlags & SCOPE_GLOBAL) {
850                         if ((d->d_Flags & DF_ONGLIST) == 0 &&
851                             (d->d_ScopeFlags & (SCOPE_CONSTRUCTOR |
852                                                SCOPE_DESTRUCTOR))) {
853                                 d->d_GNext = d->d_MyGroup->sg_GBase;
854                                 d->d_MyGroup->sg_GBase = d;
855                                 d->d_Flags |= DF_ONGLIST;
856                         }
857                 } else {
858                         if ((d->d_Flags & DF_ONCLIST) == 0 &&
859                             (d->d_ScopeFlags & SCOPE_CONSTRUCTOR)) {
860                                 d->d_CNext = d->d_MyGroup->sg_CBase;
861                                 d->d_MyGroup->sg_CBase = d;
862                                 d->d_Flags |= DF_ONCLIST;
863                         }
864                         if ((d->d_Flags & DF_ONDLIST) == 0 &&
865                             (d->d_ScopeFlags & SCOPE_DESTRUCTOR)) {
866                                 d->d_DNext = d->d_MyGroup->sg_DBase;
867                                 d->d_MyGroup->sg_DBase = d;
868                                 d->d_Flags |= DF_ONDLIST;
869                         }
870                 }
871
872                 /*
873                  * If this procedure is bound to a DLL we have to resolve
874                  * it here.
875                  */
876                 if (d->d_ScopeFlags & SCOPE_CLANG) {
877                         d->d_ProcDecl.ed_DLLFunc = 
878                                 FindDLLSymbol(NULL, d->d_ImportSemGroup,
879                                               d->d_Id);
880                 }
881                 break;
882         case DOP_ARGS_STORAGE:
883         case DOP_STACK_STORAGE:
884         case DOP_GLOBAL_STORAGE:
885         case DOP_GROUP_STORAGE:
886                 type = RESOLVETYPE(d->d_StorDecl.ed_Type);
887                 d->d_StorDecl.ed_Type = type;
888
889                 /*
890                  * Promote the lvalue storage qualifier (e.g. from a typedef)
891                  * into the declaration's scope.  This is what ultimately
892                  * controls lvalue vs rvalue arguments to procedures and such.
893                  */
894                 if ((type->ty_SQFlags & SF_LVALUE) && 
895                     (d->d_ScopeFlags & SCOPE_LVALUE) == 0
896                 ) {
897                         d->d_ScopeFlags |= SCOPE_LVALUE;
898                 }
899
900                 /*
901                  * Default assignment handling expects an rvalue.
902                  */
903                 if (d->d_StorDecl.ed_AssExp) {
904                         d->d_StorDecl.ed_AssExp =
905                                 resolveExp(d->d_ImportSemGroup, d->d_MyGroup,
906                                            d->d_StorDecl.ed_AssExp,
907                                            DEL_LVALUE(type),
908                                            flags | RESOLVE_AUTOCAST);
909                 }
910                 if (d->d_ScopeFlags & SCOPE_LVALUE) {
911                         /*
912                          * Object is passed as a LValueStor structure.  Note
913                          * that d_Bytes is going to be different then the
914                          * underlying type (which represents the actual
915                          * object).
916                          */
917                         d->d_Bytes = sizeof(LValueStor);
918                         d->d_AlignMask = LVALUE_ALIGN;
919                 } else { 
920                         /*
921                          * Object is passed by value.
922                          */
923                         d->d_AlignMask = type->ty_AlignMask;
924                         d->d_Bytes = type->ty_Bytes;
925                 }
926
927                 /*
928                  * If the declaration represents or contains an
929                  * argument-lvalue or a pointer we have to add it to
930                  * the SemGroup's SRBase list to properly reference or
931                  * dereference the elements.  XXX only do this for non-global
932                  * storage.
933                  *
934                  * If the declaration has LVALUE scope we must do the same
935                  * because the ref is tracked.
936                  */
937                 if (d->d_Op != DOP_GLOBAL_STORAGE &&
938                     (type->ty_Flags & TF_HASLVPTR)) {
939                         d->d_SRNext = d->d_MyGroup->sg_SRBase;
940                         d->d_MyGroup->sg_SRBase = d;
941                 } else if (d->d_ScopeFlags & SCOPE_LVALUE) {
942                         d->d_SRNext = d->d_MyGroup->sg_SRBase;
943                         d->d_MyGroup->sg_SRBase = d;
944                 }
945
946                 /*
947                  * Deal with constructor/destructor chaining.  The chaining
948                  * winds up being reversed and will be corrected by the
949                  * caller.
950                  */
951                 if (type->ty_Flags & TF_HASCONSTRUCT) {
952                         d->d_CNext = d->d_MyGroup->sg_CBase;
953                         d->d_MyGroup->sg_CBase = d;
954                 }
955                 if (type->ty_Flags & TF_HASDESTRUCT) {
956                         d->d_DNext = d->d_MyGroup->sg_DBase;
957                         d->d_MyGroup->sg_DBase = d;
958                 }
959                 if (type->ty_Flags & (TF_HASGCONSTRUCT|TF_HASGDESTRUCT)) {
960                         d->d_GNext = d->d_MyGroup->sg_GBase;
961                         d->d_MyGroup->sg_GBase = d;
962                 }
963
964                 /*
965                  * Automatic content-locking is only applicable to objects
966                  * that are or contain lvalues, pointers, or references.
967                  * Setting UNLOCKED relaxes requirements on taking the
968                  * address of the object.
969                  *
970                  * Automatic content-locking is not performed on class objects
971                  * or arrays.  We can set those to unlocked as well also
972                  * relaxing &reqs.
973                  */
974                 if ((d->d_Op & DOPF_STORAGE) &&
975                     (d->d_Scope.s_Flags & SCOPE_LVALUE) == 0) {
976                         if ((type->ty_Flags & TF_HASLVPTR) == 0 ||
977                             type->ty_Op == TY_CLASS ||
978                             type->ty_Op == TY_ARYOF) {
979                                 d->d_ScopeFlags |= SCOPE_UNLOCKED;
980                         }
981                 }
982
983                 break;
984         default:
985                 dassert_decl(d, 0);
986         }
987         d->d_Flags &= ~DF_RESOLVING;
988         d->d_Flags |= DF_RESOLVED;
989
990         /*
991          * Post resolution flag resolving (to handle recursion)
992          */
993         switch(d->d_Op) {
994         case DOP_PROC:
995                 /*
996                  * Create copies of procedures as they are needed (thus
997                  * avoiding an XxY matrix effect).
998                  */
999                 if ((st = d->d_ProcDecl.ed_OrigBody) == NULL) {
1000                         Declaration *super = d->d_Super;
1001                         while (super && super->d_ProcDecl.ed_OrigBody == NULL) {
1002                                 super = super->d_Super;
1003                         }
1004                         if (super) {
1005                                 st = super->d_ProcDecl.ed_OrigBody;
1006                                 if (super->d_MyGroup->sg_Stmt->st_Op == ST_Class) {
1007                                         /*
1008                                          * Copy-down a procedure from a
1009                                          * superclass.  The procedure must
1010                                          * still be linked into its superclass
1011                                          * for semantic searches to work as
1012                                          * expected, hence the use of super->
1013                                          * d_MyGroup and st->st_Parent.
1014                                          *
1015                                          * Note that this code is not reached
1016                                          * in the case of a nested procedure,
1017                                          * since nested procedures are copied
1018                                          * with the parent.
1019                                          */
1020                                         st = DupStmt(super->d_MyGroup,
1021                                                      st->st_Parent, st);
1022                                 } else {
1023                                         /*
1024                                          * Copy-down a nested procedure.
1025                                          * The procedure must be linked
1026                                          * into the copy of the parent
1027                                          * prodedure, not the original
1028                                          * parent procedure, or it will
1029                                          * never be resolved.
1030                                          */
1031                                         st = DupStmt(d->d_Stmt->st_MyGroup,
1032                                                      d->d_Stmt, st);
1033                                 }
1034                         } else {
1035                                 /*
1036                                  * Internal procedure (we do not need to do
1037                                  * anything), there is no statement body
1038                                  * to duplicate.
1039                                  */
1040                         }
1041                 } else {
1042                         /*
1043                          * Procedure is being used in the primary class it
1044                          * was defined in.
1045                          */
1046                         st = DupStmt(d->d_MyGroup, st->st_Parent, st);
1047                 }
1048                 if (st) {
1049                         /*
1050                          * Link the procedure body to the declaration and
1051                          * resolve the procedure body.
1052                          */
1053                         dassert_stmt(st, d->d_ProcDecl.ed_ProcBody == NULL);
1054
1055                         d->d_ProcDecl.ed_ProcBody = st;
1056                         st->st_ProcStmt.es_Decl = d;
1057                         st->st_ProcStmt.es_Scope = d->d_Scope;
1058                         resolveStmt(d->d_ImportSemGroup, st, flags);
1059 #if 0
1060                         ResolveAlignment(st, flags);
1061                         ResolveStorage(st, flags);
1062 #endif
1063                 }
1064                 break;
1065         default:
1066                 break;
1067         }
1068
1069         /*
1070          * __align(%d) scope qualifier, override the type's alignment
1071          */
1072         if ((d->d_Scope.s_Flags & SCOPE_ALIGN) && d->d_Scope.s_AlignOverride)
1073                 d->d_AlignMask = d->d_Scope.s_AlignOverride - 1;
1074 }
1075
1076 /*
1077  * resolveExp() - resolve expression
1078  *
1079  * Resolve an expression.  We are expected to resolve all ex_Type's 
1080  * for the expression tree as well as expected to track down
1081  * operators and base identifiers.
1082  *
1083  * itype is a type hint.  If non-NULL, the caller would like our
1084  * expression to return the specified type.  There are a few special
1085  * cases:
1086  *
1087  * EXF_REQ_ARRAY - when OBRACKET requests an arry optimization it
1088  *                 passes a post-array-indexed typehint (as if
1089  *                 you had done the optimization).  You must ignore
1090  *                 itype if you are unable to do the optimization.
1091  *
1092  * NOTE: Even rvalues may have refstor side-effects at run-time.
1093  */
1094 Exp *
1095 resolveExp(SemGroup *isg, SemGroup *sg, Exp *exp, Type *itype, int flags)
1096 {
1097         Exp copy;
1098         int couldconst;
1099
1100         loadExpCopy(&copy, exp);
1101         couldconst = 0;
1102
1103         /*
1104          * Must resolve cast target type hint.
1105          */
1106         if (itype)
1107                 itype = RESOLVETYPE(itype);
1108
1109         /*
1110          * note: certain cases below call other resolver functions and assume
1111          * that ex* variables are unchanged.
1112          */
1113         dassert((exFlags & EXF_DUPEXP) || (exFlags & EXF_RESOLVED) == 0);
1114
1115         switch(exToken) {
1116         case TOK_ASS:
1117                 /*
1118                  * An assignment.  Note that we optimize void returns
1119                  * (such as when an assignment is a statement like 'a = 4;'
1120                  * ... the result of the assignment is cast to void.
1121                  *
1122                  * NOTE: Left-hand-side must be an LVALUE, return type
1123                  *       inherits this feature unless the parent turns off
1124                  *       the bit so the TOK_ASS run-time must deal with that.
1125                  */
1126                 exLhs = resolveExp(isg, sg, exLhs, NULL,
1127                                    flags & ~RESOLVE_AUTOCAST);
1128                 dassert_exp(exLhs, exLhs->ex_Type->ty_SQFlags & SF_LVALUE);
1129                 exRhs = resolveExp(isg, sg, exRhs,
1130                                    DEL_LVALUE(exLhs->ex_Type),
1131                                    flags | RESOLVE_AUTOCAST);
1132
1133                 /* AssExp handles this optimization */
1134                 if (itype == &VoidType) {
1135                         exType = itype;
1136                         exFlags |= EXF_RET_VOID;
1137                 } else {
1138                         exType = exLhs->ex_Type;
1139                 }
1140
1141 #if 0
1142                 /*
1143                  * Check @ref assignment compatibility.
1144                  */
1145                 if (exLhs->ex_Type->ty_Op == TY_REFTO) {
1146                         switch(MatchType(exLhs->ex_Type, exRhs->ex_Type)) {
1147                         case SG_COMPAT_FULL:
1148                                 printf("assign %s compatibility FULL\n",
1149                                         exLhs->ex_Id);
1150                                 break;
1151                         case SG_COMPAT_PART:
1152                                 printf("assign %s compatibility PART\n",
1153                                         exLhs->ex_Id);
1154                                 break;
1155                         case SG_COMPAT_SUBCLASS:
1156                                 printf("assign %s compatibility SUBCL\n",
1157                                         exLhs->ex_Id);
1158                                 break;
1159                         case SG_COMPAT_FAIL:
1160                                 printf("assign %s compatibility FAIL\n",
1161                                         exLhs->ex_Id);
1162                                 break;
1163                         }
1164                 }
1165 #endif
1166                 break;
1167         case TOK_ANDAND:
1168                 /*
1169                  * NOTE: BoolType global implies an rvalue.
1170                  */
1171                 couldconst = 1;
1172                 exLhs = resolveExp(isg, sg, exLhs, &BoolType,
1173                                    flags | RESOLVE_AUTOCAST);
1174
1175                 /*
1176                  * If left-side can terminate the operation, mark the
1177                  * expression as PROBCONST for the interpreter and code
1178                  * generator (allowing the rhs to not be a constant).
1179                  */
1180                 if (exLhs->ex_Flags & (EXF_CONST | EXF_PROBCONST)) {
1181                         RunTmpStor ts;
1182
1183                         exLhs = resolveConstExpBool(isg, sg, exLhs, flags, &ts);
1184                         if (ts.ts_Bool == 0)
1185                                 exFlags |= EXF_PROBCONST;
1186                 }
1187                 exRhs = resolveExp(isg, sg, exRhs, &BoolType,
1188                                    flags | RESOLVE_AUTOCAST);
1189                 exType = &BoolType;
1190                 break;
1191         case TOK_OROR:
1192                 /*
1193                  * NOTE: BoolType global implies an rvalue.
1194                  */
1195                 couldconst = 1;
1196                 exLhs = resolveExp(isg, sg, exLhs, &BoolType,
1197                                    flags | RESOLVE_AUTOCAST);
1198
1199                 /*
1200                  * If left-side can terminate the operation, mark the
1201                  * expression as PROBCONST for the interpreter and code
1202                  * generator (allowing the rhs to not be a constant).
1203                  */
1204                 if (exLhs->ex_Flags & (EXF_CONST | EXF_PROBCONST)) {
1205                         RunTmpStor ts;
1206
1207                         exLhs = resolveConstExpBool(isg, sg, exLhs, flags, &ts);
1208                         if (ts.ts_Bool)
1209                                 exFlags |= EXF_PROBCONST;
1210                 }
1211                 exRhs = resolveExp(isg, sg, exRhs, &BoolType,
1212                                    flags | RESOLVE_AUTOCAST);
1213                 exType = &BoolType;
1214                 break;
1215         case TOK_DECL:
1216                 /*
1217                  * This synthesized token occurs when we are able to collapse
1218                  * a structural indirection or dotted element into a
1219                  * declaration.  For example, 'module.routine'.
1220                  */
1221                 /* XXX couldconst? */
1222                 break;
1223         case TOK_DOT:
1224         case TOK_STRIND:
1225                 /*
1226                  * Structual field access.  The left hand side may be an object
1227                  * (class or compound), a class type, or a compound type.
1228                  * 
1229                  * A dotted access requires an lvalue on the left hand side
1230                  * if the left hand side represents storage.
1231                  *
1232                  * The result will be an lvalue if the right hand side
1233                  * represents storage.  We only loop if the right hand side
1234                  * is an alias replacement.
1235                  */
1236                 {
1237                         string_t id;
1238                         Declaration *d;
1239                         SemGroup *sg2;
1240                         Type *type;
1241                         int globalOnly = 0;
1242                         int s;
1243                         int visibility;
1244                         int isRefTo = 0;
1245                         int procedureOnly = 0;
1246                         int eno = TOK_ERR_ID_NOT_FOUND;
1247
1248                         /*
1249                          * NOTE: Hint must 'always happen' since we may be
1250                          *       modifying an expression that will later be
1251                          *       Dup'd.
1252                          *
1253                          * NOTE: Lhs is always an lvalue for TOK_DOT, but
1254                          *       does not have to be for TOK_STRIND.
1255                          */
1256                         exLhs->ex_Flags |= EXF_REQ_TYPE;
1257                         if (exToken == TOK_DOT && (exFlags & EXF_REQ_ADDROF))
1258                                 exLhs->ex_Flags |= EXF_REQ_ADDROF;
1259                         exLhs = resolveExp(isg, sg, exLhs, NULL,
1260                                            flags & ~RESOLVE_AUTOCAST);
1261
1262                         /*
1263                          * The RHS may have been turned into a TOK_SEMGRP_ID
1264                          * in a previous duplicate.  The change is considered
1265                          * permanent.
1266                          */
1267                         if (exRhs->ex_Token != TOK_SEMGRP_ID) {
1268                                 dassert_exp(exRhs,
1269                                             exRhs->ex_Token == TOK_STRUCT_ID);
1270                                 exRhs = resolveExp(isg, sg, exRhs, NULL,
1271                                                    flags & ~RESOLVE_AUTOCAST);
1272                         }
1273                         id = exRhs->ex_Id;
1274                         type = exLhs->ex_Type;
1275
1276                         /*
1277                          * Calculate scope and SemGroup to search.  Note
1278                          * that it is legal to do a structural '.' selection
1279                          * on a pointer, but it works differently then
1280                          * indirecting through a pointer via '->'.  In the
1281                          * case of '.' on a pointer, we first search the
1282                          * system Pointer class.
1283                          */
1284                         if (exLhs->ex_Flags & EXF_RET_TYPE) {
1285                                 globalOnly = 1;
1286                         }
1287
1288                         /*
1289                          * Figure out the base type used to look-up the
1290                          * identifier.  An identifier that resolves into a
1291                          * procedure winds up only being a hint for a
1292                          * reference type.
1293                          */
1294                         if (exToken == TOK_STRIND) {
1295                                 switch(type->ty_Op) {
1296                                 case TY_CPTRTO:
1297                                         type = type->ty_CPtrType.et_Type;
1298                                         break;
1299                                 case TY_PTRTO:
1300                                         type = type->ty_PtrType.et_Type;
1301                                         break;
1302                                 case TY_REFTO:
1303                                         type = type->ty_RefType.et_Type;
1304                                         isRefTo = 1;
1305                                         break;
1306                                 default:
1307                                         dassert_exp(exp, 0);
1308                                         /* not reached */
1309                                 }
1310                         }
1311
1312 again:
1313                         switch(type->ty_Op) {
1314                         case TY_CLASS:
1315                                 sg2 = type->ty_ClassType.et_SemGroup;
1316                                 break;
1317                         case TY_COMPOUND:
1318                                 sg2 = type->ty_CompType.et_SemGroup;
1319                                 break;
1320                         case TY_ARGS:
1321                                 sg2 = type->ty_ArgsType.et_SemGroup;
1322                                 break;
1323                         case TY_VAR:
1324                                 sg2 = type->ty_VarType.et_SemGroup;
1325                                 break;
1326                         case TY_IMPORT:
1327                                 sg2 = type->ty_ImportType.et_SemGroup;
1328                                 break;
1329                         case TY_CPTRTO:
1330                                 /* YYY */
1331                                 dassert_exp(exp, PointerType.ty_Op == TY_CLASS);
1332                                 sg2 = PointerType.ty_ClassType.et_SemGroup;
1333                                 break;
1334                         case TY_PTRTO:
1335                                 dassert_exp(exp, PointerType.ty_Op == TY_CLASS);
1336                                 sg2 = PointerType.ty_ClassType.et_SemGroup;
1337                                 break;
1338                         case TY_REFTO:
1339                                 /* YYY */
1340                                 dassert_exp(exp, PointerType.ty_Op == TY_CLASS);
1341                                 sg2 = PointerType.ty_ClassType.et_SemGroup;
1342                                 break;
1343                         default:
1344                                 /*
1345                                  * Possibly a pointer, aka ptr.NULL
1346                                  */
1347                                 sg2 = NULL;
1348                         }
1349                         visibility = exLhs->ex_Visibility;
1350
1351                         /*
1352                          * Locate the identifier normally, via its type.
1353                          * ty_TypeVisbility is the initial visibility (scope)
1354                          * that the semantic search should use in locating
1355                          * the identifier.
1356                          */
1357                         if (sg2) {
1358                                 string_t ary[2] = { id, NULL };
1359                                 int level;
1360
1361                                 if (exLhs->ex_Token == TOK_ID ||
1362                                     exLhs->ex_Token == TOK_DECL) {
1363                                         if (exLhs->ex_Decl->d_Search) {
1364                                                 level = exLhs->ex_Decl->
1365                                                          d_Search->sg_Level;
1366                                         } else {
1367                                                 level = sg2->sg_Level;
1368                                         }
1369
1370                                         /*
1371                                          * XXX BIG HACK
1372                                          */
1373                                         if (exLhs->ex_Flags & EXF_SUPER) {
1374                                                 if (isRefTo) {
1375                                                         fprintf(stderr, "Can't super with reference type\n");
1376                                                         dassert_exp(exp, 0);
1377                                                 }
1378                                                 if (level == 0) {
1379                                                         fprintf(stderr, "No superclass available\n");
1380                                                         dassert_exp(exp, 0);
1381                                                 }
1382                                                 --level;
1383                                         }
1384                                 } else {
1385                                         level = sg2->sg_Level;  /* may be -1 */
1386                                 }
1387                                 visibility &= type->ty_Visibility;
1388                                 d = FindDeclPath(&exp->ex_LexRef, NULL,
1389                                                  sg2, NULL,
1390                                                  ary, FDC_NOBACK,
1391                                                  &visibility, level, &eno);
1392                                 /*
1393                                  * XXX more hack.  If the super is visible
1394                                  * and a procedure we just found our own
1395                                  * refinement, not the superclass method.
1396                                  * This is because there is no 'superclass
1397                                  * method' per say, refinements *REPLACE*
1398                                  * superclass declarations and inherit the
1399                                  * superclass's level.  However, we still
1400                                  * want to be able to chain method calls so
1401                                  * what we do instead is go through and find
1402                                  * the procedure that we smacked when we did
1403                                  * the refinement.  This procedure has
1404                                  * already been conveniently brought into
1405                                  * the subclass context as an 'invisible'
1406                                  * entity at the same d_Level.
1407                                  */
1408                                 if ((exLhs->ex_Flags & EXF_SUPER) &&
1409                                     d &&
1410                                     d->d_Op == DOP_PROC &&
1411                                     (d->d_ScopeFlags & SCOPE_ALL_VISIBLE)
1412                                 ) {
1413                                         string_t id2 = d->d_Id;
1414                                         SemGroup *olevel = d->d_Level;
1415
1416                                         dassert_exp(exp, isRefTo == 0);
1417
1418                                         while ((d = RUNE_NEXT(d, d_Node)) != NULL) {
1419                                                 if (d->d_Id == id2 &&
1420                                                     d->d_Level == olevel && 
1421                                                     d->d_Op == DOP_PROC) {
1422                                                         break;
1423                                                 }
1424                                         }
1425                                 }
1426                         } else {
1427                                 d = NULL;
1428                         }
1429
1430                         if (d && procedureOnly && d->d_Op != DOP_PROC) {
1431                                 fprintf(stderr,
1432                                         "PTR.ELEMENT may be used for special "
1433                                         "pointer method calls, but not to "
1434                                         "access storage elements.  "
1435                                         "Use PTR->ELEMENT instead\n");
1436                                 dassert_exp(exp, 0);
1437                         }
1438
1439                         /*
1440                          * If referencing actual storage the storage must be
1441                          * declared global.
1442                          */
1443                         if (d && globalOnly && (d->d_Op & DOPF_STORAGE) &&
1444                                 (d->d_ScopeFlags & SCOPE_GLOBAL) == 0
1445                         ) {
1446                                 fprintf(stderr,
1447                                         "%s is not global.  Only globals "
1448                                         "can be accessed through a type\n",
1449                                         d->d_Id);
1450                                 dassert_exp(exp, 0);
1451                         }
1452
1453                         if (d) {
1454                                 /*
1455                                  * Identifier found.  Note that if we are
1456                                  * going through a reference type the
1457                                  * declaration is not the actual one we 
1458                                  * use at run time.  It's just a template.
1459                                  */
1460                                 resolveDecl(d, flags);
1461                                 exDecl = d;
1462                                 exVisibility = visibility;
1463
1464                                 /*
1465                                  * XXX this is in wrong place
1466                                  *
1467                                  * ADDROF content-locked storage is not
1468                                  * allowed, except for the SCOPE_LVALUE case
1469                                  * if the underlying type is acceptable.
1470                                  *
1471                                  * If we are running through an LValueStor
1472                                  * UNLOCKED applies to it and not its contents.
1473                                  * Check to see if the contents are acceptable.
1474                                  */
1475                                 if ((exFlags & EXF_REQ_ADDROF) &&
1476                                     (d->d_Op & DOPF_STORAGE) &&
1477                                    (d->d_Scope.s_Flags & SCOPE_UNLOCKED) == 0) {
1478                                         type = d->d_StorDecl.ed_Type;
1479                                         if ((type->ty_Flags & TF_HASLVPTR) && 
1480                                             type->ty_Op != TY_CLASS &&
1481                                             type->ty_Op != TY_ARYOF) {
1482                                                 ExpPrintError(exp,
1483                                                     TOK_ERR_ILLEGAL_ADDRLOCKED);
1484                                                 dassert_exp(exp, 0);
1485                                         }
1486                                 }
1487
1488                                 /*
1489                                  * Misc.
1490                                  */
1491                                 switch(d->d_Op) {
1492                                 case DOP_PROC:
1493                                         exType = d->d_ProcDecl.ed_Type;
1494                                         if (d->d_ProcDecl.ed_Type->ty_SQFlags & SF_METHOD) {
1495                                                 /*
1496                                                  * Method call, do not
1497                                                  * collapse the expression into
1498                                                  * a direct declaration because
1499                                                  * the object is needed later.
1500                                                  */
1501                                                 if (exLhs->ex_Flags & EXF_RET_TYPE)
1502                                                         ExpPrintError(exLhs, TOK_ERR_METHOD_REQUIRES_OBJ);
1503                                                 dassert((exLhs->ex_Flags & EXF_RET_TYPE) == 0);
1504                                         } else if (isRefTo) {
1505                                                 /*
1506                                                  * Call via reference.  The
1507                                                  * lhs is required to evaluate
1508                                                  * the actual method call at
1509                                                  * run-time.
1510                                                  */
1511                                         } else {
1512                                                 /*
1513                                                  * Global method call or normal
1514                                                  * call.  For the global method
1515                                                  * case the lhs is not needed
1516                                                  * because the parser entered
1517                                                  * the first argument as a
1518                                                  * type already.
1519                                                  *
1520                                                  * Degenerate into a TOK_DECL.
1521                                                  * We depend on this later.
1522                                                  */
1523                                                 exFlags &= ~EXF_BINARY;
1524                                                 exLhs = NULL;
1525                                                 exRhs = NULL;
1526                                                 exToken = TOK_DECL;
1527                                         }
1528                                         break;
1529                                 case DOP_ALIAS:
1530                                         exType = DEL_LVALUE(d->d_AliasDecl.ed_Type);
1531                                         dassert_decl(d, d->d_AliasDecl.ed_AssExp != NULL);
1532                                         /*
1533                                          * NOTE: exLhs must be NULL if exp is
1534                                          * unresolved.  exp tree duplications
1535                                          * do not duplicate the alias's exLHS
1536                                          * even though UNARY is set.
1537                                          */
1538                                         dassert_exp(exp, exRhs->ex_Lhs == NULL);
1539                                         exRhs->ex_Flags |= EXF_ALIAS | EXF_UNARY;
1540                                         exRhs->ex_Lhs = DupExp(sg2,
1541                                                            d->d_AliasDecl.ed_AssExp);
1542                                         exRhs->ex_Lhs = resolveExp(isg, sg2,
1543                                                                 exRhs->ex_Lhs,
1544                                                                 exType,
1545                                                                 flags | RESOLVE_AUTOCAST);
1546                                         break;
1547                                 case DOP_ARGS_STORAGE:
1548                                 case DOP_STACK_STORAGE:
1549                                 case DOP_GLOBAL_STORAGE:
1550                                 case DOP_GROUP_STORAGE:
1551                                         /*
1552                                          * Set type.  The Rhs is a STRUCT_ID
1553                                          * and does not require a type to be
1554                                          * assigned to it.
1555                                          *
1556                                          * Return type is always an LVALUE,
1557                                          * parent may adjust.
1558                                          */
1559                                         exType = ADD_LVALUE(d->d_StorDecl.ed_Type);
1560                                         break;
1561                                 case DOP_TYPEDEF:
1562                                         /*
1563                                          * XXX make sure this is only used
1564                                          * in the lhs of a structural
1565                                          * reference. XXX
1566                                          *
1567                                          * XXX what if we went through a
1568                                          * TY_RETO type?  This type will
1569                                          * be wrong.
1570                                          *
1571                                          * collapse the exp node.
1572                                          */
1573                                         exType = d->d_TypedefDecl.ed_Type;
1574                                         exToken = TOK_DECL;
1575                                         exFlags &= ~EXF_BINARY;
1576                                         break;
1577                                 case DOP_IMPORT:
1578                                         /*
1579                                          * Do not collapse an import, we
1580                                          * require more resolution.  e.g.
1581                                          * import.<blah> will be collapsed,
1582                                          * but 'import' cannot be.
1583                                          */
1584                                         if (exFlags & EXF_REQ_TYPE) {
1585                                                 exType =
1586                         AllocImportType(
1587                                 &d->d_ImportDecl.ed_SemGroup->sg_ClassList,
1588                                 d->d_ImportDecl.ed_SemGroup,
1589                                 visibility);
1590                                                 exFlags |= EXF_RET_TYPE;
1591                                                 break;
1592                                         }
1593                                         break;
1594                                 case DOP_CLASS:
1595                                         /*
1596                                          * Do not collapse a class, we require
1597                                          * more resolution.  e.g. class.<blah>
1598                                          * will be collapsed, but 'class'
1599                                          * cannot be.
1600                                          */
1601                                         if (exFlags & EXF_REQ_TYPE) {
1602                                                 exType =
1603                         AllocClassType(
1604                                 &d->d_ClassDecl.ed_SemGroup->sg_ClassList,
1605                                 d->d_ClassDecl.ed_Super,
1606                                 d->d_ClassDecl.ed_SemGroup,
1607                                 visibility);
1608                                                 exFlags |= EXF_RET_TYPE;
1609                                                 break;
1610                                         }
1611                                         break;
1612                                 default:
1613                                         dassert_exp(exp, 0);
1614                                         break;
1615                                 }
1616                                 if (d->d_Op == DOP_PROC) {
1617                                         if (d->d_ScopeFlags & SCOPE_PURE)
1618                                                 couldconst = 1;
1619                                 } else if (exType->ty_SQFlags & SF_CONST) {
1620                                         couldconst = 1;
1621                                 }
1622
1623                         } else if ((s = StrTableSpecial(id)) &
1624                                    SPECIALF_SEMGROUP) {
1625                                 /*
1626                                  * Identifier not found, check for a special
1627                                  * identifier.
1628                                  */
1629                                 exRhs->ex_Token = TOK_SEMGRP_ID;
1630                                 exRhs->ex_Int32 = s;
1631                                 exDecl = NULL;
1632
1633                                 switch(s) {
1634                                 case SPECIAL_NULL:
1635                                         dassert(type->ty_Op == TY_PTRTO || 
1636                                                 type->ty_Op == TY_REFTO ||
1637                                                 type->ty_Op == TY_CPTRTO);
1638                                         /* NULL is not an lvalue */
1639                                         exType = DEL_LVALUE(type);
1640                                         exFlags |= EXF_NULL;
1641                                         break;
1642                                 case SPECIAL_COUNT:
1643                                         dassert(type->ty_Op != TY_PTRTO && 
1644                                                 type->ty_Op != TY_REFTO &&
1645                                                 type->ty_Op != TY_CPTRTO);
1646                                         exType = &Int32Type;
1647                                         break;
1648                                 case SPECIAL_DATA:
1649                                         /*
1650                                          * typeof(self.__data[]) vs
1651                                          * (cast)self.__data[]
1652                                          */
1653                                         dassert(type->ty_Op != TY_PTRTO &&
1654                                                 type->ty_Op != TY_REFTO &&
1655                                                 type->ty_Op != TY_CPTRTO);
1656                                         dassert(exFlags & EXF_REQ_ARRAY);
1657                                         exFlags |= EXF_RET_ARRAY;
1658                                         if (exFlags & EXF_REQ_TYPE) {
1659                                                 exFlags |= EXF_RET_TYPE;
1660                                                 exType = &DynamicLValueType;
1661                                         } else if (itype) {
1662                                                 exType = itype;
1663                                         } else {
1664                                                 /*
1665                                                  * dynamic data must be cast
1666                                                  */
1667                                                 dassert_exp(exp, 0);
1668                                                 exType = &DynamicLValueType;
1669                                         }
1670                                         break;
1671                                 case SPECIAL_VAR_COUNT:
1672                                         dassert(type->ty_Op != TY_PTRTO &&
1673                                                 type->ty_Op != TY_REFTO &&
1674                                                 type->ty_Op != TY_CPTRTO);
1675                                         exType = &Int32Type;
1676                                         break;
1677                                 case SPECIAL_VAR_DATA:
1678                                         /*
1679                                          * typeof(self.__vardata[]) vs
1680                                          * (cast)self.__vardata[]
1681                                          */
1682                                         dassert(type->ty_Op != TY_PTRTO &&
1683                                                 type->ty_Op != TY_REFTO &&
1684                                                 type->ty_Op != TY_CPTRTO);
1685                                         dassert(exFlags & EXF_REQ_ARRAY);
1686                                         exFlags |= EXF_RET_ARRAY;
1687                                         if (exFlags & EXF_REQ_TYPE) {
1688                                                 exFlags |= EXF_RET_TYPE;
1689                                                 exType = &DynamicLValueType;
1690                                         } else if (itype) {
1691                                                 exType = itype;
1692                                         } else {
1693                                                 /*
1694                                                  * dynamic data must be cast
1695                                                  */
1696                                                 dassert_exp(exp, 0);
1697                                                 exType = &DynamicLValueType;
1698                                         }
1699                                         break;
1700                                 case SPECIAL_TYPEID:
1701                                         exType = &Int32Type;
1702                                         break;
1703                                 case SPECIAL_TYPESTR:
1704                                         exType = &StrType;
1705                                         break;
1706                                 default:
1707                                         dassert_exp(exRhs, 0);
1708                                         break;
1709                                 }
1710                         } else {
1711                                 /*
1712                                  * This is nasty, I admit.  If we have a
1713                                  * pointer or reference type try again.
1714                                  */
1715                                 exDecl = NULL;
1716                                 if (type->ty_Op == TY_PTRTO) {
1717                                         type = type->ty_PtrType.et_Type;
1718                                         procedureOnly = 1;
1719                                         goto again;
1720                                 }
1721                                 if (type->ty_Op == TY_REFTO) {
1722                                         type = type->ty_RefType.et_Type;
1723                                         procedureOnly = 1;
1724                                         goto again;
1725                                 }
1726                                 if (type->ty_Op == TY_CPTRTO) {
1727                                         type = type->ty_CPtrType.et_Type;
1728                                         procedureOnly = 1;
1729                                         goto again;
1730                                 }
1731                                 ExpFatalError(exRhs, eno);
1732                                 /* NOT REACHED */
1733                         }
1734                 }
1735                 dassert_exp(exp, exType != NULL);
1736                 break;
1737         case TOK_STRUCT_ID:
1738                 /*
1739                  * NOTE: unresolved identifiers should not have alias
1740                  *       expression sub-tree duplications attached to them.
1741                  *       assert it.
1742                  */
1743                 dassert_exp(exp, exLhs == NULL);
1744                 break;
1745         case TOK_OPER:
1746                 /*
1747                  * NOTE: LVALUE/RVALUE for elements and return type depends
1748                  *       on the operator.  Operator functions normally
1749                  *       self-optimize the cases at run-time.
1750                  */
1751                 couldconst = 1;
1752                 saveExpCopy(&copy, exp);
1753                 exp = resolveExpOper(isg, sg, exp, itype,
1754                                      flags & ~RESOLVE_AUTOCAST);
1755                 loadExpCopy(&copy, exp);
1756                 break;
1757         case TOK_PTRIND:
1758                 /*
1759                  * Indirect through an expression.
1760                  *
1761                  * Return type is typically an LVALUE (if representing
1762                  * storage).  Exp parent might turn it off so run-time
1763                  * must test.  Lhs may or may not be.
1764                  */
1765                 {
1766                         Type *type;
1767
1768                         exLhs = resolveExp(isg, sg, exLhs, NULL,
1769                                            flags & ~RESOLVE_AUTOCAST);
1770                         type = exLhs->ex_Type;
1771
1772                         switch(type->ty_Op) {
1773                         case TY_REFTO:
1774                                 if ((exFlags & EXF_INDREF) == 0) {
1775                                         fprintf(stderr, "You cannot use '*' on a reference type\n");
1776                                         dassert_exp(exLhs, 0);
1777                                 }
1778                                 exType = ADD_LVALUE(type->ty_RefType.et_Type);
1779                                 break;
1780                         case TY_PTRTO:
1781                                 exType = ADD_LVALUE(type->ty_PtrType.et_Type);
1782                                 break;
1783                         case TY_CPTRTO:
1784                                 exType = ADD_LVALUE(type->ty_CPtrType.et_Type);
1785                                 break;
1786                         default:
1787                                 dassert_exp(exLhs, 0);
1788                                 break;
1789                         }
1790                 }
1791                 break;
1792         case TOK_ADDR:
1793                 /*
1794                  * Take the address of an (LVALUE) expression.  Returns an
1795                  * RVALUE.   Allow for a short-cut optimization which replaces
1796                  * the TOK_ADDR sequence with its argument in the &ary[n]
1797                  * case.
1798                  */
1799                 {
1800                         Type *type;
1801
1802                         /*
1803                          * note: hint must 'always happen' since we may be
1804                          * modifying an expression that will later be Dup'd.
1805                          */
1806                         exLhs->ex_Flags |= EXF_REQ_ADDROF;
1807                         exLhs->ex_Flags |= EXF_ADDRUSED;
1808                         exLhs = resolveExp(isg, sg, exLhs, NULL,
1809                                            flags & ~RESOLVE_AUTOCAST);
1810                         if (exLhs->ex_Flags & EXF_RET_ADDROF) {
1811                                 exp = exLhs;
1812                                 loadExpCopy(&copy, exp);
1813                         } else {
1814                                 type = exLhs->ex_Type;
1815                                 dassert_exp(exLhs,
1816                                             type->ty_SQFlags & SF_LVALUE);
1817                                 exType = RESOLVETYPE(TypeToPtrType(type));
1818                                 /* DEL_LVALUE() not needed here */
1819                         }
1820                 }
1821                 break;
1822         case TOK_OBRACKET:
1823                 /*
1824                  * Array index, takes an RVALUE, returns an LVALUE.
1825                  *
1826                  * Note: we have to convert the special __data[exp] case.
1827                  *
1828                  * Note: ex_Flags hints must 'always happen' since we may be
1829                  *       modifying an expression that will later be Dup'd.
1830                  */
1831                 exRhs = resolveExp(isg, sg, exRhs, NULL,
1832                                    flags & ~RESOLVE_AUTOCAST);
1833                 exLhs->ex_Flags |= EXF_REQ_ARRAY | (exFlags & EXF_REQ_TYPE);
1834                 exLhs->ex_Flags |= EXF_ADDRUSED;
1835                 exLhs->ex_AuxExp = exRhs;
1836                 exLhs = resolveExp(isg, sg, exLhs, itype,
1837                                    flags & ~RESOLVE_AUTOCAST);
1838
1839                 if (MatchType(&IntegralType, exRhs->ex_Type) <= SG_COMPAT_PART) {
1840                         ExpPrintError(exRhs, TOK_ERR_EXPECTED_INTEGRAL_TYPE);
1841                         dassert_exp(exp, 0);
1842                 }
1843
1844                 if (exLhs->ex_Flags & EXF_RET_ARRAY) {
1845                         /*
1846                          * __data and __vardata specials
1847                          */
1848                         exp->ex_Token = TOK_ERR_EXP_REMOVED;
1849                         return(exLhs);
1850                 } else if (exFlags & EXF_REQ_ADDROF) {
1851                         /*
1852                          * &ary[i] optimization - allows us to create
1853                          * a bounded pointer (returns an RVALUE).
1854                          */
1855                         Type *type;
1856
1857                         exFlags |= EXF_RET_ADDROF;
1858
1859                         dassert((exLhs->ex_Flags & EXF_RET_TYPE) == 0);
1860
1861                         exLhs->ex_AuxExp = NULL;
1862                         type = exLhs->ex_Type;
1863                         switch(type->ty_Op) {
1864                         case TY_ARYOF:
1865                                 type = type->ty_AryType.et_Type;
1866                                 break;
1867                         case TY_CPTRTO:
1868                                 type = type->ty_CPtrType.et_Type;
1869                                 break;
1870                         case TY_PTRTO:
1871                                 type = type->ty_PtrType.et_Type;
1872                                 break;
1873                         case TY_REFTO:
1874                                 /* Cannot take address of a reference type */
1875                                 dassert_exp(exp, 0);
1876                                 break;
1877                         }
1878                         exType = RESOLVETYPE(TypeToPtrType(type));
1879                         /* returns an RVALUE */
1880                 } else {
1881                         /*
1882                          * Unoptimized array lookup, returns an lvalue
1883                          */
1884                         Type *type;
1885
1886                         dassert((exLhs->ex_Flags & EXF_RET_TYPE) == 0);
1887
1888                         exLhs->ex_AuxExp = NULL;
1889                         type = exLhs->ex_Type;
1890                         switch(type->ty_Op) {
1891                         case TY_ARYOF:
1892                                 type = type->ty_AryType.et_Type;
1893                                 break;
1894                         case TY_CPTRTO:
1895                                 type = type->ty_CPtrType.et_Type;
1896                                 break;
1897                         case TY_PTRTO:
1898                                 type = type->ty_PtrType.et_Type;
1899                                 break;
1900                         case TY_REFTO:
1901                                 fprintf(stderr,
1902                                         "Cannot index a reference type\n");
1903                                 dassert_exp(exp, 0);
1904                                 break;
1905                         }
1906                         exType = ADD_LVALUE(type);
1907                         /* returns an LVALUE */
1908                 }
1909                 break;
1910         case TOK_OPAREN:
1911                 dassert_exp(exp, 0);    /* XXX */
1912                 break;
1913         case TOK_DSTRING:
1914         case TOK_BSTRING:
1915                 /*
1916                  * XXX we should return a bounded pointer here.
1917                  */
1918                 exType = &StrType;
1919                 exId = StrTableEscapeQuotedString(exId, strlen(exId), 1);
1920                 ReplaceStrTable(&exp->ex_Id, exId);
1921                 break;
1922         case TOK_SSTRING:
1923                 couldconst = 1;
1924                 exFlags |= EXF_CONST;
1925                 exType = &UInt8Type;    /* XXX make wide? */
1926                 exId = StrTableEscapeQuotedString(exId, strlen(exId), 0);
1927                 dassert(StrTableLen(exId) == 1);
1928                 ReplaceStrTable(&exp->ex_Id, exId);
1929                 break;
1930         case TOK_INTEGER:
1931                 couldconst = 1;
1932                 {
1933                         char *ptr;
1934                         int size = 4;
1935
1936                         strtol(exp->ex_Id, &ptr, 0);
1937                         while (*ptr) {
1938                                 switch(*ptr) {
1939                                 case 'u':
1940                                 case 'U':
1941                                         size |= 0x1000;
1942                                         break;
1943                                 case 's':
1944                                 case 'S':
1945                                         size &= ~0xFFF;
1946                                         break;
1947                                 case 'b':
1948                                 case 'B':
1949                                         size = (size & ~0xFFF) | 1;
1950                                         break;
1951                                 case 'w':
1952                                 case 'W':
1953                                         size = (size & ~0xFFF) | 2;
1954                                         break;
1955                                 case 'i':
1956                                 case 'I':
1957                                         size = (size & ~0xFFF) | 4;
1958                                         break;
1959                                 case 'l':
1960                                 case 'L':
1961                                         size = (size & ~0xFFF) | 8;
1962                                         break;
1963                                 case 'x':
1964                                 case 'X':
1965                                         size = (size & ~0xFFF) | 16;
1966                                         break;
1967                                 case 'z':
1968                                 case 'Z':
1969                                         size = (size & ~0xFFF) |
1970                                         sizeof(runesize_t);
1971                                         break;
1972                                 default:
1973                                         ExpFatalError(exp,
1974                                                       TOK_ERR_ILLEGAL_SUFFIX);
1975                                         /* NOT REACHED */
1976                                         break;
1977                                 }
1978                                 ++ptr;
1979                         }
1980                         switch(size) {
1981                         case 1:
1982                                 exType = &Int8Type;
1983                                 break;
1984                         case 2:
1985                                 exType = &Int16Type;
1986                                 break;
1987                         case 4:
1988                                 exType = &Int32Type;
1989                                 break;
1990                         case 8:
1991                                 exType = &Int64Type;
1992                                 break;
1993                         case 16:
1994                                 exType = &Int128Type;
1995                                 break;
1996                         case 0x1000 | 1:
1997                                 exType = &UInt8Type;
1998                                 break;
1999                         case 0x1000 | 2:
2000                                 exType = &UInt16Type;
2001                                 break;
2002                         case 0x1000 | 4:
2003                                 exType = &UInt32Type;
2004                                 break;
2005                         case 0x1000 | 8:
2006                                 exType = &UInt64Type;
2007                                 break;
2008                         case 0x1000 | 16:
2009                                 exType = &UInt128Type;
2010                                 break;
2011                         default:
2012                                 exType = &Int32Type;
2013                                 break;
2014                         }
2015                 }
2016                 exFlags |= EXF_CONST;
2017                 break;
2018         case TOK_FLOAT:
2019                 couldconst = 1;
2020                 {
2021                         char *ptr;
2022
2023                         exType = &Float64Type;
2024
2025                         strtod(exp->ex_Id, &ptr);
2026                         while (*ptr) {
2027                                 switch(*ptr) {
2028                                 case 'f':
2029                                 case 'F':
2030                                         exType = &Float32Type;
2031                                         break;
2032                                 case 'd':
2033                                 case 'D':
2034                                         exType = &Float64Type;
2035                                         break;
2036                                 case 'x':
2037                                 case 'X':
2038                                         exType = &Float128Type;
2039                                         break;
2040                                 }
2041                                 ++ptr;
2042                         }
2043                 }
2044                 exFlags |= EXF_CONST;
2045                 break;
2046         case TOK_VOIDEXP:
2047                 exType = &VoidType;
2048                 break;
2049         case TOK_SELF:
2050                 /*
2051                  * The self identifier represents the current procedure's
2052                  * arguments.  A varargs procedure will actually be called
2053                  * with an extended version of this type, but for resolution
2054                  * purposes we can use this time.
2055                  *
2056                  * This is an LVALUE to support things like self.new() XXX.
2057                  */
2058                 exType = ADD_LVALUE(resolveArgsType(sg, flags));
2059                 break;
2060         case TOK_DOLLAR:
2061                 /*
2062                  * The '$' identifier represents the current procedure's
2063                  * return storage.
2064                  */
2065                 exType = ADD_LVALUE(resolveReturnType(sg, flags));
2066                 break;
2067         case TOK_ID:
2068         case TOK_CLASSID:
2069                 /*
2070                  * Lookup the identifier.  The returned declaration could 
2071                  * represent a class, typedef, module, or storage, but for
2072                  * this case we only allow storage or a constant.  Since
2073                  * we are starting from our own semantic group, visibility
2074                  * is initially ALL (private, library, and public).
2075                  *
2076                  * The identifier might represent something at a higher scoping
2077                  * layer.  For example, a nested procedure accessing a variable
2078                  * in the parent procedure or a method procedure in a class
2079                  * accessing an element of the object.
2080                  *
2081                  * It is also possible for the current execution scoping layer
2082                  * (sg) to have a secondary contextual layer from which global
2083                  * constants can be accessed.  This is typically set when
2084                  * resolving procedure arguments for procedures called through
2085                  * objects or types.  Only type globals can be accesed via
2086                  * this shortcut.
2087                  *
2088                  * This returns an LVALUE if the id represents storage.
2089                  */
2090                 {
2091                         string_t ary[2];
2092                         int eno = TOK_ERR_ID_NOT_FOUND;
2093
2094                         exDecl = NULL;
2095
2096                         /*
2097                          * Special case 'super'. XXX TY_REFTO
2098                          *
2099                          * Make an in-place change to the expression
2100                          * structure.  'super' is actually 'this' with the
2101                          * EXF_SUPER flag set.
2102                          */
2103                         if (exId == String_Super) {
2104                                 exId = String_This;
2105                                 ReplaceStrTable(&exp->ex_Id, exId);
2106                                 exFlags |= EXF_SUPER;
2107                         }
2108                         ary[0] = exp->ex_Id;
2109                         ary[1] = NULL;
2110
2111                         exDecl = FindDeclPath(&exp->ex_LexRef, isg, sg,
2112                                               NULL, ary,
2113                                               FDC_NULL, &exVisibility,
2114                                               -1, &eno);
2115                         if (exDecl == NULL) {
2116                                 exDecl = FindDeclPathAltContext(
2117                                                       &exp->ex_LexRef, isg, sg,
2118                                                       NULL, ary,
2119                                                       FDC_NULL, &exVisibility,
2120                                                       -1, &eno);
2121                         }
2122                         if (exDecl == NULL) {
2123                                 ExpPrintError(exp, eno);
2124                                 dassert_exp(exp, 0);
2125                         }
2126
2127                         /*
2128                          * The EXF flag is set by TOK_ADDR, possibly
2129                          * propagated down via TOK_DOT.  Use this to flag
2130                          * that the stack context might be used outside of
2131                          * its normal life.  LValue scoped declarations do
2132                          * not count because they have their own RefStor.
2133                          *
2134                          * (This code is primarily responsible for causing
2135                          * SRSGET and SRSPUT instructions to be emitted).
2136                          */
2137                         if ((exFlags & EXF_REQ_ADDROF) &&
2138                             (exDecl->d_Scope.s_Flags & SCOPE_LVALUE) == 0) {
2139                                 exDecl->d_MyGroup->sg_Flags |= SGF_ADDRUSED;
2140                         }
2141
2142                         /*
2143                          * Try to delay resolving the procedure declaration
2144                          * (which will resolve the procedure body).  We cannot
2145                          * delay the resolution if resolving a constant
2146                          * that the resolver needs immediately.
2147                          */
2148                         if (flags & RESOLVE_CONSTEXP) {
2149                                 resolveDecl(exDecl, flags);
2150                         }
2151                 }
2152
2153                 /*
2154                  * Taking the address of content-locked storage is illegal.
2155                  *
2156                  * If we are running through an LValueStor
2157                  * UNLOCKED applies to it and not its contents.
2158                  * Check to see if the contents are acceptable.
2159                  */
2160                 if ((exFlags & EXF_REQ_ADDROF) &&
2161                    (exDecl->d_Scope.s_Flags & SCOPE_UNLOCKED) == 0) {
2162                         Type *type = exDecl->d_StorDecl.ed_Type;
2163                         if ((type->ty_Flags & TF_HASLVPTR) && 
2164                             type->ty_Op != TY_CLASS &&
2165                             type->ty_Op != TY_ARYOF) {
2166                                 ExpPrintError(exp,
2167                                             TOK_ERR_ILLEGAL_ADDRLOCKED);
2168                                 dassert_exp(exp, 0);
2169                         }
2170                 }
2171
2172                 switch(exDecl->d_Op) {
2173                 case DOP_ARGS_STORAGE:
2174                 case DOP_STACK_STORAGE:
2175                 case DOP_GLOBAL_STORAGE:
2176                 case DOP_GROUP_STORAGE:
2177                         /*
2178                          * Storage identifiers are lvalues.
2179                          *
2180                          * Try to delay this step, giving the language more
2181                          * flexibility in avoiding resolver loops from
2182                          * interdependencies that can cause it to fail.
2183                          *
2184                          * We can't delay this step when resolving an
2185                          * expression that the resolver needs an actual
2186                          * constant result for.
2187                          */
2188                         exType = ADD_LVALUE(exDecl->d_StorDecl.ed_Type);
2189                         if (exDecl->d_Op == DOP_STACK_STORAGE &&
2190                             (exFlags & EXF_ADDRUSED)) {
2191                                 exDecl->d_Flags |= DF_ADDRUSED;
2192                         }
2193                         if (exType->ty_SQFlags & SF_CONST)
2194                                 couldconst = 1;
2195                         if (flags & RESOLVE_CONSTEXP) {
2196                                 Exp **asexpp = &exDecl->d_StorDecl.ed_AssExp;
2197                                 if (*asexpp) {
2198                                         *asexpp = DupExp(sg, *asexpp);
2199                                         *asexpp = resolveExp(isg, sg, *asexpp,
2200                                                              DEL_LVALUE(exType),
2201                                                      flags | RESOLVE_AUTOCAST);
2202                                         *asexpp = SetDupExp(sg, *asexpp);
2203                                 }
2204                         }
2205                         break;
2206                 case DOP_ALIAS:
2207                         /*
2208                          * Aliases are rvalues (even if they could be lvalues).
2209                          */
2210                         exType = DEL_LVALUE(exDecl->d_AliasDecl.ed_Type);
2211                         exFlags |= EXF_ALIAS | EXF_UNARY;
2212
2213                         /*
2214                          * NOTE: exLhs must be NULL if exp is unresolved.
2215                          *       exp tree duplications do not duplicate
2216                          *       the alias's exLHS even though UNARY is set.
2217                          */
2218                         dassert_exp(exp, exLhs == NULL);
2219                         exLhs = DupExp(sg, exDecl->d_AliasDecl.ed_AssExp);
2220                         exLhs = resolveExp(isg, sg, exLhs, exType,
2221                                            flags | RESOLVE_AUTOCAST);
2222
2223                         /*
2224                          * Inherit EXF_NULL (NULL pointer special) through
2225                          * the alias, otherwise it will not be assignable
2226                          * to arbitrary pointers.
2227                          */
2228                         exFlags |= exLhs->ex_Flags & EXF_NULL;
2229                         break;
2230
2231                 case DOP_PROC:
2232                         /*
2233                          * A procedural identifier.
2234                          *
2235                          * Note: procedural pointers cannot be changed so
2236                          *       they are not lvalues.
2237                          */
2238                         dassert_exp(exp, (exFlags & EXF_REQ_PROC));
2239                         exType = exDecl->d_ProcDecl.ed_Type;
2240                         if (exDecl->d_ScopeFlags & SCOPE_PURE)
2241                                 couldconst = 1;
2242                         break;
2243                 case DOP_TYPEDEF:
2244                         if (exFlags & EXF_REQ_TYPE) {
2245                                 exType = exDecl->d_TypedefDecl.ed_Type;
2246                                 exFlags |= EXF_RET_TYPE;
2247                                 break;
2248                         }
2249                         dassert_exp(exp, 0);
2250                         break;
2251                 case DOP_CLASS:
2252                         if (exFlags & EXF_REQ_TYPE) {
2253                                 exType =
2254                     AllocClassType(
2255                             &exDecl->d_ClassDecl.ed_SemGroup->sg_ClassList,
2256                             exDecl->d_ClassDecl.ed_Super,
2257                             exDecl->d_ClassDecl.ed_SemGroup,
2258                             exVisibility);
2259                                 exFlags |= EXF_RET_TYPE;
2260                                 break;
2261                         }
2262                         dassert_exp(exp, 0);
2263                         break;
2264                 case DOP_IMPORT:
2265                         if (exFlags & EXF_REQ_TYPE) {
2266                                 exType =
2267                     AllocImportType(
2268                             &exDecl->d_ImportDecl.ed_SemGroup->sg_ClassList,
2269                             exDecl->d_ImportDecl.ed_SemGroup,
2270                             exVisibility);
2271                                 exFlags |= EXF_RET_TYPE;
2272                                 break;
2273                         }
2274                         dassert_exp(exp, 0);
2275                         break;
2276                 default:
2277                         dassert_exp(exp, 0);
2278                 }
2279                 break;
2280         case TOK_NOT:
2281                 /*
2282                  * NOTE: BoolType global implies an rvalue.
2283                  */
2284                 couldconst = 1;
2285                 exLhs = resolveExp(isg, sg, exLhs, &BoolType,
2286                                    flags | RESOLVE_AUTOCAST);
2287                 break;
2288         case TOK_TYPE:
2289                 if (exFlags & EXF_REQ_TYPE) {
2290                         exType = RESOLVETYPE(exType);
2291                         exFlags |= EXF_RET_TYPE;
2292                 } else {
2293                         dassert_exp(exp, 0);
2294                 }
2295                 break;
2296         case TOK_CAST:
2297                 /*
2298                  * User cast (or maybe the parser inserted it).  Try to
2299                  * resolve the expression with the requested type hint
2300                  * but tell resolveExp() not to force the cast.
2301                  *
2302                  * Then check the result.  If resolveExp() was not able to
2303                  * optimize the requested cast then resolve the cast.
2304                  *
2305                  * If the types are compatible we still keep the TOK_CAST
2306                  * node in place for the moment.  XXX we really need to
2307                  * formalized how ex_Type is set Similar vs Exact.
2308                  *
2309                  * NOTE: Cast results are always an RVALUE.  XXX validate here.
2310                  */
2311                 couldconst = 1;
2312                 if ((exFlags & EXF_PARSE_TYPE) == 0) {
2313                         exRhs->ex_Flags |= EXF_REQ_TYPE;
2314                         exRhs = resolveExp(isg, sg, exRhs, NULL,
2315                                            flags & ~RESOLVE_AUTOCAST);
2316                         exType = exRhs->ex_Type;
2317                 }
2318                 exLhs = resolveExp(isg, sg, exLhs, exType,
2319                                    flags & ~RESOLVE_AUTOCAST);
2320                 if (SimilarType(exType, exLhs->ex_Type) == 0) {
2321                         saveExpCopy(&copy, exp);
2322                         exp = resolveExpCast(isg, sg, exLhs, exType, flags);
2323                         loadExpCopy(&copy, exp);
2324                 }
2325 #if 0
2326                 /* propagate NULL flag to allow cast to any pointer type */
2327                 if (exLhs->ex_Flags & EXF_NULL)
2328                         printf("LHS NULL\n");
2329                 exp->ex_Flags |= exLhs->ex_Flags & EXF_NULL;
2330 #endif
2331                 break;
2332         case TOK_CALL:
2333                 /*
2334                  * Calls require the RHS to be a compound expression
2335                  * representing the procedure arguments.
2336                  *
2337                  * XXX deal with pointer-to-function verses function
2338                  * XXX the lhs must at the moment resolve to the procedure
2339                  * itself.
2340                  *
2341                  * In regards to procedure pointers, the declaration
2342                  * will require a pointer to the procedure's statement
2343                  * body.  XXX this pointer can be the physical storage
2344                  * associated with the lhs data but thus requires the
2345                  * type to be a pointer.  We do not support the 'C'
2346                  * (*ptr_to_func)(...) form.  You have to use ptr_to_func(...).
2347                  */
2348                 {
2349                         Type *ltype;
2350                         Type *atype;            /* type for alt context */
2351                         SemGroup *save_asg;     /* save old alt context */
2352
2353                         dassert_exp(exRhs, exRhs->ex_Token == TOK_COMPOUND);
2354
2355                         /*
2356                          * Note: ex_Flags hints must 'always happen' since
2357                          * we may be modifying an expression that will later
2358                          * be Dup'd.
2359                          */
2360                         exLhs->ex_Flags |= EXF_REQ_PROC;
2361                         exLhs = resolveExp(isg, sg, exLhs, NULL,
2362                                            flags & ~RESOLVE_AUTOCAST);
2363                         ltype = exLhs->ex_Type;
2364 #if 0
2365                         if (ltype->ty_Op == TY_PTRTO)
2366                                 ltype = type->ty_PtrType.et_Type; /* XXX */
2367 #endif
2368 #if 0
2369                         dassert_exp(exLhs, exLhs->ex_Token == TOK_DECL ||
2370                                            exLhs->ex_Token == TOK_ID);
2371 #endif
2372                         dassert_exp(exLhs, ltype != NULL &&
2373                                            ltype->ty_Op == TY_PROC);
2374                         dassert_exp(exLhs, exLhs->ex_Decl != NULL);
2375                         dassert_exp(exRhs, exRhs->ex_Token == TOK_COMPOUND);
2376
2377                         /*
2378                          * If the lhs type indicates a method procedure, then
2379                          * it's lhs is the object we wish to pass as the
2380                          * first argument to the method.  We move the lhs lhs
2381                          * exp.  For a STRIND TY_PTRTO method call we
2382                          * indirect the element and convert it to a TOK_DOT
2383                          * lvalue argument of the underlying object.
2384                          *
2385                          * A method call via a reference object is a very
2386                          * weird case.
2387                          *
2388                          * Since the method called through an object winds up
2389                          * being a method taylored for that object, and we
2390                          * are calling through a reference to an object,
2391                          * the actual method will be looked up at run time
2392                          * and will match the object.  Thus we can safely
2393                          * indirect through the reference object for this
2394                          * one case.  Since (*ref_obj) is not normally
2395                          * allowed this will be special-cased at
2396                          * compile/run-time.
2397                          *
2398                          * Note that this occurs before we evaluate the
2399                          * compound expression on the right hand side.  Also
2400                          * note that since the resolver can be called multiple
2401                          * times on a shared expression, we have to be
2402                          * careful to shift the arguments around only once.
2403                          */
2404                         if ((ltype->ty_SQFlags & SF_METHOD) && 
2405                             (exRhs->ex_Flags & EXF_CALL_CONV) == 0
2406                         ) {
2407                                 Exp *obj;
2408
2409                                 exRhs->ex_Flags |= EXF_CALL_CONV;
2410
2411                                 switch(exLhs->ex_Token) {
2412                                 case TOK_STRIND:        /* indirect */
2413                                         obj = exLhs->ex_Lhs;
2414                                         if (methodProcThisIsPointer(ltype)) {
2415                                                 ;
2416                                         } else if (obj->ex_Type->ty_Op ==
2417                                                    TY_PTRTO) {
2418                                                 Exp *nexp = AllocExp(NULL);
2419
2420                                                 nexp->ex_Lhs = obj;
2421                                                 nexp->ex_Token = TOK_PTRIND;
2422                                                 nexp->ex_Type = ADD_LVALUE(obj->ex_Type->ty_PtrType.et_Type);
2423                                                 nexp->ex_Flags |= EXF_RESOLVED |
2424                                                                   EXF_UNARY;
2425                                                 LexDupRef(&obj->ex_LexRef,
2426                                                           &nexp->ex_LexRef);
2427                                                 exLhs->ex_Token = TOK_DOT;
2428                                                 obj = nexp;
2429                                         } else if (obj->ex_Type->ty_Op ==
2430                                                    TY_CPTRTO) {
2431                                                 Exp *nexp = AllocExp(NULL);
2432
2433                                                 nexp->ex_Lhs = obj;
2434                                                 nexp->ex_Token = TOK_PTRIND;
2435                                                 nexp->ex_Type = ADD_LVALUE(obj->ex_Type->ty_CPtrType.et_Type);
2436                                                 nexp->ex_Flags |= EXF_RESOLVED |
2437                                                                   EXF_UNARY;
2438                                                 LexDupRef(&obj->ex_LexRef,
2439                                                           &nexp->ex_LexRef);
2440                                                 exLhs->ex_Token = TOK_DOT;
2441                                                 obj = nexp;
2442                                         } else if (obj->ex_Type->ty_Op ==
2443                                                     TY_REFTO) {
2444                                                 Exp *nexp = AllocExp(NULL);
2445
2446                                                 nexp->ex_Lhs = obj;
2447                                                 nexp->ex_Token = TOK_PTRIND;
2448                                                 nexp->ex_Type = ADD_LVALUE(obj->ex_Type->ty_RefType.et_Type);
2449                                                 nexp->ex_Flags |= EXF_RESOLVED |
2450                                                                   EXF_UNARY |
2451                                                                   EXF_INDREF;
2452                                                 LexDupRef(&obj->ex_LexRef,
2453                                                           &nexp->ex_LexRef);
2454                                                 obj = nexp;
2455                                         } else {
2456                                                 dassert_exp(obj, 0);
2457                                         }
2458                                         break;
2459                                 case TOK_DOT:
2460                                         /*
2461                                          * Pass directly as an lvalue.  If this
2462                                          * is a pointer or reference only the
2463                                          * builtin methods for the Pointer
2464                                          * class are possible.  These methods
2465                                          * require a content-locked pointer.
2466                                          */
2467                                         obj = exLhs->ex_Lhs;
2468                                         if (obj->ex_Type->ty_Op != TY_PTRTO &&
2469                                             obj->ex_Type->ty_Op != TY_REFTO) {
2470                                                 break;
2471                                         }
2472
2473                                         if (obj->ex_Decl == NULL ||
2474                                             (obj->ex_Decl->d_Scope.s_Flags & SCOPE_UNLOCKED)) {
2475                                                 exFlags |= EXF_UNLOCKEDMTH;
2476                                         }
2477                                         break;
2478                                 default:
2479                                         dassert_exp(exp, 0);
2480                                         obj = NULL;
2481                                         break;
2482                                 }
2483
2484                                 /*
2485                                  * Leave the lhs intact, but set the
2486                                  * duplication flag in case things get
2487                                  * nasty later.
2488                                  */
2489                                 exLhs->ex_Lhs = SetDupExp(sg, exLhs->ex_Lhs);
2490                                 obj->ex_Next = exRhs->ex_Lhs;
2491                                 exRhs->ex_Lhs = obj;
2492
2493                                 atype = obj->ex_Type;
2494                         } else {
2495                                 atype = NULL;
2496                         }
2497
2498                         /*
2499                          * Try to set an alternative search context during
2500                          * resolution of the procedure arguments.  This context
2501                          * is only searched if an identifier cannot be found
2502                          * through normal means so local variables and such
2503                          * will override it as the programmer should expect.
2504                          * Since the local semantic stack is under the
2505                          * programmer's control, unexpected collisions should
2506                          * either not occur or be easily fixed.
2507                          */
2508                         if (atype) {
2509                                 switch(atype->ty_Op) {
2510                                 case TY_REFTO:
2511                                         atype = atype->ty_PtrType.et_Type;
2512                                         break;
2513                                 case TY_PTRTO:
2514                                         atype = atype->ty_PtrType.et_Type;
2515                                         break;
2516                                 }
2517                                 if (atype->ty_Op != TY_CLASS)
2518                                         atype = NULL;
2519                         }
2520                         if (atype) {
2521                                 save_asg = sg->sg_AltContext;
2522                                 sg->sg_AltContext = atype->ty_ClassType.et_SemGroup;
2523                         } else {
2524                                 save_asg = NULL;
2525                         }
2526
2527                         /*
2528                          * Resolve the right hand side, which are the
2529                          * procedure arguments as a compound type.  This
2530                          * can get tricky.  XXX
2531                          *
2532                          * NOTE: We inherit the SF_LVALUE flag from the
2533                          *       return type.  Parent might turn it off.
2534                          */
2535                         /*d = exLhs->ex_Decl;*/
2536                         exRhs = resolveExp(isg, sg, exRhs,
2537                                            ltype->ty_ProcType.et_ArgsType,
2538                                            flags | RESOLVE_AUTOCAST);
2539                         exType = ltype->ty_ProcType.et_RetType;
2540                         if (atype) {
2541                                 /*
2542                                  * Restore AltContext after resolving rhs.
2543                                  */
2544                                 sg->sg_AltContext = save_asg;
2545                         } else if ((exRhs->ex_Flags & (EXF_CONST |
2546                                                        EXF_PROBCONST)) &&
2547                                    (exLhs->ex_Decl->d_ScopeFlags & SCOPE_PURE)) {
2548                                 /*
2549                                  * atype NULL (not method call, which requires
2550                                  * an object), arguments can become constants,
2551                                  * pure function, so result can become a
2552                                  * constant.
2553                                  */
2554                                 exFlags |= EXF_PROBCONST;
2555                         }
2556                 }
2557                 break;
2558         case TOK_COMPOUND:
2559                 /*
2560                  * (NOTE EARLY RETURN)
2561                  *
2562                  * A compound expression should always be an RVALUE, but
2563                  * might contain LVALUEs (XXX).
2564                  */
2565                 couldconst = 1;
2566                 exp = resolveCompoundExp(isg, sg, exp, itype, flags);
2567                 return(exp);
2568                 /* not reached */
2569         case TOK_TYPEOF:
2570                 /*
2571                  * The caller must be able to handle a type return when
2572                  * typeof() is used.
2573                  */
2574                 dassert_exp(exp, exFlags & EXF_REQ_TYPE);
2575                 /* fall through */
2576         case TOK_SIZEOF:
2577         case TOK_ARYSIZE:
2578                 /*
2579                  * If an expression was supplied, convert it to a type.
2580                  *
2581                  * NOTE: ex_Flags hints must 'always happen' since we may be
2582                  *       modifying an expression that will later be Dup'd.
2583                  */
2584                 couldconst = 1;
2585                 if ((exFlags & EXF_RET_TYPE) == 0) {
2586                         dassert(exLhs != NULL);
2587                         exLhs->ex_Flags |= EXF_REQ_TYPE;
2588                         exLhs = resolveExp(isg, sg, exLhs, NULL,
2589                                            flags & ~RESOLVE_AUTOCAST);
2590                         exType = exLhs->ex_Type;
2591 #if 1
2592                         /* do not clear EXF_UNARY, messes up tmp exp storage */
2593                         /* exFlags &= ~EXF_UNARY; */
2594 #endif
2595                         exFlags |= EXF_RET_TYPE;
2596                         /* XXX delete the lhs */
2597                 } else {
2598                         exType = RESOLVETYPE(exType);
2599                 }
2600                 switch(exToken) {
2601                 case TOK_SIZEOF:
2602                         exId = StrTableInt(exType->ty_Bytes);
2603                         exp->ex_Token = exToken = TOK_INTEGER;
2604                         exType = &SizeType;
2605                         exFlags &= ~EXF_RET_TYPE;
2606                         exFlags |= EXF_CONST;
2607                         break;
2608                 case TOK_ARYSIZE:
2609                         dassert_exp(exp, exType->ty_Op == TY_ARYOF);
2610                         if (exType->ty_AryType.et_Type->ty_Bytes) {
2611                                 exId = StrTableInt(exType->ty_Bytes /
2612                                         exType->ty_AryType.et_Type->ty_Bytes);
2613                         } else {
2614                                 exId = StrTableInt(0);
2615                         }
2616                         exp->ex_Token = exToken = TOK_INTEGER;
2617                         exType = &SizeType;
2618                         exFlags &= ~EXF_RET_TYPE;
2619                         exFlags |= EXF_CONST;
2620                         /* exLhs = NULL; */
2621                         break;
2622                 case TOK_TYPEOF:
2623                         /* type is returned */
2624                         break;
2625                 }
2626                 break;
2627         default:
2628                 dassert_exp(exp, 0);
2629                 break;
2630         }
2631
2632         /*
2633          * Resolve the type and cast-to-type.
2634          */
2635         if (exType) {
2636                 exType = RESOLVETYPE(exType);
2637                 /* XXX exType was ex_Type */
2638
2639                 /*
2640                  * Special-case compound compatibility issues so the
2641                  * interpreter and code generator do not have to deal with
2642                  * it.
2643                  */
2644                 if ((flags & RESOLVE_AUTOCAST) && itype && 
2645                     itype->ty_Op == TY_COMPOUND &&
2646                     exType->ty_Op != TY_COMPOUND) {
2647                         /*
2648                          * The expression parser might have optimized-out
2649                          * the TOK_COMPOUND wrapper around single-element
2650                          * parenthesized expressions.  Add it back in if
2651                          * the cast target expects a compound expression.
2652                          *
2653                          * XXX Currently hack a SetDupExp() to avoid
2654                          *     re-resolving the already-resolved component.
2655                          */
2656                         SetDupExp(sg, exp);
2657                         saveExpCopy(&copy, exp);
2658                         exp = ExpToCompoundExp(exp, TOK_COMPOUND);
2659                         exp = resolveCompoundExp(isg, sg, exp, itype, flags);
2660                         loadExpCopy(&copy, exp);
2661                 } else
2662                 if ((flags & RESOLVE_AUTOCAST) && itype && 
2663                     itype->ty_Op == TY_CLASS &&
2664                     exType->ty_Op == TY_CLASS &&
2665                     itype != &VoidType &&
2666                     (itype->ty_Flags & (TF_ISBOOL | TF_ISINTEGER |
2667                                         TF_ISFLOATING)) == 0 &&
2668                     (exType->ty_Flags & (TF_ISBOOL | TF_ISINTEGER |
2669                                          TF_ISFLOATING))) {
2670                         /*
2671                          * The expression parser might have optimized-out
2672                          * the TOK_COMPOUND wrapper around single-element
2673                          * parenthesized expressions used in a class iterator
2674                          * (in an assignment).  Add it back in if the
2675                          * itype is a non-core class and exType is a core
2676                          * class.
2677                          *
2678                          * XXX Currently hack a SetDupExp() to avoid
2679                          *     re-resolving the already-resolved component.
2680                          */
2681                         SetDupExp(sg, exp);
2682                         saveExpCopy(&copy, exp);
2683                         exp = ExpToCompoundExp(exp, TOK_COMPOUND);
2684                         exp = resolveCompoundExp(isg, sg, exp, itype, flags);
2685                         loadExpCopy(&copy, exp);
2686                 }
2687
2688                 /*
2689                  * If the type hint did not succeed we may have to cast the
2690                  * expression to the requested type.  Note that if the itype
2691                  * was set as part of an array optimization request which could
2692                  * not be handled, we must ignore itype.
2693                  *
2694                  * Note that SimilarType() will allow exp->ex_Type to be a
2695                  * var-args TY_ARGS, and since the original Rhs of a call
2696                  * is set to the procedure arguments type, VarType.et_Type
2697                  * should match exactly.
2698                  */
2699                 if (itype &&
2700                     (exFlags & (EXF_REQ_ARRAY|EXF_RET_ARRAY)) != EXF_REQ_ARRAY
2701                 ) {
2702                         if ((itype->ty_Flags & TF_RESOLVED) == 0)
2703                                 itype = RESOLVETYPE(itype);
2704                         if ((itype->ty_SQFlags & SF_LVALUE) &&
2705                             (exType->ty_SQFlags & SF_LVALUE) == 0
2706                         ) {
2707                                 /* XXX */
2708                                 fprintf(stderr, "Exp must be an lvalue here\n");
2709                                 dassert_exp(exp, 0);
2710                         }
2711                         if (!SimilarType(itype, exType) &&
2712                             (flags & RESOLVE_AUTOCAST)) {
2713                                 if (exp->ex_Flags & EXF_DUPEXP) {
2714                                         Exp *nexp = AllocExp(NULL);
2715
2716                                         nexp->u = exp->u;
2717                                         LexDupRef(&exp->ex_LexRef,
2718                                                   &nexp->ex_LexRef);
2719                                         exp = nexp;
2720                                         exFlags &= ~EXF_DUPEXP;
2721                                         /*exp = DupExp(sg, exp);*/
2722                                 }
2723                                 exFlags |= EXF_RESOLVED;
2724                                 exp = dupExpCopy(&copy, exp);
2725                                 exp = resolveExpCast(isg, sg, exp, itype,
2726                                                      flags);
2727                                 loadExpCopy(&copy, exp);
2728                         }
2729                 }
2730         }
2731
2732         /*
2733          * Generic constant evaluation flag.  Note that EXF_PROBCONST
2734          * could also be set above (TOK_CALL).
2735          */
2736         if (couldconst &&
2737             (exLhs == NULL || (exLhs->ex_Flags & (EXF_CONST|EXF_PROBCONST))) &&
2738             (exRhs == NULL || (exRhs->ex_Flags & (EXF_CONST|EXF_PROBCONST)))) {
2739                 exFlags |= EXF_PROBCONST;
2740         }
2741
2742         exFlags |= EXF_RESOLVED;
2743         exp = dupExpCopy(&copy, exp);
2744         return(exp);
2745 }
2746
2747 /*
2748  * Resolve an expression for which the resolver needs the result
2749  * immediately.
2750  */
2751 Exp *
2752 resolveConstExp(SemGroup *isg, SemGroup *sg, Exp *exp, int flags)
2753 {
2754 #if 0
2755         Declaration *d;
2756 #endif
2757         flags &= ~RESOLVE_AUTOCAST;
2758
2759         if ((exp->ex_Flags & EXF_RESOLVED) == 0)
2760                 exp = resolveExp(isg, sg, exp, NULL, flags | RESOLVE_CONSTEXP);
2761         if ((exp->ex_Flags & (EXF_CONST | EXF_PROBCONST)) == 0) {
2762                 ExpPrintError(exp, TOK_ERR_EXPECTED_INTEGRER_CONST);
2763                 dassert_exp(exp, 0);
2764         }
2765
2766 #if 0
2767         if (exp->ex_Token != TOK_ID)
2768                 goto done;
2769         d = exp->ex_Decl;
2770         if ((d->d_StorDecl.ed_Type->ty_SQFlags & SF_CONST) == 0)
2771                 goto done;
2772
2773         switch(d->d_Op) {
2774         case DOP_ARGS_STORAGE:
2775         case DOP_STACK_STORAGE:
2776         case DOP_GLOBAL_STORAGE:
2777         case DOP_GROUP_STORAGE:
2778                 exp = d->d_StorDecl.ed_AssExp;
2779                 break;
2780         default:
2781                 break;
2782         }
2783 done:
2784 #endif
2785         /*
2786          * Special interpreter execution to resolve the expression.
2787          */
2788         {
2789                 RunContext ct;
2790                 union {
2791                         int64_t tmpbuf[128];
2792                         float128_t tmpflt[64];
2793                 } u;
2794
2795                 bzero(&ct, sizeof(ct));
2796                 ct.ct_Flags |= CTF_RESOLVING;
2797                 if (sg->sg_TmpBytes < (runesize_t)sizeof(u.tmpbuf) &&
2798                     sg->sg_TmpAlignMask < (runesize_t)sizeof(float128_t))
2799                         ct.ct_TmpData = (char *)u.tmpbuf;
2800                 else
2801                         posix_memalign((void *)&ct.ct_TmpData,
2802                                        sg->sg_TmpAlignMask + 1,
2803                                        sg->sg_TmpBytes);
2804
2805                 ct.ct_TmpBytes = sg->sg_TmpBytes;
2806                 ct.ct_CtxRefStor.rs_Refs = 1;
2807                 (void)exp->ex_Run(&ct, exp);
2808
2809                 if ((exp->ex_Flags & EXF_CONST) == 0) {
2810                         ExpPrintError(exp, TOK_ERR_EXPECTED_INTEGRER_CONST);
2811                         dassert_exp(exp, 0);
2812                 }
2813                 if (ct.ct_TmpData != (char *)u.tmpbuf)
2814                         free(ct.ct_TmpData);
2815         }
2816         return exp;
2817 }
2818
2819 Exp *
2820 resolveConstExpBool(SemGroup *isg, SemGroup *sg, Exp *exp, int flags,
2821                     RunTmpStor *ts)
2822 {
2823         runesize_t tmpbytes;
2824         runesize_t ooffset;
2825         int oflags;
2826
2827         flags &= ~RESOLVE_AUTOCAST;
2828
2829         tmpbytes = 0;
2830         if ((exp->ex_Flags & EXF_RESOLVED) == 0) {
2831                 exp = resolveExp(isg, sg, exp, NULL, flags | RESOLVE_CONSTEXP);
2832         }
2833
2834         /*
2835          * [re]-resolve the storage from 0 so we can execute the expression.
2836          */
2837         oflags = exp->ex_Flags;
2838         ooffset = exp->ex_TmpOffset;
2839         resolveStorageExp(exp, &tmpbytes);
2840         if ((exp->ex_Flags & (EXF_CONST | EXF_PROBCONST)) == 0) {
2841                 ExpPrintError(exp, TOK_ERR_EXPECTED_INTEGRER_CONST);
2842                 dassert_exp(exp, 0);
2843         }
2844
2845         /*
2846          * Special interpreter execution to resolve the expression.
2847          */
2848         {
2849                 RunContext ct;
2850                 RunTmpStor *rts;
2851                 union {
2852                         int64_t tmpbuf[128];
2853                         float128_t tmpflt[64];
2854                 } u;
2855
2856                 bzero(&ct, sizeof(ct));
2857                 ct.ct_Flags |= CTF_RESOLVING;
2858
2859                 /*
2860                  * XXX
2861                  */
2862                 if (tmpbytes < (runesize_t)sizeof(u.tmpbuf))
2863                         ct.ct_TmpData = (char *)u.tmpbuf;
2864                 else
2865                         posix_memalign((void *)&ct.ct_TmpData, 16, tmpbytes);
2866                 ct.ct_TmpBytes = tmpbytes;
2867                 ct.ct_CtxRefStor.rs_Refs = 1;
2868                 rts = exp->ex_Run(&ct, exp).data;
2869
2870                 if ((exp->ex_Flags & EXF_CONST) == 0) {
2871                         ExpPrintError(exp, TOK_ERR_EXPECTED_INTEGRER_CONST);
2872                         dassert_exp(exp, 0);
2873                 }
2874                 ts->ts_Bool = rts->ts_Bool;
2875                 if (ct.ct_TmpData != (char *)u.tmpbuf)
2876                         free(ct.ct_TmpData);
2877         }
2878
2879         /*
2880          * exp is now a constant, restore the original ex_TmpOffset
2881          * for normal execution/operation (the storage may be needed for
2882          * large constants).
2883          */
2884         if (oflags & EXF_TMPRESOLVED) {
2885                 exp->ex_TmpOffset = ooffset;
2886                 resolveStorageExp(exp, &tmpbytes);
2887         } else {
2888                 exp->ex_TmpOffset = -1;
2889         }
2890
2891         return exp;
2892 }
2893
2894 /*
2895  * Extract constant from already-constant-resolved expression.
2896  * resolveConstExp() must have previously been called on exp.
2897  *
2898  * Expression must have already been constant-optimized, meaning
2899  * that we should be able to execute it without a context to access
2900  * the cached results in exp->u.
2901  */
2902 static
2903 int64_t
2904 resolveGetConstExpInt64(Exp *exp)
2905 {
2906         rundata_t data;
2907         int64_t value;
2908
2909         dassert_exp(exp, exp->ex_Token == TOK_INTEGER ||
2910                          (exp->ex_Flags & EXF_CONST));
2911         data = exp->ex_Run(NULL, exp);
2912
2913         if (exp->ex_Type->ty_Flags & TF_ISUNSIGNED) {
2914                 switch(exp->ex_Type->ty_Bytes) {
2915                 case 1:
2916                         value = *(uint8_t *)data.data;
2917                         break;
2918                 case 2:
2919                         value = *(uint16_t *)data.data;
2920                         break;
2921                 case 4:
2922                         value = *(uint32_t *)data.data;
2923                         break;
2924                 case 8:
2925                         value = *(uint64_t *)data.data;
2926                         break;
2927                 default:
2928                         value = 0;
2929                         dassert_exp(exp, 0);
2930                         break;
2931                 }
2932         } else {
2933                 switch(exp->ex_Type->ty_Bytes) {
2934                 case 1:
2935                         value = *(int8_t *)data.data;
2936                         break;
2937                 case 2:
2938                         value = *(int16_t *)data.data;
2939                         break;
2940                 case 4:
2941                         value = *(int32_t *)data.data;
2942                         break;
2943                 case 8:
2944                         value = *(int64_t *)data.data;
2945                         break;
2946                 default:
2947                         value = 0;
2948                         dassert_exp(exp, 0);
2949                         break;
2950                 }
2951         }
2952         return value;
2953 }
2954
2955 /*
2956  * resolveCompoundExp() - resolve a compound expression (called from 
2957  *                        resolveExp() and resolveExpOper()).
2958  *
2959  * Resolve a compound expression.  Compound expressions require
2960  * a compound type to normalize against.  This will work for
2961  * direct assignments, return values, casts, and procedure arguments
2962  * only. 
2963  *
2964  * NOTE: We can't use itype if EXF_REQ_ARRAY is specified because
2965  *       its hinting for the array optimization case, which we cannot do.
2966  *
2967  * Compound expressions may be used in conjuction with types 
2968  * reprsenting classes, compound types, and procedure arguments.  The
2969  * compound expression may contain subclasses of the superclasses expected
2970  * by itype.  This is only allowed if the procedure's body has not yet been
2971  * generated (for example, a method call in a subclass).
2972  *
2973  * Partially resolved operators are typically converted into procedure calls
2974  * and method calls are also partially resolved, so some elements may already 
2975  * be resolved.
2976  *
2977  * XXX named initialization, missing elements (structural
2978  * initialization), and so forth needs to be dealt with.
2979  */
2980 Exp *
2981 resolveCompoundExp(SemGroup *isg, SemGroup *sg, Exp *exp,
2982                    Type *itype, int flags)
2983 {
2984         Exp **pscan;
2985         Exp *scan;
2986         Declaration *d;
2987         SemGroup *sg2;
2988         int varargs = 0;
2989         int isconst = 1;
2990         Type *type;
2991
2992         flags &= ~RESOLVE_AUTOCAST;     /* not applicable to this function */
2993
2994         /*
2995          * Expression dup()ing
2996          */
2997         if (exp->ex_Flags & EXF_DUPEXP) {
2998 #if DUPEXP_DEBUG
2999                 static int count; fprintf(stderr, "DUPEXPC %d\n", ++count);
3000 #endif
3001                 exp = DupExp(sg, exp);
3002         }
3003
3004         if (itype && (exp->ex_Flags & EXF_REQ_ARRAY) == 0)
3005                 exp->ex_Type = itype;
3006
3007         /*
3008          * If we don't have a SemGroup to normalize against, XXX how should
3009          * we normalize the compound expression?
3010          */
3011         if (exp->ex_Type == NULL) {
3012                 dassert_exp(exp, 0);
3013         }
3014
3015         /*
3016          * Normalize the compound expression based on the
3017          * argument types expected by the procedure.  We have
3018          * to resolve the type before we start the scan in order
3019          * to ensure that d_Offset is properly assigned.
3020          *
3021          * Use the declarations found in the compound type 
3022          * semantic group to coerce the procedure arguments to
3023          * generate the correct compound type.  Note that resolveExp()
3024          * recursion must still use the SemGroup that was passed to us.
3025          *
3026          * XXX deal with defaults and pre-resolved arguments. XXX
3027          */
3028         type = exp->ex_Type = RESOLVETYPE(exp->ex_Type);
3029
3030         switch(type->ty_Op) {
3031         case TY_ARGS:
3032                 sg2 = type->ty_ArgsType.et_SemGroup;
3033                 break;
3034         case TY_VAR:
3035                 sg2 = type->ty_VarType.et_SemGroup;
3036                 break;
3037         case TY_COMPOUND:
3038                 sg2 = type->ty_CompType.et_SemGroup;
3039                 break;
3040         case TY_CLASS:
3041                 sg2 = type->ty_ClassType.et_SemGroup;
3042                 break;
3043         default:
3044                 dassert_exp(exp, 0);
3045                 sg2 = NULL;     /* NOT REACHED */
3046                 break;
3047         }
3048         pscan = &exp->ex_Lhs;
3049
3050         /*
3051          * Scan the compound expression and match it up against the compound
3052          * type.
3053          */
3054         d = RUNE_FIRST(&sg2->sg_DeclList);
3055         while ((scan = *pscan) != NULL) {
3056                 if (scan->ex_ArgId != NULL) {
3057                         /*
3058                          * Named argument, find it
3059                          *
3060                          * (Overloading not allowed)
3061                          */
3062                         int eno = TOK_ERR_ID_NOT_FOUND;
3063                         Declaration *nd;
3064
3065                         nd = FindDeclId(sg2, scan->ex_ArgId, &eno);
3066                         if (nd == NULL) {
3067                                 ExpFatalError(scan, eno);
3068                                 /* NOT REACHED */
3069                         }
3070
3071                         /*
3072                          * XXX for now, punt on setting EXF_PROBCONST
3073                          * if the named argument skips a declaration.
3074                          */
3075                         if (nd != d && nd != RUNE_NEXT(d, d_Node)) {
3076                                 isconst = 0;
3077                         }
3078                         d = nd;
3079                 } else {
3080                         /*
3081                          * Unnamed argument, run through sequentially.  Skip
3082                          * any non-storage or global storage.
3083                          */
3084                         while (d && d->d_Op != DOP_ARGS_STORAGE &&
3085                                 d->d_Op != DOP_STACK_STORAGE &&
3086                                 d->d_Op != DOP_GROUP_STORAGE
3087                         ) {
3088                                 d = RUNE_NEXT(d, d_Node);
3089                         }
3090
3091                         /*
3092                          * Ran out of storage declarations.  If this is a
3093                          * var-args SemGroup then we actually create a new
3094                          * SemGroup (and eventually a new type) to represent
3095                          * it.
3096                          *
3097                          * We then extend the varargs SemGroup.  This isn't
3098                          * pretty.
3099                          */
3100                         if (d == NULL) {
3101                                 if (varargs == 0 &&
3102                                     (sg2->sg_Flags & SGF_VARARGS)) {
3103                                         sg2 = DupSemGroup(sg2->sg_Parent, NULL, sg2, 1);
3104 #if 0
3105                                         if (resolveSemGroup1(sg3, flags) &&
3106                                             resolveSemGroup2(sg3, flags))
3107                                                 resolveSemGroup3(sg3, flags);
3108                                         sg2 = sg3;
3109 #endif
3110                                         varargs = 1;
3111                                 }
3112                                 if (varargs == 0) {
3113                                         fprintf(stderr,
3114                                                 "Too many arguments in "
3115                                                 "expression\n");
3116                                         dassert_exp(scan, 0);
3117                                 }
3118                         }
3119                 }
3120
3121                 /*
3122                  * Unlink the expression from the compound list temporarily
3123                  * so we can safely resolve it.  Either cast the expression
3124                  * to the compound element, or create a compound element
3125                  * (e.g. varargs call) to match the expression.
3126                  *
3127                  * Due to the resolver moving things around, the elements of
3128                  * a compound expression are sometimes resolved multiple times.
3129                  */
3130                 *pscan = scan->ex_Next;
3131                 scan->ex_Next = NULL;
3132                 if (d) {
3133                         Type *stype = d->d_StorDecl.ed_Type;
3134                         int sflags;
3135
3136                         /*
3137                          * HACK! XXX YYY
3138                          */
3139                         if (SimilarType(stype, &PointerType) &&
3140                             (stype->ty_SQFlags & SF_LVALUE) == SF_LVALUE
3141                         ) {
3142                                 stype = NULL;
3143                                 sflags = flags & ~RESOLVE_AUTOCAST;
3144                         } else {
3145                                 sflags = flags | RESOLVE_AUTOCAST;
3146                         }
3147                         if (d->d_ScopeFlags & SCOPE_LVALUE)
3148                                 scan->ex_Flags |= EXF_ADDRUSED;
3149
3150                         if ((scan->ex_Flags & EXF_RESOLVED) == 0) {
3151                                 scan = resolveExp(isg, sg, scan,
3152                                                   stype, sflags);
3153                         } else if (stype) {
3154                                 /*
3155                                  * Since we have already resolved the
3156                                  * expression we need to do the same sanity
3157                                  * checking that it would do to cast.
3158                                  */
3159                                 dassert_exp(scan,
3160                                     (stype->ty_SQFlags & SF_LVALUE) == 0 ||
3161                                     (scan->ex_Type->ty_SQFlags & SF_LVALUE));
3162                                 if (!SimilarType(stype, scan->ex_Type)) {
3163                                         scan = resolveExpCast(isg, sg, scan,
3164                                                               stype, flags);
3165                                 }
3166                         }
3167                 } else {
3168                         Scope tscope = INIT_SCOPE(0);
3169
3170                         if ((scan->ex_Flags & EXF_RESOLVED) == 0)
3171                                 scan = resolveExp(isg, sg, scan, NULL,
3172                                                   flags & ~RESOLVE_AUTOCAST);
3173                         dassert(varargs != 0);
3174                         d = AllocDeclaration(sg2, DOP_ARGS_STORAGE, &tscope);
3175                         d->d_StorDecl.ed_Type = DEL_LVALUE(scan->ex_Type);
3176                         ++sg2->sg_VarCount;
3177                         d->d_Bytes = scan->ex_Type->ty_Bytes;
3178                         d->d_AlignMask = scan->ex_Type->ty_AlignMask;
3179
3180                         /*
3181                          * __align(%d) scope qualifier, override the type's
3182                          * alignment
3183                          */
3184                         if ((d->d_Scope.s_Flags & SCOPE_ALIGN) &&
3185                             d->d_Scope.s_AlignOverride) {
3186                                 d->d_AlignMask = d->d_Scope.s_AlignOverride - 1;
3187                         }
3188
3189 #if 0
3190                         sg2->sg_Bytes = (sg2->sg_Bytes + d->d_AlignMask) &
3191                                         ~d->d_AlignMask;
3192 #endif
3193                         d->d_Offset = sg2->sg_Bytes;
3194 #if 0
3195                         sg2->sg_Bytes += d->d_Bytes;
3196                         if (sg2->sg_AlignMask < d->d_AlignMask)
3197                                 sg2->sg_AlignMask = d->d_AlignMask;
3198 #endif
3199                 }
3200
3201                 /*
3202                  * Relink and check if constant
3203                  */
3204                 scan->ex_Next = *pscan;
3205                 *pscan = scan;
3206                 if ((scan->ex_Flags & (EXF_CONST | EXF_PROBCONST)) == 0)
3207                         isconst = 0;
3208
3209                 /*
3210                  * If the declaration requires an LVALUE, assert that
3211                  * we have an lvalue.  Otherwise set the direct-store
3212                  * request (also see InterpCompoundExp).
3213                  */
3214                 if (d->d_ScopeFlags & SCOPE_LVALUE) {
3215                         if ((scan->ex_Type->ty_SQFlags & SF_LVALUE) == 0)
3216                                 fprintf(stderr, "argument must be an lvalue\n");
3217                         dassert_exp(scan,
3218                                     scan->ex_Type->ty_SQFlags & SF_LVALUE);
3219                 }
3220
3221                 /*
3222                  * accounting
3223                  */
3224                 d = RUNE_NEXT(d, d_Node);
3225                 pscan = &scan->ex_Next;
3226         }
3227
3228         /*
3229          * Make sure the caller knows its a var-args function even if
3230          * we didn't supply any additional args.  Otherwise the backend
3231          * may not generate the correct form for calls to the target.
3232          */
3233         if (varargs == 0 &&
3234             (sg2->sg_Flags & SGF_VARARGS)) {
3235                 sg2 = DupSemGroup(sg2->sg_Parent, NULL, sg2, 1);
3236                 varargs = 1;
3237         }
3238
3239         /*
3240          * Resolve the varargs sg2 after building it.
3241          */
3242         if (varargs) {
3243                 if (resolveSemGroup1(sg2, flags) &&
3244                     resolveSemGroup2(sg2, flags)) {
3245                         resolveSemGroup3(sg2, flags);
3246                 }
3247                 /* resolveStorageSemGroupAlign(sg2); */
3248                 /*resolveStorageSemGroup(sg2, 0, 0);*/
3249         }
3250
3251         /*
3252          * If we made a var-args call, adjust the expression's type
3253          */
3254         if (varargs) {
3255                 dassert(type->ty_Op == TY_ARGS);
3256                 exp->ex_Type = RESOLVETYPE(TypeToVarType(type, sg2));
3257         }
3258         if (isconst)
3259                 exp->ex_Flags |= EXF_PROBCONST;
3260
3261         exp->ex_Flags |= EXF_RESOLVED;
3262         return(exp);
3263 }
3264
3265 /*
3266  * resolveExpCast() - Cast the expression to the specified type and return
3267  *                    the cast expression.
3268  *
3269  *      Note that expression nodes depend on their ex_Type being correct,
3270  *      and also expressions may be shared, so be careful not to modify the
3271  *      ex_Type (or anything else) in the existing expression.
3272  *
3273  *      This code is somewhat different then resolveExpOper() and friends.
3274  *      The Exp argument has already been resolved so do not resolve it
3275  *      again, and the cast type already has SF_LVALUE set or cleared as
3276  *      appropriate (had better be cleared!)
3277  *
3278  *      As with operators we have to locate the cast declaration matching
3279  *      the cast we want to do.
3280  */
3281 static Exp *
3282 resolveExpCast(SemGroup *isg, SemGroup *sg, Exp *exp, Type *ltype, int flags)
3283 {
3284         Type *rtype;
3285         Declaration *d;
3286
3287         flags &= ~RESOLVE_AUTOCAST;     /* not applicable to this function */
3288
3289         rtype = exp->ex_Type;
3290         dassert(rtype && ltype);
3291         /*
3292          * XXX attempt to cast from subclass to superclass?
3293          */
3294
3295         /*
3296          * XXX look in our local semantic hierarchy for a compatible cast ?
3297          */
3298
3299         /*
3300          * Look in the right hand (source) type for the cast
3301          */
3302         d = findCast(rtype, ltype, rtype, flags);
3303
3304         /*
3305          * If that fails then look in the left hand (destination) type for
3306          * the cast.
3307          */
3308         if (d == NULL) {
3309                 d = findCast(ltype, ltype, rtype, flags);
3310         }
3311 #if 1
3312         if (d == NULL && (rtype->ty_Op == TY_PTRTO ||
3313                           rtype->ty_Op == TY_REFTO ||
3314                           rtype->ty_Op == TY_CPTRTO)) {
3315                 d = findCast(&PointerType, ltype, rtype, flags);
3316         }
3317 #endif
3318
3319         if (d == NULL) {
3320                 /*
3321                  * We could not find a specific cast operator.  There are
3322                  * some inherent casts that we can do.  We run through these
3323                  * in attempt to come up with matching types.
3324                  */
3325                 if (ltype->ty_Op != rtype->ty_Op &&
3326                     (ltype->ty_Op == TY_PTRTO || ltype->ty_Op == TY_CPTRTO ||
3327                     ltype->ty_Op == TY_ARYOF) &&
3328                     (rtype->ty_Op == TY_PTRTO || rtype->ty_Op == TY_CPTRTO ||
3329                     rtype->ty_Op == TY_ARYOF)) {
3330                         /*
3331                          * Pointers, C pointers, or arrays can be cast to
3332                          * pointers, C pointers, or arrays of the same type.
3333                          *
3334                          * Cast the right hand type to an equivalent
3335                          * pointer/cpointer/array of the right hand type
3336                          * and re-resolve the cast.
3337                          */
3338                         exp = ExpToCastExp(exp,
3339                                 RESOLVETYPE(ChangeType(rtype, ltype->ty_Op)));
3340                         return(resolveExpCast(isg, sg, exp, ltype, flags));
3341                 } else if (MatchType(ltype, rtype) <= SG_COMPAT_PART) {
3342                         /*
3343                          * If the types are compatible (casting rtype->ltype),
3344                          * we can cast trivially.
3345                          */
3346                         exp = ExpToCastExp(exp, ltype);
3347                 } else if (MatchType(&NumericType, ltype) <= SG_COMPAT_PART &&
3348                            MatchType(&NumericType, rtype) <= SG_COMPAT_PART) {
3349                         /*
3350                          * Casting from one numeric type to another must be
3351                          * supported by the interpreter/compiler.
3352                          */
3353                         exp = ExpToCastExp(exp, ltype);
3354                 } else if (SimilarType(&VoidType, ltype)) {
3355                         /*
3356                          * Casting anything to void is allowed (throwing the
3357                          * object away).  E.g. statement-expressions.
3358                          */
3359                         exp = ExpToCastExp(exp, ltype);
3360                 } else if (SimilarType(&VoidPtrType, ltype)) {
3361                         /*
3362                          * Casting a pointer to a (void *) is trivial, but is
3363                          * only allowed if the underlying structure does not
3364                          * contain any pointers.
3365                          *
3366                          * NOTE: Generally only used when a pointer is being
3367                          *       cast to an integer.  Rune does not allow
3368                          *       casting back to other pointer types.
3369                          *
3370                          * XXX validate integral # of objects fit in pointer
3371                          * range.
3372                          */
3373                         dassert_exp(exp, (rtype->ty_PtrType.et_Type->ty_Flags & TF_HASLVPTR) == 0);
3374                         exp = ExpToCastExp(exp, ltype);
3375                 } else if (SimilarType(&VoidRefType, ltype)) {
3376                         /*
3377                          * Casting a pointer to a (void @) is trivial.
3378                          *
3379                          * NOTE: Generally only used when a pointer is being
3380                          *       cast to an integer.  Rune does not allow
3381                          *       casting back to other pointer types.
3382                          *
3383                          * XXX validate integral # of objects fit in pointer
3384                          * range.
3385                          */
3386                         dassert_exp(exp, (rtype->ty_RefType.et_Type->ty_Flags & TF_HASLVPTR) == 0);
3387                         exp = ExpToCastExp(exp, ltype);
3388                 } else if (SimilarType(rtype, &VoidPtrType)) {
3389                         /*
3390                          * Casting from a void pointer may not be trivial
3391                          * but we leave it up to the interpreter/compiler.
3392                          *
3393                          * Only allow if the target does not contain any
3394                          * pointers or if the right-hand-side is NULL.
3395                          *
3396                          * XXX validate integral # of objects fit in pointer
3397                          * range.
3398                          */
3399                         switch(ltype->ty_Op) {
3400                         case TY_REFTO:
3401                                 if ((exp->ex_Flags & EXF_NULL) == 0)
3402                                 dassert_exp(exp, (ltype->ty_RefType.et_Type->ty_Flags & TF_HASLVPTR) == 0);
3403                                 break;
3404                         case TY_PTRTO:
3405                                 if ((exp->ex_Flags & EXF_NULL) == 0)
3406                                 dassert_exp(exp, (ltype->ty_PtrType.et_Type->ty_Flags & TF_HASLVPTR) == 0);
3407                                 break;
3408                         default:
3409                                 break;
3410                         }
3411                         exp = ExpToCastExp(exp, ltype);
3412                 } else if (SimilarType(rtype, &CVoidPtrType)) {
3413                         switch(ltype->ty_Op) {
3414                         case TY_CPTRTO:
3415                                 if ((exp->ex_Flags & EXF_NULL) == 0)
3416                                 dassert_exp(exp, (ltype->ty_PtrType.et_Type->ty_Flags & TF_HASLVPTR) == 0);
3417                                 break;
3418                         default:
3419                                 break;
3420                         }
3421                 } else if (SimilarType(ltype, &BoolType) &&
3422                            (rtype->ty_Op == TY_PTRTO ||
3423                             rtype->ty_Op == TY_REFTO ||
3424                             rtype->ty_Op == TY_CPTRTO)) {
3425                         /*
3426                          * Any pointer can be cast to a boolean, which
3427                          * tests against NULL.
3428                          */
3429                         exp = ExpToCastExp(exp, ltype);
3430                 } else if (ltype->ty_Op == rtype->ty_Op &&
3431                            (ltype->ty_Op == TY_PTRTO ||
3432                             ltype->ty_Op == TY_CPTRTO ||
3433                             ltype->ty_Op == TY_ARYOF)) {
3434                         /*
3435                          * We allow casts of pointers to similar numeric
3436                          * types if they are the same size, though this is
3437                          * really rather a hack.  This is mainly to handle
3438                          * the signed<->unsigned cast case.  XXX
3439                          */
3440                         int ok = 0;
3441
3442                         switch(ltype->ty_Op) {
3443                         case TY_PTRTO:
3444                                 if (MatchType(&NumericType,
3445                                               ltype->ty_PtrType.et_Type) <=
3446                                      SG_COMPAT_SUBCLASS &&
3447                                     MatchType(&NumericType,
3448                                               rtype->ty_PtrType.et_Type) <=
3449                                      SG_COMPAT_SUBCLASS &&
3450                                     ltype->ty_Bytes == rtype->ty_Bytes
3451                                 ) {
3452                                         exp = ExpToCastExp(exp, ltype);
3453                                         ok = 1;
3454                                 }
3455                                 break;
3456                         case TY_CPTRTO:
3457                                 if (MatchType(&NumericType,
3458                                               ltype->ty_CPtrType.et_Type) <=
3459                                      SG_COMPAT_SUBCLASS &&
3460                                     MatchType(&NumericType,
3461                                               rtype->ty_CPtrType.et_Type) <=
3462                                      SG_COMPAT_SUBCLASS &&
3463                                     ltype->ty_Bytes == rtype->ty_Bytes
3464                                 ) {
3465                                         exp = ExpToCastExp(exp, ltype);
3466                                         ok = 1;
3467                                 }
3468                                 break;
3469                         case TY_ARYOF:
3470                                 if (MatchType(&NumericType,
3471                                               ltype->ty_AryType.et_Type) <=
3472                                      SG_COMPAT_SUBCLASS &&
3473                                     MatchType(&NumericType,
3474                                               rtype->ty_AryType.et_Type) <=
3475                                      SG_COMPAT_SUBCLASS &&
3476                                     ltype->ty_Bytes == rtype->ty_Bytes
3477                                 ) {
3478                                         exp = ExpToCastExp(exp, ltype);
3479                                         ok = 1;
3480                                 }
3481                                 break;
3482                         }
3483                         if (ok == 0) {
3484                                 fprintf(stderr,
3485                                         "Unable to resolve cast from pointers "
3486                                         "to dissimilar numeric types "
3487                                         "%s to %s\n",
3488                                         TypeToStr(rtype, NULL),
3489                                         TypeToStr(ltype, NULL));
3490                                 dassert_exp(exp, 0);
3491                         }
3492                 } else {
3493                         fprintf(stderr,
3494                                 "Unable to resolve cast from %s to %s\n",
3495                                 TypeToStr(rtype, NULL),
3496                                 TypeToStr(ltype, NULL));
3497                         dassert_exp(exp, 0);
3498                 }
3499         } else if (d->d_ScopeFlags & SCOPE_INTERNAL) {
3500                 /*
3501                  * We found a cast operator and it is an internal operator
3502                  */
3503                 exp = ExpToCastExp(exp, ltype);
3504                 exp->ex_Decl = d;
3505         } else {
3506                 /*
3507                  * We found a cast operator and it is a Rune cast procedure.  We
3508                  * must convert the cast to a procedure call.  If we want
3509                  * resolveCompoundExp() to be able to generate a compatible
3510                  * procedure (in a subclass) we have to tell it about the
3511                  * procedure.
3512                  */
3513                 Exp *sexp;
3514
3515                 sexp = ExpToCompoundExp(exp, TOK_COMPOUND);
3516                 if (d->d_ProcDecl.ed_ProcBody == NULL)
3517                         sexp->ex_Decl = d;
3518                 sexp = resolveCompoundExp(isg, sg, sexp,
3519                               d->d_ProcDecl.ed_Type->ty_ProcType.et_ArgsType,
3520                               flags);
3521                 exp = AllocExp(NULL);
3522                 exp->ex_Lhs = AllocExp(NULL);
3523                 exp->ex_Lhs->ex_Token = TOK_DECL;
3524                 exp->ex_Lhs->ex_Id = d->d_Id;
3525                 exp->ex_Lhs->ex_Decl = d;
3526                 exp->ex_Lhs->ex_Type = d->d_ProcDecl.ed_Type;
3527                 exp->ex_Lhs->ex_Flags |= EXF_RESOLVED;
3528                 exp->ex_Rhs  = sexp;
3529                 exp->ex_Flags |= EXF_BINARY;
3530                 exp->ex_Token = TOK_CALL;
3531                 /* XXX use ltype or procedure's rettype? */
3532                 exp->ex_Type = ltype;
3533                 LexDupRef(&sexp->ex_LexRef, &exp->ex_LexRef);
3534                 LexDupRef(&sexp->ex_LexRef, &exp->ex_Lhs->ex_LexRef);
3535         }
3536         exp->ex_Flags |= EXF_RESOLVED;
3537         return(exp);
3538 }
3539
3540 static
3541 Declaration *
3542 findCast(Type *btype, Type *ltype, Type *rtype, int flags)
3543 {
3544         SemGroup *sg;
3545         Declaration *d;
3546
3547         flags &= ~RESOLVE_AUTOCAST;     /* not applicable to this function */
3548
3549         /*
3550          * Locate the base type.  If the base type does not have a SemGroup
3551          * there are no casts.  (XXX put system operators here)
3552          */
3553         sg = BaseType(&btype);
3554
3555         if (sg == NULL)
3556                 return(NULL);
3557
3558         /*
3559          * Look for the cast in the SemGroup
3560          */
3561         RUNE_FOREACH(d, &sg->sg_DeclList, d_Node) {
3562                 if (d->d_Op == DOP_PROC && (d->d_ScopeFlags & SCOPE_CAST)) {
3563                         if (MatchCastTypes(d, ltype, rtype))
3564                                 return(d);
3565                 }
3566         }
3567
3568         /*
3569          * Failed.  If the base type is a compound type, look for the
3570          * cast in the SemGroup for each element making up the compound
3571          * type.  e.g. so (mycustomtype, double) would find the cast
3572          * in mycustomtype.
3573          */
3574         if (btype->ty_Op == TY_COMPOUND) {
3575                 RUNE_FOREACH(d, &sg->sg_DeclList, d_Node) {
3576                         Declaration *d2;
3577                         if (d->d_Op & DOPF_STORAGE) {
3578                                 d2 = findCast(d->d_StorDecl.ed_Type,
3579                                               ltype, rtype, flags);
3580                         } else if (d->d_Op == DOP_TYPEDEF) {
3581                                 d2 = findCast(d->d_TypedefDecl.ed_Type,
3582                                               ltype, rtype, flags);
3583                         } else {
3584                                 d2 = NULL;
3585                         }
3586                         if (d2)
3587                                 return(d2);
3588                 }
3589         }
3590         return(NULL);
3591 }
3592
3593
3594 /*
3595  * resolveExpOper() - resolve an operator
3596  *
3597  *      This is complex enough that it is broken out into its own procedure.
3598  *      Normally we just look the operator up but we have to special case
3599  *      pointer arithmatic because we do will not know until now that we
3600  *      have to do it.
3601  *
3602  *      itype is a return-type hint only.  resolveExpOper() can ignore it
3603  *      if it wishes.  We currently use it to detect cast-to-void, such as
3604  *      when an expression like "++i" is used in a for() loop or as a
3605  *      standalone statement.  This allows us to optimize the case.
3606  */
3607 static Exp *
3608 resolveExpOper(SemGroup *isg, SemGroup *sg, Exp *exp, Type *itype, int flags)
3609 {
3610         Declaration *d;
3611         int isPointerOp = 0;
3612         Exp copy;
3613
3614         flags &= ~RESOLVE_AUTOCAST;     /* not applicable to this function */
3615
3616         loadExpCopy(&copy, exp);
3617         dassert_exp(exp, exp->ex_Id != NULL);
3618         if (exFlags & EXF_BINARY) {
3619                 exLhs = resolveExp(isg, sg, exLhs, NULL, flags);
3620                 exRhs = resolveExp(isg, sg, exRhs, NULL, flags);
3621         } else if (exFlags & EXF_UNARY) {
3622                 exLhs = resolveExp(isg, sg, exLhs, NULL, flags);
3623         } else {
3624                 dassert_exp(exp, 0);
3625         }
3626
3627         /*
3628          * If the lhs is a pointer look the operator up in the Pointer
3629          * class first.  Operators in the Pointer class are special-cased.
3630          * A second pointer argument or a pointer return value must match
3631          * the lhs pointer.
3632          *
3633          * If this fails, or if the ltype is not a pointer, then look
3634          * the operator up normally.
3635          */
3636         if (exLhs->ex_Type->ty_Op == TY_PTRTO ||
3637             exLhs->ex_Type->ty_Op == TY_REFTO ||
3638             exLhs->ex_Type->ty_Op == TY_CPTRTO
3639         ) {
3640                 Type *ltype;
3641                 Type *rtype;
3642
3643                 if (exFlags & EXF_BINARY) {
3644                         rtype = exRhs->ex_Type;
3645                         ltype = exLhs->ex_Type;
3646                 } else {
3647                         dassert(exFlags & EXF_UNARY);
3648                         rtype = NULL;
3649                         ltype = exLhs->ex_Type;
3650                 }
3651                 d = findOper(&PointerType, exp->ex_Id, ltype, rtype, flags);
3652                 if (d)
3653                         isPointerOp = 1;
3654                 else
3655                         d = findExpOper(&copy, flags);
3656         } else {
3657                 d = findExpOper(&copy, flags);
3658         }
3659
3660         /*
3661          * Fall through to finish up resolving the operator.  We just set
3662          * ex_Decl for internal operators, and construct a call for
3663          * non-internal procedural operators.
3664          */
3665         if (d) {
3666                 Declaration *d2;
3667                 Type *type;
3668                 SemGroup *sg2;
3669                 int count = 0;
3670
3671                 dassert_exp(exp, d != NULL);
3672                 dassert_exp(exp, d->d_Op == DOP_PROC);
3673                 dassert_exp(exp, d->d_ProcDecl.ed_Type->ty_Op == TY_PROC);
3674                 type = d->d_ProcDecl.ed_Type;
3675                 exType = type->ty_ProcType.et_RetType;
3676
3677                 /*
3678                  * Special case for internal Pointer ops.  The return type is
3679                  * the left-hand type (we may still optimize it to void later).
3680                  */
3681                 if (isPointerOp &&
3682                     (d->d_ScopeFlags & SCOPE_INTERNAL) && 
3683                     SimilarType(&VoidRefType, exType)
3684                 ) {
3685                         if (exType->ty_SQFlags & SF_LVALUE)
3686                                 exType = ADD_LVALUE(exLhs->ex_Type);
3687                         else
3688                                 exType = DEL_LVALUE(exLhs->ex_Type);
3689                 }
3690
3691                 type = d->d_ProcDecl.ed_Type->ty_ProcType.et_ArgsType;
3692                 dassert(type->ty_Op == TY_ARGS);
3693                 sg2 = type->ty_ArgsType.et_SemGroup;
3694
3695                 /*
3696                  * Assert that LVALUE requirements are met.  XXX MatchType()
3697                  * code should disallow the non-lvalue-cast-to-lvalue case
3698                  * so we don't have to do a check here.
3699                  */
3700                 RUNE_FOREACH(d2, &sg2->sg_DeclList, d_Node) {
3701                         if ((d2->d_Op & DOPF_STORAGE) &&
3702                             d2->d_Op != DOP_GLOBAL_STORAGE) {
3703                                 if (count == 0) {
3704                                         if ((d2->d_ScopeFlags & SCOPE_LVALUE) &&
3705                                             (exLhs->ex_Type->ty_SQFlags &
3706                                              SF_LVALUE) == 0
3707                                         ) {
3708                                                 fprintf(stderr,
3709                                                         "lhs of exp must be "
3710                                                         "lvalue\n");
3711                                                 dassert_exp(exp, 0);
3712                                         }
3713                                 } else if (count == 1) {
3714                                         if ((d2->d_ScopeFlags & SCOPE_LVALUE) &&
3715                                                 (exRhs->ex_Type->ty_SQFlags &
3716                                                  SF_LVALUE) == 0
3717                                         ) {
3718                                                 fprintf(stderr,
3719                                                         "rhs of exp must be "
3720                                                         "lvalue\n");
3721                                                 dassert_exp(exp, 0);
3722                                         }
3723                                 }
3724                                 ++count;
3725                         }
3726                 }
3727
3728                 if (d->d_ScopeFlags & SCOPE_INTERNAL) {
3729                         /*
3730                          * Internal operator.  Optimize any cast to void
3731                          * by having the internal function deal with it.
3732                          * (since we aren't setting exType the optimization
3733                          * currently doesn't do anything, see ST_Exp)
3734                          */
3735                         exDecl = d;
3736                         if (itype == &VoidType) {
3737                                 /*exType = itype;*/
3738                                 exFlags |= EXF_RET_VOID;
3739                         }
3740                 } else {
3741                         /*
3742                          * Normal procedural operator.  Convert the left and
3743                          * right hand sides to a compound expression and
3744                          * convert exp to a TOK_CALL.  NOTE! ex_Rhs may be
3745                          * NULL (unary op).
3746                          *
3747                          * The compound expression may need to rewrite a
3748                          * subclass procedure, which it can do if the
3749                          * procedure's body has not yet been created (or
3750                          * duplicated from the superclass).  ex_Decl must
3751                          * be set in this case.
3752                          *
3753                          * Note that the expression structure may be shared.
3754                          * The conversion is permanent so that is ok.
3755                          *
3756                          * XXX keep the type intact?
3757                          */
3758                         exLhs->ex_Next = exRhs;
3759                         exRhs = exLhs;
3760                         exRhs = ExpToCompoundExp(exRhs, TOK_COMPOUND);
3761                         if (d->d_ProcDecl.ed_ProcBody == NULL)
3762                                 exRhs->ex_Decl = d;
3763                         exRhs = resolveCompoundExp(isg, sg, exRhs, type, flags);
3764                         exLhs = AllocExp(NULL);
3765                         LexDupRef(&exp->ex_LexRef, &exLhs->ex_LexRef);
3766                         exLhs->ex_Token = TOK_ID;
3767                         exLhs->ex_Id = d->d_Id;
3768                         exLhs->ex_Decl = d;
3769                         exLhs->ex_Type = d->d_ProcDecl.ed_Type;
3770                         exLhs->ex_Flags |= EXF_RESOLVED;
3771                         exToken = exp->ex_Token = TOK_CALL;
3772                         exFlags = EXF_BINARY;
3773                 }
3774         }
3775         if (d == NULL) {
3776                 fprintf(stderr,
3777                         "Unable to resolve operator: %s\n", exp->ex_Id);
3778                 dassert_exp(exp, 0);
3779         }
3780
3781         /*
3782          * Flag a pure operator whos arguments are constants as probably
3783          * being constant.
3784          */
3785         if (d->d_ScopeFlags & SCOPE_PURE) {
3786                 if ((exLhs->ex_Flags & (EXF_CONST | EXF_PROBCONST)) &&
3787                     (exRhs == NULL ||
3788                      (exRhs->ex_Flags & (EXF_CONST | EXF_PROBCONST)))) {
3789                         exFlags |= EXF_PROBCONST;
3790                 }
3791         }
3792
3793         exFlags |= EXF_RESOLVED;
3794         return(dupExpCopy(&copy, exp));
3795 }
3796
3797 static void
3798 loadExpCopy(Exp *copy, Exp *exp)
3799 {
3800         copy->ex_Lhs = exp->ex_Lhs;
3801         copy->ex_Rhs = exp->ex_Rhs;
3802         copy->ex_Flags = exp->ex_Flags;
3803         copy->ex_Type = exp->ex_Type;
3804         copy->ex_Decl = exp->ex_Decl;
3805         copy->ex_Token = exp->ex_Token;
3806         copy->ex_Visibility = exp->ex_Visibility;
3807         copy->ex_Id = exp->ex_Id;
3808         copy->ex_ArgId = exp->ex_ArgId;
3809         copy->ex_AuxExp = exp->ex_AuxExp;
3810 }
3811
3812 static void
3813 saveExpCopy(Exp *copy, Exp *exp)
3814 {
3815         exp->ex_Lhs = copy->ex_Lhs;
3816         exp->ex_Rhs = copy->ex_Rhs;
3817         exp->ex_Flags = copy->ex_Flags;
3818         exp->ex_Type = copy->ex_Type;
3819         exp->ex_Decl = copy->ex_Decl;
3820         exp->ex_Token = copy->ex_Token;
3821         exp->ex_Visibility = copy->ex_Visibility;
3822         exp->ex_Id = copy->ex_Id;
3823         exp->ex_ArgId = copy->ex_ArgId;
3824         exp->ex_AuxExp = copy->ex_AuxExp;
3825 }
3826
3827 #define EXF_DUPSHAREFLAGS       -1
3828
3829 static Exp *
3830 dupExpCopy(Exp *copy, Exp *exp)
3831 {
3832         Exp *nexp;
3833
3834         if ((exp->ex_Flags & EXF_DUPEXP) == 0) {
3835                 saveExpCopy(copy, exp);
3836                 return(exp);
3837         }
3838
3839         /*
3840          * We can share the expression or subexpression across duplicated
3841          * elements in distinct subclasses if these conditions are met.
3842          *
3843          * Note: 0x80000000 for ex_Visibility simply means that the visibility
3844          * was never modified and can be changed for the first time.
3845          * Superclasses are resolved first so we should be ok.
3846          */
3847         if (exp->ex_Lhs == copy->ex_Lhs &&
3848                 exp->ex_Rhs == copy->ex_Rhs &&
3849                 ((exp->ex_Flags ^ copy->ex_Flags) & ~EXF_DUPSHAREFLAGS) == 0 &&
3850                 (exp->ex_Type == copy->ex_Type || exp->ex_Type == NULL) &&
3851                 exp->ex_Token == copy->ex_Token &&
3852                 (exp->ex_Decl == copy->ex_Decl || exp->ex_Decl == NULL) &&
3853                 (exp->ex_Id == copy->ex_Id || exp->ex_Id == NULL) &&
3854                 (exp->ex_ArgId == copy->ex_ArgId || exp->ex_ArgId == NULL) &&
3855                 (exp->ex_AuxExp == copy->ex_AuxExp || exp->ex_AuxExp == NULL) &&
3856                 (exp->ex_Visibility == copy->ex_Visibility ||
3857                  (exp->ex_Visibility & 0x80000000))
3858         ) {
3859 #if DUPEXP_DEBUG
3860                 static int count;
3861                 fprintf(stderr, "DUPEXPB COMPARE %d %p\n", ++count, exp);
3862 #endif
3863                 saveExpCopy(copy, exp);
3864                 return(exp);
3865         } 
3866
3867         nexp = AllocExp(NULL);
3868         LexDupRef(&exp->ex_LexRef, &nexp->ex_LexRef);
3869
3870 #if DUPEXP_DEBUG
3871         {
3872                 static int count;
3873                 fprintf(stderr,
3874                         "DUPEXPB %d %p lhs (%p,%p) rhs (%p,%p) "
3875                         "flags (%08x,%08x) types (%p, %p) "
3876                         "tokens (%04x, %04x), decl (%p, %p) "
3877                         "vis (%d, %d)\n",
3878                         ++count,
3879                         exp,
3880                         exp->ex_Lhs, copy->ex_Lhs,
3881                         exp->ex_Rhs, copy->ex_Rhs,
3882                         exp->ex_Flags & ~EXF_DUPSHAREFLAGS,
3883                         copy->ex_Flags & ~EXF_DUPSHAREFLAGS,
3884                         exp->ex_Type, copy->ex_Type,
3885                         exp->ex_Token, copy->ex_Token,
3886                         exp->ex_Decl, copy->ex_Decl,
3887                         exp->ex_Visibility, copy->ex_Visibility
3888                 );
3889                 ExpPrintError(exp, 0);
3890         }
3891 #endif
3892
3893         copy->ex_Flags &= ~EXF_DUPEXP;
3894         saveExpCopy(copy, nexp);
3895         nexp->u = exp->u;
3896         return(nexp);
3897 }
3898
3899 /*
3900  * resolveType() -      Resolve a type
3901  *
3902  *      This routine is responsible for resolving the size and alignment
3903  *      features of a type.  Note that we do not special-case LVALUE
3904  *      qualified types here.
3905  *
3906  *      This routine is also rsponsible for resolving the visibility of
3907  *      a type's elements.  Visibility is inherited from sub-types.  Base
3908  *      classes's visibility should already be set by resolveSuperClass()
3909  */
3910 Type *
3911 resolveType(Type *type, Type *adjtype, int flags)
3912 {
3913         SemGroup *sg = NULL;
3914         Type *otype = type;
3915         int do2 = 0;
3916
3917         flags &= ~RESOLVE_AUTOCAST;     /* not applicable to this function */
3918
3919         if (type->ty_Flags & TF_RESOLVED)
3920                 return(type);
3921
3922         dassert_type(type, (type->ty_Flags & TF_RESOLVING) == 0);
3923         type->ty_Flags |= TF_RESOLVING;
3924
3925         switch(type->ty_Op) {
3926         case TY_CLASS:
3927                 /*
3928                  * NOTE: TF_HASLVPTR inherited as appropriate after switch.
3929                  *
3930                  * NOTE: Special case, PointerType fields not in classes XXX
3931                  *       (force alignment and bytes)?
3932                  */
3933                 dassert(type->ty_SQList ==
3934                         &type->ty_ClassType.et_SemGroup->sg_ClassList);
3935                 sg = type->ty_ClassType.et_SemGroup;
3936                 do2 = resolveSemGroup1(sg, flags);
3937                 if (type != &PointerType) {
3938                         type->ty_Bytes = sg->sg_Bytes;
3939                         type->ty_AlignMask = sg->sg_AlignMask;
3940                 }
3941                 /* visibility already determined by resolveSuperClass? */
3942
3943                 if (type->ty_ClassType.et_Super &&
3944                     type->ty_ClassType.et_Super->ty_Op == TY_UNRESOLVED) {
3945                         type->ty_ClassType.et_Super =
3946                                 resolveSuperClass(type->ty_ClassType.et_Super);
3947                 }
3948
3949                 /*
3950                  * Type inherits ISUNSIGNED from class.  This is a special
3951                  * flag helper for the interpreter and code generator.
3952                  */
3953                 if (sg->sg_Flags & SGF_ISINTEGER)
3954                         type->ty_Flags |= TF_ISINTEGER;
3955                 if (sg->sg_Flags & SGF_ISUNSIGNED)
3956                         type->ty_Flags |= TF_ISUNSIGNED;
3957                 if (sg->sg_Flags & SGF_ISFLOATING)
3958                         type->ty_Flags |= TF_ISFLOATING;
3959                 if (sg->sg_Flags & SGF_ISBOOL)
3960                         type->ty_Flags |= TF_ISBOOL;
3961                 if (sg->sg_Flags & SGF_HASASS)
3962                         type->ty_Flags |= TF_HASASS;
3963                 dassert(type->ty_Visibility != 0);
3964                 break;
3965         case TY_CPTRTO:
3966                 /*
3967                  * NOTE: Do not set TF_HASLVPTR, C pointers are not tracked.
3968                  */
3969                 type->ty_Bytes = sizeof(void *);
3970                 type->ty_AlignMask = POINTER_ALIGN;
3971                 type->ty_CPtrType.et_Type =
3972                         RESOLVETYPEADJ(type->ty_CPtrType.et_Type, type);
3973                 type->ty_Visibility = type->ty_CPtrType.et_Type->ty_Visibility;
3974                 break;
3975         case TY_PTRTO:
3976                 /*
3977                  * Set TF_HASLVPTR, pointers are tracked.
3978                  */
3979                 type->ty_Bytes = sizeof(PointerStor);
3980                 type->ty_AlignMask = POINTER_ALIGN;
3981                 type->ty_PtrType.et_Type =
3982                         RESOLVETYPEADJ(type->ty_PtrType.et_Type, type);
3983                 type->ty_Visibility = type->ty_PtrType.et_Type->ty_Visibility;
3984                 type->ty_Flags |= TF_HASLVPTR;
3985                 break;
3986         case TY_REFTO:
3987                 /*
3988                  * Set TF_HASLVPTR, references are tracked.
3989                  */
3990                 type->ty_Bytes = sizeof(PointerStor);
3991                 type->ty_AlignMask = POINTER_ALIGN;
3992                 type->ty_RefType.et_Type =
3993                         RESOLVETYPEADJ(type->ty_RefType.et_Type, type);
3994                 type->ty_Visibility = type->ty_RefType.et_Type->ty_Visibility;
3995                 type->ty_Flags |= TF_HASLVPTR;
3996                 break;
3997         case TY_ARYOF:
3998                 /*
3999                  * Inherit TF_HASLVPTR (if array type is or contains something
4000                  * which needs to be tracked).
4001                  *
4002                  * XXX allow ArySize resolve to local expression?
4003                  * XXX use interpreter to resolve constant expression?
4004                  * XXX SemGroup passed as NULL.
4005                  *
4006                  * XXX hack, ex_ArySize can be shared amoungst qualified
4007                  *     array types.  Only resolve it once.  XXX
4008                  *
4009                  * YYY hack what is our ImportSemGroup ???
4010                  */
4011                 {
4012                         Exp *exp = type->ty_AryType.et_ArySize;
4013                         if ((exp->ex_Flags & EXF_RESOLVED) == 0) {
4014                                 exp = resolveConstExp(NULL,
4015                                                  type->ty_AryType.et_SemGroup,
4016                                                  exp, flags);
4017                         }
4018                         type->ty_AryType.et_ArySize = exp;
4019                         type->ty_AryType.et_Type =
4020                                 RESOLVETYPEADJ(type->ty_AryType.et_Type, type);
4021                         type->ty_AryType.et_Count = resolveGetConstExpInt64(exp);
4022                         type->ty_AlignMask =
4023                                 type->ty_AryType.et_Type->ty_AlignMask;
4024                         type->ty_Bytes =
4025                                 type->ty_AryType.et_Type->ty_Bytes *
4026                                 type->ty_AryType.et_Count;
4027                 }
4028                 type->ty_Visibility = type->ty_AryType.et_Type->ty_Visibility;
4029                 type->ty_Flags |= type->ty_AryType.et_Type->ty_Flags &
4030                                   (TF_HASLVPTR | TF_HASCONSTRUCT |
4031                                    TF_HASDESTRUCT | TF_HASGCONSTRUCT |
4032                                    TF_HASGDESTRUCT | TF_HASASS);
4033                 break;
4034         case TY_COMPOUND:
4035                 /*
4036                  * NOTE: TF_HASLVPTR inherited as appropriate after switch.
4037                  */
4038                 sg = type->ty_CompType.et_SemGroup;
4039                 do2 = resolveSemGroup1(sg, flags);
4040                 type->ty_Bytes = sg->sg_Bytes;
4041                 type->ty_AlignMask = sg->sg_AlignMask;
4042                 type->ty_Visibility = SCOPE_ALL_VISIBLE;
4043                 break;
4044         case TY_VAR:
4045                 /*
4046                  * NOTE: TF_HASLVPTR inherited as appropriate after switch.
4047                  */
4048                 sg = type->ty_VarType.et_SemGroup;
4049                 do2 = resolveSemGroup1(sg, flags);
4050                 type->ty_Bytes = sg->sg_Bytes;
4051                 type->ty_AlignMask = sg->sg_AlignMask;
4052                 type->ty_Visibility = SCOPE_ALL_VISIBLE;
4053                 break;
4054         case TY_ARGS:
4055                 /*
4056                  * NOTE: TF_HASLVPTR inherited as appropriate after switch.
4057                  */
4058                 sg = type->ty_ArgsType.et_SemGroup;
4059                 do2 = resolveSemGroup1(sg, flags);
4060                 type->ty_Bytes = sg->sg_Bytes;
4061                 type->ty_AlignMask = sg->sg_AlignMask;
4062                 type->ty_Visibility = SCOPE_ALL_VISIBLE;
4063                 break;
4064         case TY_PROC:
4065                 /*
4066                  * NOTE: Storage not tracked.
4067                  */
4068                 type->ty_ProcType.et_ArgsType =
4069                         RESOLVETYPE(type->ty_ProcType.et_ArgsType);
4070                 type->ty_ProcType.et_RetType =
4071                         RESOLVETYPEADJ(type->ty_ProcType.et_RetType, type);
4072                 type->ty_Bytes = 0;
4073                 type->ty_AlignMask = 0;
4074                 type->ty_Visibility = SCOPE_ALL_VISIBLE;
4075                 break;
4076         case TY_STORAGE:
4077                 /*
4078                  * NOTE: Base storage is not tracked.
4079                  */
4080                 type->ty_Bytes = type->ty_StorType.et_Bytes;
4081                 /* XXX check pwr of 2 */
4082                 if (type->ty_Bytes)
4083                         type->ty_AlignMask = type->ty_Bytes - 1;
4084                 type->ty_Visibility = SCOPE_ALL_VISIBLE;
4085                 break;
4086         case TY_UNRESOLVED:
4087                 /*
4088                  * NOTE: Tracking set by resolveType().
4089                  */
4090                 type->ty_Flags &= ~TF_RESOLVING;
4091                 type = resolveSuperClass(type);
4092                 if (type == NULL) {
4093                         errorDottedId(otype->ty_UnresType.et_DottedId,
4094                                       "Unable to resolve class");
4095                         dpanic("");
4096                         /* NOT REACHED */
4097                 }
4098                 type = RESOLVETYPE(type);
4099                 type->ty_Flags |= TF_RESOLVING;
4100                 /* visibility set by resolveSuperClass() */
4101                 break;
4102         case TY_DYNAMIC:
4103                 /*
4104                  * NOTE: Tracking unknown (must be handled at run-time).
4105                  */
4106                 type->ty_Visibility = SCOPE_ALL_VISIBLE;
4107                 break;
4108         case TY_IMPORT:
4109                 /*
4110                  * NOTE: Storage is persistent, so wrapper is not tracked.
4111                  */
4112                 type->ty_Visibility = SCOPE_ALL_VISIBLE;        /* XXX */
4113                 break;
4114         default:
4115                 dpanic("Unknown type %d (type=%p)", type->ty_Op, type);
4116                 break;
4117         }
4118         type->ty_Flags &= ~TF_RESOLVING;
4119         type->ty_Flags |= TF_RESOLVED;
4120         if (do2 && sg) {
4121                 do2 = resolveSemGroup2(sg, flags);
4122                 if (do2)
4123                         resolveSemGroup3(sg, flags);
4124         }
4125
4126         /*
4127          * Resolve tracking flags so the run-time can take appropriate
4128          * action.
4129          */
4130         if (sg) {
4131                 if (sg->sg_Flags & SGF_HASASS)
4132                         type->ty_Flags |= TF_HASASS;
4133                 if (sg->sg_SRBase)
4134                         type->ty_Flags |= TF_HASLVPTR;
4135                 if (sg->sg_Flags & SGF_VARARGS)
4136                         type->ty_Flags |= TF_HASLVPTR;  /* XXX TF_VARARGS */
4137                 if (sg->sg_CBase)
4138                         type->ty_Flags |= TF_HASCONSTRUCT;
4139                 if (sg->sg_DBase)
4140                         type->ty_Flags |= TF_HASDESTRUCT;
4141                 /*
4142                  * Combine constructor/destructor hint flags for globals
4143                  * because we have just one linked list for global constructors
4144                  * and destructors (no need to optimize heavily).
4145                  */
4146                 if (sg->sg_GBase)
4147                         type->ty_Flags |= TF_HASGCONSTRUCT|TF_HASGDESTRUCT;
4148         }
4149
4150         /*
4151          * Resolve the default expression for the type, if any.
4152          *
4153          * XXX qualified types just copy the exp. bad bad YYY
4154          *
4155          * YYY resolveExp() no ISG (import sem group)
4156          */
4157         if (type->ty_AssExp) {
4158                 if ((type->ty_AssExp->ex_Flags & EXF_RESOLVED) == 0) {
4159                         type->ty_AssExp = resolveExp(NULL, sg, type->ty_AssExp,
4160                                                      DEL_LVALUE(type),
4161                                                      flags | RESOLVE_AUTOCAST);
4162                 }
4163                 type->ty_Flags |= TF_HASASS;
4164         }
4165
4166         /*
4167          * If adjtype is non-NULL it must be moved to the new type's QList.
4168          */
4169         if (adjtype && type != otype) {
4170                 if (adjtype->ty_SQList)
4171                         RUNE_REMOVE(adjtype->ty_SQList, adjtype, ty_Node);
4172                 adjtype->ty_SQList = &type->ty_QList;
4173                 RUNE_INSERT_TAIL(adjtype->ty_SQList, adjtype, ty_Node);
4174         }
4175
4176         /*
4177          * ty_DynamicVector is nominally used when a Rune binary is run, but
4178          * we also need to set up enough of it such that mixed interpretation
4179          * and execution, or even just straight interpretation, works.  This
4180          * is because the interpreter calls into libruntime.
4181          */
4182         type->ty_DynamicVector = DefaultDynamicVector;
4183
4184         return(type);
4185 }
4186
4187 /*
4188  * resolveSuperClass() - resolve an unresolved dotted id sequence into a class
4189  *
4190  *      Unresolved type identifier sequences must be resolved.  We are also
4191  *      responsible for setting the visibility of the type's elements.
4192  */
4193 Type *
4194 resolveSuperClass(Type *super)
4195 {
4196         string_t *dottedId;
4197         SemGroup *sg;
4198         Declaration *d;
4199         int visibility = SCOPE_ALL_VISIBLE;
4200         int eno = 0;
4201
4202         dassert_type(super, super->ty_Op == TY_UNRESOLVED);
4203
4204         dottedId = super->ty_UnresType.et_DottedId;
4205         sg = super->ty_UnresType.et_SemGroup;
4206
4207         d = FindDeclPath(NULL, super->ty_UnresType.et_ImportSemGroup,
4208                          sg, super,
4209                          dottedId, FDC_NULL, &visibility, -1, &eno);
4210         if (d == NULL)
4211                 return(NULL);
4212
4213         /*
4214          * Resolve the unresolved type.  Note that this occurs during class
4215          * resolution and we can't call resolveType() here without getting into
4216          * a loop, so we do not yet know storage requirements (ty_Bytes and
4217          * ty_Align).
4218          */
4219         switch(d->d_Op) {
4220         case DOP_CLASS:
4221                 sg = d->d_ClassDecl.ed_SemGroup;
4222                 super->ty_Op = TY_CLASS;
4223                 super->ty_ClassType.et_SemGroup = sg;
4224                 super->ty_ClassType.et_Super = d->d_ClassDecl.ed_Super;
4225                 super->ty_Visibility = visibility;
4226                 if (super->ty_SQList)
4227                         RUNE_REMOVE(super->ty_SQList, super, ty_Node);
4228                 super->ty_SQList = &sg->sg_ClassList;
4229                 RUNE_INSERT_TAIL(super->ty_SQList, super, ty_Node);
4230                 dassert(visibility);
4231                 /*
4232                  * XXX should we move the class from the unresolved list to
4233                  * the new SemGroup's actual list?
4234                  */
4235                 break;
4236         case DOP_TYPEDEF:
4237                 /*
4238                  * Adjust super instead of allocating a new super, so all
4239                  * other references to super using this class path get
4240                  * resolved too.
4241                  */
4242                 {
4243                         dassert_type(super, d->d_TypedefDecl.ed_Type != super);
4244                         TypeToQualType(
4245                                 d->d_TypedefDecl.ed_Type,
4246                                 super,
4247                                 super->ty_SQFlags |
4248                                  d->d_TypedefDecl.ed_Type->ty_SQFlags,
4249                                 super->ty_AssExp
4250                         );
4251                 }
4252                 super->ty_Visibility = visibility;
4253                 break;
4254         default:
4255                 errorDottedId(dottedId, "identifier is not a class or typedef");
4256                 dassert_type(super, 0);
4257         }
4258         return(super);
4259 }
4260
4261 /*
4262  * Resolve the declarations in a semantic group.  We have to do this if
4263  * (a) The declaration(s) would not otherwise be resolved by our statement
4264  * scan, or (b) We need definitive size/alignment information now rather
4265  * then later.
4266  *
4267  * Also resolve SemGroup global initialization dependencies via SemGroupDepend.
4268  *
4269  * SemGroup resolution occurs in three stages in order to deal with
4270  * resolver loops.  The first stage does just enough to figure out
4271  * how large the non-global part of the SemGroup is (e.g. doesn't run
4272  * through pointers).  The second stage handles global elements, and the
4273  * third stage completes the process.
4274  *
4275  * NOTE!  This code does not resolve declarations related to executable
4276  * semantic groups, such as sub-blocks within a procedure, but it does
4277  * have to resolve procedure definitions found in Class's and such.
4278  *
4279  * NOTE!  This code handles the last stage of subclass refinement, by 
4280  * checking the validity of the refinement and setting sg_Compat properly.
4281  */
4282 static
4283 int
4284 resolveSemGroup1(SemGroup *sg, int flags)
4285 {
4286         SemGroup *dep;
4287         Declaration *d;
4288         Type *type;
4289
4290         flags &= ~RESOLVE_AUTOCAST;     /* not applicable to this function */
4291
4292         dep = resolvePushSGDepend(sg);
4293         if (sg->sg_Flags & SGF_RESOLVED) {
4294                 resolvePopSGDepend(dep);
4295                 return(0);
4296         }
4297         if (sg->sg_Flags & SGF_RESOLVING) {
4298                 fprintf(stderr,
4299                         "Unable to resolve embedded recursive reference\n");
4300                 dassert_semgrp(sg, (sg->sg_Flags & SGF_RESOLVING) == 0);
4301         }
4302         sg->sg_Flags |= SGF_RESOLVING;
4303
4304         /*
4305          * First pass - resolve storage only.  Note that this specifically
4306          * does not try to handle the multiple semantic layers inside a
4307          * procedure.  See ResolveStorage() for that.
4308          */
4309         RUNE_FOREACH(d, &sg->sg_DeclList, d_Node) {
4310                 switch(d->d_Op) {
4311                 case DOP_CLASS:
4312                 case DOP_TYPEDEF:
4313                 case DOP_ALIAS:
4314                 case DOP_IMPORT:
4315                         break;
4316                 case DOP_PROC:
4317                         /*
4318                          * Deal with constructor/destructor chaining.
4319                          */
4320                         if (d->d_ScopeFlags & SCOPE_GLOBAL) {
4321                                 if ((d->d_Flags & DF_ONGLIST) == 0 &&
4322                                     (d->d_ScopeFlags & (SCOPE_CONSTRUCTOR |
4323                                                        SCOPE_DESTRUCTOR))) {
4324                                         d->d_GNext = d->d_MyGroup->sg_GBase;
4325                                         d->d_MyGroup->sg_GBase = d;
4326                                         d->d_Flags |= DF_ONGLIST;
4327                                 }
4328                         } else {
4329                                 if ((d->d_Flags & DF_ONCLIST) == 0 &&
4330                                     (d->d_ScopeFlags & SCOPE_CONSTRUCTOR)) {
4331                                         d->d_CNext = d->d_MyGroup->sg_CBase;
4332                                         d->d_MyGroup->sg_CBase = d;
4333                                         d->d_Flags |= DF_ONCLIST;
4334                                 }
4335                                 if ((d->d_Flags & DF_ONDLIST) == 0 &&
4336                                     (d->d_ScopeFlags & SCOPE_DESTRUCTOR)) {
4337                                         d->d_DNext = d->d_MyGroup->sg_DBase;
4338                                         d->d_MyGroup->sg_DBase = d;
4339                                         d->d_Flags |= DF_ONDLIST;
4340                                 }
4341                         }
4342                         break;
4343                 case DOP_STACK_STORAGE:
4344                         /*
4345                          * can't happen.  Stack storage is only used in
4346                          * executable contexts.
4347                          */
4348                         dassert_decl(d, 0);
4349                 case DOP_ARGS_STORAGE:
4350                 case DOP_GROUP_STORAGE:
4351                         type = d->d_StorDecl.ed_Type;
4352
4353                         switch(type->ty_Op) {
4354                         case TY_CPTRTO:
4355                                 d->d_Bytes = sizeof(void *);
4356                                 d->d_AlignMask = POINTER_ALIGN;
4357                                 if ((d->d_Scope.s_Flags & SCOPE_ALIGN) &&
4358                                     d->d_Scope.s_AlignOverride) {
4359                                         d->d_AlignMask =
4360                                                 d->d_Scope.s_AlignOverride - 1;
4361                                 }
4362                                 break;
4363                         case TY_PTRTO:
4364                         case TY_REFTO:
4365                                 if (d->d_ScopeFlags & SCOPE_LVALUE) {
4366                                         /*
4367                                          * NOTE: d->d_Bytes is different from
4368                                          *       the size of the underlying
4369                                          *       type that the LValueStor
4370                                          *       points to.
4371                                          */
4372                                         dassert(d->d_Op == DOP_ARGS_STORAGE);
4373                                         d->d_Bytes = sizeof(LValueStor);
4374                                         d->d_AlignMask = LVALUE_ALIGN;
4375                                 } else {
4376                                         d->d_Bytes = sizeof(PointerStor);
4377                                         d->d_AlignMask = POINTER_ALIGN;
4378                                 }
4379                                 if ((d->d_Scope.s_Flags & SCOPE_ALIGN) &&
4380                                     d->d_Scope.s_AlignOverride) {
4381                                         d->d_AlignMask =
4382                                                 d->d_Scope.s_AlignOverride - 1;
4383                                 }
4384                                 break;
4385                         default:
4386                                 resolveDecl(d, flags);
4387                                 break;
4388                         }
4389                         if (sg->sg_AlignMask < d->d_AlignMask)
4390                                 sg->sg_AlignMask = d->d_AlignMask;
4391                         sg->sg_Bytes = (sg->sg_Bytes + d->d_AlignMask) &
4392                                        ~d->d_AlignMask;
4393                         d->d_Offset = sg->sg_Bytes;
4394                         sg->sg_Bytes += d->d_Bytes;
4395                         if (d->d_StorDecl.ed_AssExp)
4396                                 sg->sg_Flags |= SGF_HASASS;
4397                         if (type->ty_Flags & TF_HASASS)
4398                                 sg->sg_Flags |= SGF_HASASS;
4399                         if (type->ty_Flags & TF_HASLVPTR)
4400                                 sg->sg_Flags |= SGF_HASLVPTR;
4401                         break;
4402                 case DOP_GLOBAL_STORAGE:
4403                         /* handled in pass2 */
4404                         break;
4405                 default:
4406                         dassert_semgrp(sg, 0);
4407                         break;
4408                 }
4409 #if 0
4410                 /*
4411                  * Rollup &obj into a SemGroup flag.
4412                  */
4413                 if (d->d_Flags & DF_ADDRUSED) {
4414                         sg->sg_Flags |= SGF_ADDRUSED;
4415                         fprintf(stderr, "RESOLVER ADDRUSED %s\n", d->d_Id);
4416                 }
4417 #endif
4418         }
4419
4420         /*
4421          * Final alignment
4422          */
4423         sg->sg_Bytes = (sg->sg_Bytes + sg->sg_AlignMask) & ~sg->sg_AlignMask;
4424         sg->sg_Flags |= SGF_RESOLVED;
4425         resolvePopSGDepend(dep);
4426
4427         return(1);
4428 }
4429
4430 /*
4431  * Followup - resolve globals
4432  */
4433 static
4434 int
4435 resolveSemGroup2(SemGroup *sg, int flags)
4436 {
4437         Declaration *d;
4438         Type *type;
4439
4440         flags &= ~RESOLVE_AUTOCAST;     /* not applicable to this function */
4441
4442         if (sg->sg_Flags & SGF_GRESOLVED)
4443                 return(0);
4444         if (sg->sg_Flags & SGF_GRESOLVING) {
4445                 fprintf(stderr,
4446                         "Unable to resolve embedded recursive reference\n");
4447                 dassert_semgrp(sg, (sg->sg_Flags & SGF_GRESOLVING) == 0);
4448         }
4449         sg->sg_Flags |= SGF_GRESOLVING;
4450
4451         /*
4452          * First pass - resolve storage only.  Note that this specifically
4453          * does not try to handle the multiple semantic layers inside a
4454          * procedure.  See ResolveStorage() for that.
4455          */
4456         RUNE_FOREACH(d, &sg->sg_DeclList, d_Node) {
4457                 switch(d->d_Op) {
4458                 case DOP_CLASS:
4459                 case DOP_TYPEDEF:
4460                 case DOP_ALIAS:
4461                 case DOP_IMPORT:
4462                 case DOP_PROC:
4463                         break;
4464                 case DOP_STACK_STORAGE:
4465                         /*
4466                          * can't happen.  Stack storage is only used in
4467                          * executable contexts.
4468                          */
4469                         dassert_decl(d, 0);
4470                 case DOP_ARGS_STORAGE:
4471                 case DOP_GROUP_STORAGE:
4472                         /*
4473                          * Non-globals were handled in pass-1
4474                          */
4475                         break;
4476                 case DOP_GLOBAL_STORAGE:
4477                         /*
4478                          * Global storage must be handled in pass-2
4479                          */
4480                         type = d->d_StorDecl.ed_Type;
4481
4482                         switch(type->ty_Op) {
4483                         case TY_CPTRTO:
4484                                 d->d_Bytes = sizeof(void *);
4485                                 d->d_AlignMask = POINTER_ALIGN;
4486                                 if ((d->d_Scope.s_Flags & SCOPE_ALIGN) &&
4487                                     d->d_Scope.s_AlignOverride) {
4488                                         d->d_AlignMask =
4489                                                 d->d_Scope.s_AlignOverride - 1;
4490                                 }
4491                                 break;
4492                         case TY_PTRTO:
4493                         case TY_REFTO:
4494                                 d->d_Bytes = sizeof(PointerStor);
4495                                 d->d_AlignMask = POINTER_ALIGN;
4496                                 if ((d->d_Scope.s_Flags & SCOPE_ALIGN) &&
4497                                     d->d_Scope.s_AlignOverride) {
4498                                         d->d_AlignMask =
4499                                                 d->d_Scope.s_AlignOverride - 1;
4500                                 }
4501                                 break;
4502                         default:
4503                                 resolveDecl(d, flags);
4504                                 break;
4505                         }
4506                         if (sg->sg_GlobalAlignMask < d->d_AlignMask)
4507                                 sg->sg_GlobalAlignMask = d->d_AlignMask;
4508                         sg->sg_GlobalBytes = (sg->sg_GlobalBytes +
4509                                               d->d_AlignMask) & ~d->d_AlignMask;
4510                         d->d_Offset = sg->sg_GlobalBytes;
4511                         sg->sg_GlobalBytes += d->d_Bytes;
4512                         if (d->d_StorDecl.ed_AssExp)
4513                                 sg->sg_Flags |= SGF_GHASASS;
4514                         if (type->ty_Flags & TF_HASASS)
4515                                 sg->sg_Flags |= SGF_GHASASS;
4516                         if (type->ty_Flags & TF_HASLVPTR)
4517                                 sg->sg_Flags |= SGF_GHASLVPTR;
4518                         break;
4519                 default:
4520                         dassert_semgrp(sg, 0);
4521                         break;
4522                 }
4523         }
4524
4525         /*
4526          * Final alignment
4527          */
4528         sg->sg_GlobalBytes = (sg->sg_GlobalBytes + sg->sg_GlobalAlignMask) &
4529                              ~sg->sg_GlobalAlignMask;
4530         sg->sg_Flags |= SGF_GRESOLVED;
4531         return(1);
4532 }
4533
4534 static
4535 void
4536 resolveSemGroup3(SemGroup *sg, int flags)
4537 {
4538         Declaration *d;
4539         int dyncount;
4540
4541         flags &= ~RESOLVE_AUTOCAST;     /* not applicable to this function */
4542
4543         /*
4544          * 0 - reserved for dynamic initialization
4545          * 1 - reserved for dynamic destructor
4546          */
4547         dyncount = 2;
4548
4549         /*
4550          * Third pass, resolve non-storage entities after setting
4551          * SGF_RESOLVED, these entities may legally embed this class (if
4552          * this is a class).
4553          *
4554          * Resolve pointers that were only partially resolved in the first
4555          * pass.
4556          *
4557          * Refinements have been resolved but we have to check them for
4558          * legality and set sg_Compat.
4559          *
4560          * Note that this is what allows us to typedef a subclass in its
4561          * superclass.  The typedef itself is safe.
4562          *
4563          * Also resolve storage pointer entities that were skipped in the
4564          * first pass.  Such pointers could point to ourselves.
4565          *
4566          * Finally, set SCOPE_UNLOCKED on any entity which does not
4567          * contain any lockable data (like int's).
4568          */
4569         RUNE_FOREACH(d, &sg->sg_DeclList, d_Node) {
4570                 /*
4571                  * Final resolution of refinements.
4572                  */
4573                 if (d->d_ScopeFlags & SCOPE_REFINE) {
4574                         resolveDecl(d->d_Super, flags);
4575                         resolveDecl(d, flags);
4576                         RefineDeclaration(sg, d->d_Super, d);
4577                 }
4578
4579                 /*
4580                  * Yada yada.
4581                  */
4582                 switch(d->d_Op) {
4583                 case DOP_CLASS:
4584                 case DOP_TYPEDEF:
4585                 case DOP_ALIAS:
4586                 case DOP_IMPORT:
4587                         resolveDecl(d, flags);
4588                         break;
4589                 case DOP_PROC:
4590                         resolveDecl(d, flags);
4591
4592                         /*
4593                          * For now internal generation does not need a
4594                          * dynamic component (and doesn't generate external
4595                          * code so the function wouldn't exist anyway).
4596                          */
4597                         if (d->d_ScopeFlags & SCOPE_INTERNAL)
4598                                 continue;
4599
4600                         /*
4601                          * Assign the dynamic index.  There may be multiple
4602                          * entries for the same d_Id, they are ordered such
4603                          * that refinements use the same DynIndex as in
4604                          * the superclass which is what allows dynamic method
4605                          * calls to work properly.  All non-refined subclass
4606                          * elements are ordered after all refined/non=refined
4607                          * superclass elements (replacing the superclass
4608                          * element and using the same DynIndex when refined).
4609                          */
4610                         d->d_DynIndex = dyncount;
4611                         ++dyncount;
4612                         break;
4613                 case DOP_ARGS_STORAGE:
4614                 case DOP_GROUP_STORAGE:
4615                 /*case DOP_STACK_STORAGE:*/
4616                 case DOP_GLOBAL_STORAGE:
4617                         switch(d->d_StorDecl.ed_Type->ty_Op) {
4618                         case TY_CPTRTO:
4619                         case TY_PTRTO:
4620                         case TY_REFTO:
4621                                 resolveDecl(d, flags);
4622                                 break;
4623                         }
4624                         break;
4625                 default:
4626                         dassert_semgrp(sg, 0);
4627                         break;
4628                 }
4629         }
4630
4631         /*
4632          * If no dynamic methods and no dynamic initialization or destruction
4633          * required, set dyncount to 0.
4634          */
4635         if (dyncount == 2 &&
4636             (sg->sg_Flags & SGF_HASASS) == 0 &&
4637             sg->sg_SRBase == NULL &&
4638             sg->sg_CBase == NULL &&
4639             sg->sg_DBase == NULL) {
4640                 dyncount = 0;
4641         }
4642         sg->sg_DynCount = dyncount;
4643         sg->sg_Flags &= ~SGF_RESOLVING;
4644 }
4645
4646 /*
4647  * findExpOper() -      Find operator declaration matching expression
4648  *
4649  *      Locate the operator declaration (a DOP_PROCDEF) that matches
4650  *      the expression or NULL if no match could be found.  The expression's
4651  *      left and right hand sides must already be resolved.
4652  *
4653  *      NOTE!  A temporary 'copy' Exp may be passed, not all fields are valid.
4654  */
4655 static
4656 Declaration *
4657 findExpOper(Exp *exp, int flags)
4658 {
4659         Type *ltype;
4660         Type *rtype;
4661         Declaration *d;
4662
4663         flags &= ~RESOLVE_AUTOCAST;     /* not applicable to this function */
4664
4665         if (exp->ex_Flags & EXF_BINARY) {
4666                 rtype = exp->ex_Rhs->ex_Type;
4667                 ltype = exp->ex_Lhs->ex_Type;
4668         } else {
4669                 dassert(exp->ex_Flags & EXF_UNARY);
4670                 rtype = NULL;
4671                 ltype = exp->ex_Lhs->ex_Type;
4672         }
4673
4674         /*
4675          * XXX look in our local semantic hierarchy for a compatible operator ?
4676          */
4677
4678         /*
4679          * Attempt to find a matching operator from the left hand side
4680          */
4681         d = findOper(ltype, exp->ex_Id, ltype, rtype, flags);
4682
4683         if (d || (exp->ex_Flags & EXF_BINARY) == 0)
4684                 return(d);
4685
4686         d = findOper(rtype, exp->ex_Id, ltype, rtype, flags);
4687         return(d);
4688 }
4689
4690 static
4691 Declaration *
4692 findOper(Type *btype, string_t id, Type *ltype, Type *rtype, int flags)
4693 {
4694         SemGroup *sg;
4695         Declaration *d;
4696         int args = (rtype != NULL) ? 2 : 1;
4697
4698         flags &= ~RESOLVE_AUTOCAST;     /* not applicable to this function */
4699
4700         /*
4701          * Locate the base type.  If the base type does not have a SemGroup
4702          * there are no operators.  (XXX put system operators here)
4703          */
4704         sg = BaseType(&btype);
4705
4706         if (sg == NULL)
4707                 return(NULL);
4708
4709         /*
4710          * Look for the operator in the SemGroup
4711          */
4712         for (d = FindOperId(sg, id, args); d; d = d->d_ONext) {
4713                 resolveDecl(d, flags);
4714                 if (d->d_MyGroup == sg &&
4715                         d->d_Op == DOP_PROC &&
4716                         d->d_ProcDecl.ed_OperId == id &&
4717                         MatchOperatorTypes(d, ltype, rtype)
4718                 ) {
4719                         return(d);
4720                 }
4721         }
4722
4723         /*
4724          * Failed.  If the base type is a compound type, look for the
4725          * operator in the SemGroup for each element making up the compound
4726          * type.  e.g. so (mycustomtype, double) would find the operator
4727          * in mycustomtype.
4728          */
4729         if (btype->ty_Op == TY_COMPOUND) {
4730                 RUNE_FOREACH(d, &sg->sg_DeclList, d_Node) {
4731                         Declaration *d2;
4732                         if (d->d_Op & DOPF_STORAGE) {
4733                                 d2 = findOper(d->d_StorDecl.ed_Type, id,
4734                                               ltype, rtype, flags);
4735                         } else if (d->d_Op == DOP_TYPEDEF) {
4736                                 d2 = findOper(d->d_TypedefDecl.ed_Type, id,
4737                                               ltype, rtype, flags);
4738                         } else {
4739                                 d2 = NULL;
4740                         }
4741                         if (d2)
4742                                 return(d2);
4743                 }
4744         }
4745         return(NULL);
4746 }
4747
4748 static void
4749 errorDottedId(string_t *ary, const char *ctl, ...)
4750 {
4751         va_list va;
4752         int i;
4753
4754         va_start(va, ctl);
4755         vfprintf(stderr, ctl, va);
4756         va_end(va);
4757         fprintf(stderr, ": %s", ary[0]);
4758         for (i = 1; ary[i]; ++i)
4759                 fprintf(stderr, ".%s", ary[i]);
4760         fprintf(stderr, "\n");
4761 }
4762
4763 /*
4764  * Resolve the alignment requirements for SemGroups related to
4765  * statements, including the alignment requirements needed for
4766  * temporary expression space.
4767  */
4768 void
4769 ResolveAlignment(Stmt *st, int flags)
4770 {
4771         SemGroup *sg = st->st_MyGroup;
4772         Stmt *scan;
4773
4774         if (st->st_Flags & STF_ALIGNRESOLVED)
4775                 return;
4776         st->st_Flags |= STF_ALIGNRESOLVED;
4777
4778         /*
4779          * If this is an executable semantic layer or an import layer then
4780          * assign storage to declarations up-front.  Of the various
4781          * DOP_*_STORAGE ops, we should only see DOP_STACK_STORAGE and
4782          * DOP_GLOBAL_STORAGE.
4783          *
4784          * Note: if this is the root ST_Import STF_SEMANTIC is *NOT* set and
4785          * sg will be NULL.
4786          */
4787         if ((st->st_Flags & STF_SEMANTIC) && st->st_Op != ST_Class) {
4788                 Declaration *d;
4789
4790                 /*
4791                  * Pre-scan for alignment.  Don't try to propagate the
4792                  * alignment to the parent for now as that would require
4793                  * recalculating the parent(s).
4794                  */
4795                 RUNE_FOREACH(d, &sg->sg_DeclList, d_Node) {
4796                         switch(d->d_Op) {
4797                         case DOP_STACK_STORAGE:
4798                         case DOP_ARGS_STORAGE:
4799                         case DOP_GROUP_STORAGE:
4800                                 if (sg->sg_AlignMask < d->d_AlignMask)
4801                                         sg->sg_AlignMask = d->d_AlignMask;
4802                                 break;
4803                         case DOP_GLOBAL_STORAGE:
4804                                 if (sg->sg_GlobalAlignMask < d->d_AlignMask)
4805                                         sg->sg_GlobalAlignMask = d->d_AlignMask;
4806                                 break;
4807                         default:
4808                                 break;
4809                         }
4810                 }
4811         }
4812
4813         switch(st->st_Op) {
4814         case ST_Import:
4815                 break;
4816         case ST_Module:
4817         case ST_Class:
4818                 break;
4819         case ST_Typedef:
4820                 /* XXX needed? */
4821                 {
4822                         Declaration *d;
4823
4824                         d = st->st_TypedefStmt.es_Decl;
4825                         resolveStorageDeclExpAlign(d, &sg->sg_TmpAlignMask);
4826                 }
4827                 break;
4828         case ST_Decl:
4829                 /*
4830                  * NOTE: Don't calculate for declarations that belong in
4831                  *       a different context.
4832                  */
4833                 {
4834                         Declaration *d;
4835                         int i;
4836
4837                         d = st->st_DeclStmt.es_Decl;
4838
4839                         for (i = 0; i < st->st_DeclStmt.es_DeclCount; ++i) {
4840                                 if (st->st_MyGroup == d->d_MyGroup)
4841                                         resolveStorageDeclExpAlign(d, &sg->sg_TmpAlignMask);
4842                                 d = RUNE_NEXT(d, d_Node);
4843                         }
4844                 }
4845                 break;
4846         case ST_Block:
4847                 break;
4848         case ST_Proc:
4849                 break;
4850         case ST_Nop:
4851                 break;
4852         case ST_Loop:
4853                 {
4854                         if (st->st_LoopStmt.es_BCond) {
4855                                 resolveStorageExpAlign(st->st_LoopStmt.es_BCond,
4856                                                        &sg->sg_TmpAlignMask);
4857                         }
4858                         if (st->st_LoopStmt.es_ACond) {
4859                                 resolveStorageExpAlign(st->st_LoopStmt.es_ACond,
4860                                                        &sg->sg_TmpAlignMask);
4861                         }
4862                         if (st->st_LoopStmt.es_AExp) {
4863                                 resolveStorageExpAlign(st->st_LoopStmt.es_AExp,
4864                                                        &sg->sg_TmpAlignMask);
4865                         }
4866                 }
4867                 break;
4868         case ST_BreakCont:
4869                 break;
4870         case ST_Bad:
4871                 break;
4872         case ST_IfElse:
4873                 resolveStorageExpAlign(st->st_IfStmt.es_Exp,
4874                                        &sg->sg_TmpAlignMask);
4875                 break;
4876         case ST_Return:
4877                 if (st->st_RetStmt.es_Exp)
4878                         resolveStorageExpAlign(st->st_RetStmt.es_Exp,
4879                                                &sg->sg_TmpAlignMask);
4880                 break;
4881         case ST_Result:
4882                 if (st->st_ResStmt.es_Exp)
4883                         resolveStorageExpAlign(st->st_ResStmt.es_Exp,
4884                                                &sg->sg_TmpAlignMask);
4885                 break;
4886         case ST_Switch:
4887                 /*
4888                  * The switch expression's temporary data must be saved while
4889                  * we are executing the sub-statements (the cases).
4890                  */
4891                 resolveStorageExpAlign(st->st_SwStmt.es_Exp,
4892                                        &sg->sg_TmpAlignMask);
4893                 break;
4894         case ST_Case:
4895                 if (st->st_CaseStmt.es_Exp)
4896                         resolveStorageExpAlign(st->st_CaseStmt.es_Exp,
4897                                                &sg->sg_TmpAlignMask);
4898                 break;
4899         case ST_Exp:
4900                 resolveStorageExpAlign(st->st_ExpStmt.es_Exp,
4901                                        &sg->sg_TmpAlignMask);
4902                 break;
4903         case ST_ThreadSched:
4904                 break;
4905         default:
4906                 dassert_stmt(st, 0);
4907         }
4908
4909         /*
4910          * Calculate storage requirements for substatements.  offset
4911          * acts as our base.  We union the storage for the substatements
4912          * together.  Note that often scan->sg_MyGroup == sg.
4913          */
4914         RUNE_FOREACH(scan, &st->st_List, st_Node) {
4915                 if (scan->st_Op == ST_Class) {
4916                         ResolveAlignment(scan, flags);
4917                 } else if (scan->st_Op == ST_Decl &&
4918                            scan->st_DeclStmt.es_Decl->d_MyGroup !=
4919                            st->st_MyGroup) {
4920                         /*
4921                          * Do nothing
4922                          */
4923                         ;
4924                 } else if (scan->st_Op == ST_Decl &&
4925                            (scan->st_DeclStmt.es_Decl->d_Flags & DF_RESOLVED)) {
4926                         /*
4927                          * See prior comments, skip declarations that
4928                          * were moved to another context
4929                          *
4930                          * (already resolved so can use junk offsets)
4931                          */
4932                         resolveStorageDeclExpAlign(scan->st_DeclStmt.es_Decl,
4933                                                    &sg->sg_TmpAlignMask);
4934                 } else if (scan->st_Op == ST_Proc && 
4935                            scan->st_ProcStmt.es_Decl->d_ProcDecl.ed_OrigBody == scan
4936                 ) {
4937                         /* Do not resolve template procedures! */
4938                 } else if (scan->st_Flags & STF_SEMTOP) {
4939                         ResolveAlignment(scan, flags);
4940                 } else {
4941                         ResolveAlignment(scan, flags);
4942                 }
4943         }
4944
4945         /*
4946          * If this is a new semantic level call resolveStorageSemGroup() to
4947          * do the final cleanup of SemGroup issues.  This will redundantly
4948          * calculate temporary space requirements.  Also, due to type/class
4949          * references the temporary space for a class may have already been
4950          * resolved.  Since a class can only contain declarations it had
4951          * better match what we calculate here.
4952          *
4953          * Note that for non-Class executable SemGroup's TmpBytes is
4954          * incorporated in a downward fashion while sg_Bytes is incorporated
4955          * in an upward fashion.  It can become quite confusing.  Don't ask
4956          * me why I did it that way.
4957          */
4958         if (st->st_Flags & STF_SEMANTIC) {
4959                 if ((sg->sg_Flags & SGF_TMPRESOLVED) == 0) {
4960                         resolveStorageSemGroupAlign(sg);
4961                 }
4962         }
4963
4964         /*
4965          * Propagate alignment requirements upward.
4966          */
4967         if ((st->st_Flags & (STF_SEMANTIC|STF_SEMTOP)) == STF_SEMANTIC) {
4968                 if (sg->sg_Parent->sg_AlignMask < sg->sg_AlignMask)
4969                         sg->sg_Parent->sg_AlignMask = sg->sg_AlignMask;
4970                 if (sg->sg_Parent->sg_TmpAlignMask < sg->sg_TmpAlignMask)
4971                         sg->sg_Parent->sg_TmpAlignMask = sg->sg_TmpAlignMask;
4972         }
4973 }
4974
4975 /*
4976  * ResolveStorage() -   Final storage resolution pass
4977  *
4978  *      This pass carefully scans the SemGroup hierarchy and assigns
4979  *      offsets to declarations.
4980  *
4981  *      PROCEDURES - all the various 'executable' semantic layers in
4982  *      a procedure are collapsed together for efficiency, so we only
4983  *      have to manage one context.  This means that the d_Offset 
4984  *      assigned to declarations in sub-blocks may exceed the sg_ size
4985  *      of the sub-block's SemGroup.  We do not attempt to resolve
4986  *      procedure body templates (d_ProcDecl.ed_OrigBody).
4987  *
4988  *      CLASSES - are given offsets in their SemGroup's relative to 0, if
4989  *                not already resolved.
4990  *
4991  *      IMPORTS - are given offsets in their SemGroup's relative to 0
4992  *
4993  *      COMPOUND TYPES - (such as procedure arguments) are given offsets
4994  *      in their SemGroup's relative to 0.
4995  *
4996  *      TEMPORARY STORAGE - expressions may require temporary storage
4997  *      for intermediate results.  That space is reserved here.
4998  *
4999  *      We specifically do not resolve unrelated storage.
5000  */
5001 static
5002 void
5003 ResolveStorage(Stmt *st, int flags)
5004 {
5005         runesize_t noffset;
5006         runesize_t offset;
5007         runesize_t goffset;
5008         runesize_t ngoffset;
5009         SemGroup *sg = st->st_MyGroup;
5010         Stmt *scan;
5011         Type *type;
5012
5013 #if 0
5014         if (st->st_Op != ST_Class) {
5015                 dassert((st->st_Flags & STF_RESOLVING) == 0);
5016                 if (st->st_Flags & STF_RESOLVED) {
5017                         return;
5018                 }
5019                 st->st_Flags |= STF_RESOLVING;
5020         }
5021 #endif
5022         dassert(st->st_Flags & STF_ALIGNRESOLVED);
5023         if (st->st_Flags & STF_TMPRESOLVED)
5024                 return;
5025         st->st_Flags |= STF_TMPRESOLVED;
5026
5027         /*
5028          * If this is an executable semantic layer or an import layer then
5029          * assign storage to declarations up-front.  Of the various
5030          * DOP_*_STORAGE ops, we should only see DOP_STACK_STORAGE and
5031          * DOP_GLOBAL_STORAGE.
5032          *
5033          * Note: if this is the root ST_Import STF_SEMANTIC is *NOT* set and
5034          * sg will be NULL.
5035          */
5036         if ((st->st_Flags & STF_SEMANTIC) && st->st_Op != ST_Class) {
5037                 Declaration *d;
5038
5039                 dassert((sg->sg_Flags & (SGF_FRESOLVED|SGF_FRESOLVING)) == 0);
5040
5041                 sg->sg_Flags |= SGF_FRESOLVING;
5042
5043                 /*
5044                  * The base offset for sub-semantic-blocks must match the
5045                  * alignment they require in order to allow us to do an
5046                  * aligned BZEROing of the space.  We do not include the
5047                  * temporary space here (it does not need to be BZERO'd).
5048                  *
5049                  * NOTE: sg_TmpAlignMask is taken into accoun when the
5050                  *       top-level frame is allocated.
5051                  */
5052                 if (st->st_Flags & STF_SEMTOP) {
5053                         dassert(sg->sg_Bytes == 0);
5054                         offset = 0;
5055                 } else {
5056                         offset = sg->sg_Parent->sg_Bytes;
5057                         offset = (offset + sg->sg_AlignMask) &
5058                                  ~sg->sg_AlignMask;
5059                 }
5060
5061                 sg->sg_BlkOffset = offset;
5062
5063                 RUNE_FOREACH(d, &sg->sg_DeclList, d_Node) {
5064                         switch(d->d_Op) {
5065                         case DOP_STACK_STORAGE:
5066                         case DOP_ARGS_STORAGE:
5067                         case DOP_GROUP_STORAGE:
5068                                 type = d->d_StorDecl.ed_Type;
5069                                 offset = (offset + d->d_AlignMask) &
5070                                         ~d->d_AlignMask;
5071                                 dassert_decl(d, d->d_Offset == (runesize_t)-1);
5072                                 d->d_Offset = offset;
5073                                 offset += d->d_Bytes;
5074                                 if (d->d_StorDecl.ed_AssExp)
5075                                         sg->sg_Flags |= SGF_HASASS;
5076                                 if (type->ty_Flags & TF_HASASS)
5077                                         sg->sg_Flags |= SGF_HASASS;
5078                                 if (type->ty_Flags & TF_HASLVPTR)
5079                                         sg->sg_Flags |= SGF_HASLVPTR;
5080                                 break;
5081                         case DOP_GLOBAL_STORAGE:
5082                                 type = d->d_StorDecl.ed_Type;
5083                                 sg->sg_GlobalBytes =
5084                                         (sg->sg_GlobalBytes + d->d_AlignMask) &
5085                                         ~d->d_AlignMask;
5086                                 dassert_decl(d, d->d_Offset == (runesize_t)-1);
5087                                 d->d_Offset = sg->sg_GlobalBytes;
5088                                 sg->sg_GlobalBytes += d->d_Bytes;
5089                                 if (d->d_StorDecl.ed_AssExp)
5090                                         sg->sg_Flags |= SGF_GHASASS;
5091                                 if (type->ty_Flags & TF_HASASS)
5092                                         sg->sg_Flags |= SGF_GHASASS;
5093                                 if (type->ty_Flags & TF_HASLVPTR)
5094                                         sg->sg_Flags |= SGF_GHASLVPTR;
5095                                 break;
5096                         default:
5097                                 break;
5098                         }
5099                 }
5100
5101                 /*
5102                  * The byte size of the block does not have to be aligned,
5103                  * but aligning it (within reason) might provide a benefit.
5104                  */
5105                 sg->sg_Bytes = offset;
5106
5107 #if 0
5108                 if (sg->sg_AlignMask < 256) {
5109                         sg->sg_Bytes = (offset + sg->sg_AlignMask) &
5110                                        ~sg->sg_AlignMask;
5111                 }
5112                 if (sg->sg_GlobalAlignMask < 256) {
5113                         sg->sg_GlobalBytes =
5114                                 (sg->sg_GlobalBytes + sg->sg_GlobalAlignMask) &
5115                                 ~sg->sg_GlobalAlignMask;
5116                 }
5117 #endif
5118                 sg->sg_BlkBytes = sg->sg_Bytes - sg->sg_BlkOffset;
5119                 sg->sg_Flags |= SGF_FRESOLVED;
5120                 sg->sg_Flags &= ~SGF_FRESOLVING;
5121         }
5122
5123         /*
5124          * Figure out how much temporary space we need to be able to execute
5125          * statements and expressions.  Temporary space, like the main
5126          * procedural space, must be inherited from and consolidated into
5127          * the top-level SemGroup
5128          */
5129         if (sg) {
5130                 offset = sg->sg_TmpBytes;
5131                 noffset = offset;
5132                 goffset = sg->sg_GlobalTmpBytes;
5133                 ngoffset = goffset;
5134         } else {
5135                 /*
5136                  * Root ST_Import.  avoid compiler warnings
5137                  */
5138                 offset = 0;
5139                 noffset = 0;
5140                 goffset = 0;
5141                 ngoffset = 0;
5142         }
5143
5144         switch(st->st_Op) {
5145         case ST_Import:
5146                 if (st->st_ImportStmt.es_DLL) {
5147                         void (*func)(void) = dlsym(st->st_ImportStmt.es_DLL,
5148                                                    "resolveStorage");
5149                         if (func)
5150                                 func();
5151                 }
5152                 break;
5153         case ST_Module:
5154         case ST_Class:
5155                 break;
5156         case ST_Typedef:
5157                 {
5158                         resolveStorageDeclExp(st->st_TypedefStmt.es_Decl,
5159                                               &noffset, &ngoffset);
5160                 }
5161                 break;
5162         case ST_Decl:
5163                 /*
5164                  * Temporary space for declarations are handled here.
5165                  *
5166                  * Resolve declarations, skipping any whos context was
5167                  * moved to a class (e.g. a declaration at the top level
5168                  * of a file like Fd.setfd(...) also exists in the Fd class).
5169                  */
5170                 {
5171                         Declaration *d;
5172                         int i;
5173
5174                         d = st->st_DeclStmt.es_Decl;
5175
5176                         if (d->d_Op == DOP_GLOBAL_STORAGE)
5177                                 st->st_DeclStmt.es_TmpOffset = goffset;
5178                         else
5179                                 st->st_DeclStmt.es_TmpOffset = offset;
5180                         printf("STDECLTMPOFFSET %zd\n", offset);
5181                         for (i = 0; i < st->st_DeclStmt.es_DeclCount; ++i) {
5182                                 runesize_t xoffset = offset;
5183                                 runesize_t xgoffset = goffset;
5184
5185 #if 1
5186                                 if (st->st_MyGroup != d->d_MyGroup) {
5187                                         /*printf("SKIPB %s\n", d->d_Id)*/;
5188                                         resolveStorageDeclExp(d, &xoffset, &xgoffset);
5189                                 } else if (d->d_Flags & DF_RESOLVED) {
5190                                         resolveStorageDeclExp(d, &xoffset, &xgoffset);
5191                                 }
5192 #endif
5193                                 else
5194                                         resolveStorageDeclExp(
5195                                                         d,
5196                                                         &xoffset,
5197                                                         &xgoffset);
5198
5199                                 if (noffset < xoffset)
5200                                         noffset = xoffset;
5201                                 if (ngoffset < xgoffset)
5202                                         ngoffset = xgoffset;
5203                                 d = RUNE_NEXT(d, d_Node);
5204                         }
5205                 }
5206                 break;
5207         case ST_Block:
5208                 break;
5209         case ST_Proc:
5210                 break;
5211         case ST_Nop:
5212                 break;
5213         case ST_Loop:
5214                 {
5215                         runesize_t xoffset;
5216
5217                         if (st->st_LoopStmt.es_BCond) {
5218                                 xoffset = offset;
5219                                 resolveStorageExp(st->st_LoopStmt.es_BCond,
5220                                                   &xoffset);
5221                                 if (noffset < xoffset)
5222                                         noffset = xoffset;
5223                         }
5224                         if (st->st_LoopStmt.es_ACond) {
5225                                 xoffset = offset;
5226                                 resolveStorageExp(st->st_LoopStmt.es_ACond,
5227                                                   &xoffset);
5228                                 if (noffset < xoffset)
5229                                         noffset = xoffset;
5230                         }
5231                         if (st->st_LoopStmt.es_AExp) {
5232                                 xoffset = offset;
5233                                 resolveStorageExp(st->st_LoopStmt.es_AExp,
5234                                                   &xoffset);
5235                                 if (noffset < xoffset)
5236                                         noffset = xoffset;
5237                         }
5238                 }
5239                 break;
5240         case ST_BreakCont:
5241                 break;
5242         case ST_Bad:
5243                 break;
5244         case ST_IfElse:
5245                 resolveStorageExp(st->st_IfStmt.es_Exp, &noffset);
5246                 break;
5247         case ST_Return:
5248                 if (st->st_RetStmt.es_Exp)
5249                         resolveStorageExp(st->st_RetStmt.es_Exp, &noffset);
5250                 break;
5251         case ST_Result:
5252                 if (st->st_ResStmt.es_Exp)
5253                         resolveStorageExp(st->st_ResStmt.es_Exp, &noffset);
5254                 break;
5255         case ST_Switch:
5256                 /*
5257                  * The switch expression's temporary data must be saved while
5258                  * we are executing the sub-statements (the cases).
5259                  */
5260                 resolveStorageExp(st->st_SwStmt.es_Exp, &noffset);
5261                 offset = noffset;
5262                 goffset = ngoffset;
5263                 break;
5264         case ST_Case:
5265                 if (st->st_CaseStmt.es_Exp)
5266                         resolveStorageExp(st->st_CaseStmt.es_Exp, &noffset);
5267                 break;
5268         case ST_Exp:
5269                 resolveStorageExp(st->st_ExpStmt.es_Exp, &noffset);
5270                 break;
5271         case ST_ThreadSched:
5272                 break;
5273         default:
5274                 dassert_stmt(st, 0);
5275         }
5276
5277         /*
5278          * Calculate storage requirements for substatements.  offset
5279          * acts as our base.  We union the storage for the substatements
5280          * together.  Note that often scan->sg_MyGroup == sg.
5281          */
5282         RUNE_FOREACH(scan, &st->st_List, st_Node) {
5283                 dassert(scan->st_Op != ST_Proc);
5284                 if (scan->st_Op == ST_Class) {
5285                         ResolveStorage(scan, flags);
5286 #if 1
5287                 } else if (scan->st_Op == ST_Decl &&
5288                            scan->st_DeclStmt.es_Decl->d_MyGroup !=
5289                            st->st_MyGroup) {
5290                         /*
5291                          * See prior comments, skip declarations that
5292                          * were moved to another context.
5293                          *
5294                          * (does not belong in context so can use
5295                          *  junk offsets).
5296                          */
5297                         runesize_t junk1 = 0;
5298                         runesize_t junk2 = 0;
5299                         /*
5300                         printf("SKIPC %s\n",
5301                                 scan->st_DeclStmt.es_Decl->d_Id);
5302                         */
5303                         resolveStorageDeclExp(scan->st_DeclStmt.es_Decl,
5304                                               &junk1, &junk2);
5305                 } else if (scan->st_Op == ST_Decl &&
5306                            (scan->st_DeclStmt.es_Decl->d_Flags & DF_RESOLVED)) {
5307                         /*
5308                          * See prior comments, skip declarations that
5309                          * were moved to another context
5310                          *
5311                          * (already resolved so can use junk offsets)
5312                          */
5313                         runesize_t junk1 = 0;
5314                         runesize_t junk2 = 0;
5315                         /*
5316                         printf("SKIPD %s\n",
5317                                 scan->st_DeclStmt.es_Decl->d_Id);
5318                         */
5319                         runesize_t save_offset;
5320                         runesize_t save_goffset;
5321                         save_offset = scan->st_MyGroup->sg_TmpBytes;
5322                         save_goffset = scan->st_MyGroup->sg_GlobalTmpBytes;
5323                         scan->st_MyGroup->sg_TmpBytes = offset;
5324                         scan->st_MyGroup->sg_GlobalTmpBytes = goffset;
5325                         resolveStorageDeclExp(scan->st_DeclStmt.es_Decl,
5326                                               &junk1, &junk2);
5327                         if (scan->st_MyGroup->sg_TmpBytes < save_offset)
5328                                 scan->st_MyGroup->sg_TmpBytes = save_offset;
5329                         if (scan->st_MyGroup->sg_GlobalTmpBytes < save_goffset) {
5330                                 scan->st_MyGroup->sg_GlobalTmpBytes = save_goffset;
5331                         }
5332                         if (noffset < scan->st_MyGroup->sg_TmpBytes)
5333                                 noffset = scan->st_MyGroup->sg_TmpBytes;
5334                         if (ngoffset < scan->st_MyGroup->sg_GlobalTmpBytes)
5335                                 ngoffset = scan->st_MyGroup->sg_GlobalTmpBytes;
5336 #endif
5337                 } else if (scan->st_Op == ST_Proc) {
5338                         /* Do not resolve template procedures! */
5339                         fprintf(stderr, "STORAGE %s\n", scan->st_ProcStmt.es_Decl->d_Id);
5340                         if (scan->st_ProcStmt.es_Decl->d_ProcDecl.ed_OrigBody == scan) {
5341                         } else {
5342                         }
5343                 } else if (scan->st_Flags & STF_SEMTOP) {
5344                         assert(scan->st_MyGroup != sg);
5345                         ResolveStorage(scan, flags);
5346                 } else {
5347                         /*
5348                          * This is a bit of a mess.  The baseline
5349                          * sg_TmpBytes needs to be set so calculated
5350                          * temporary offsets are relative to it, and
5351                          * then restored.  Otherwise we might blow
5352                          * away the SGF_TMPRESOLVED SemGroup
5353                          *
5354                          * XXX
5355                          */
5356                         runesize_t save_offset;
5357                         runesize_t save_goffset;
5358                         save_offset = scan->st_MyGroup->sg_TmpBytes;
5359                         save_goffset = scan->st_MyGroup->sg_GlobalTmpBytes;
5360                         scan->st_MyGroup->sg_TmpBytes = offset;
5361                         scan->st_MyGroup->sg_GlobalTmpBytes = goffset;
5362                         ResolveStorage(scan, flags);
5363
5364                         if (scan->st_MyGroup->sg_TmpBytes < save_offset)
5365                                 scan->st_MyGroup->sg_TmpBytes = save_offset;
5366                         if (scan->st_MyGroup->sg_GlobalTmpBytes < save_goffset) {
5367                                 scan->st_MyGroup->sg_GlobalTmpBytes = save_goffset;
5368                         }
5369                         if (noffset < scan->st_MyGroup->sg_TmpBytes)
5370                                 noffset = scan->st_MyGroup->sg_TmpBytes;
5371                         if (ngoffset < scan->st_MyGroup->sg_GlobalTmpBytes)
5372                                 ngoffset = scan->st_MyGroup->sg_GlobalTmpBytes;
5373                 }
5374         }
5375
5376         /*
5377          * If this is a new semantic level call resolveStorageSemGroup() to
5378          * do the final cleanup of SemGroup issues.  This will redundantly
5379          * calculate temporary space requirements.  Also, due to type/class
5380          * references the temporary space for a class may have already been
5381          * resolved.  Since a class can only contain declarations it had
5382          * better match what we calculate here.
5383          *
5384          * Note that for non-Class executable SemGroup's TmpBytes is
5385          * incorporated in a downward fashion while sg_Bytes is incorporated
5386          * in an upward fashion.  It can become quite confusing.  Don't ask
5387          * me why I did it that way.
5388          */
5389         if (st->st_Flags & STF_SEMANTIC) {
5390                 if ((sg->sg_Flags & SGF_TMPRESOLVED) == 0) {
5391                         resolveStorageSemGroup(sg, noffset, ngoffset);
5392                 } else {
5393                         dassert(sg->sg_TmpBytes == noffset && 
5394                                 sg->sg_GlobalTmpBytes == ngoffset);
5395                 }
5396         } else if (sg) {
5397                 sg->sg_TmpBytes = noffset;
5398                 sg->sg_GlobalTmpBytes = ngoffset;
5399         } /* else this is the Root st_Import */
5400
5401         if ((st->st_Flags & (STF_SEMANTIC|STF_SEMTOP)) == STF_SEMANTIC) {
5402                 sg->sg_Parent->sg_Bytes = sg->sg_Bytes;
5403         }
5404 }
5405
5406 /*
5407  * resolveStorageDeclExp() - resolve the storage reservation required to
5408  *                           process an expression.
5409  *
5410  *      This is an expression tree traversal storage resolution procedure.
5411  *      We have to traverse through declarations to get to default assignments
5412  *      and such.
5413  *
5414  *      If a declaration has no assigned default the underlying type may
5415  *      itself have an assigned default which must be dealt with.
5416  */
5417 static void
5418 resolveStorageDeclExpAlign(Declaration *d, runesize_t *expalignp)
5419 {
5420         switch(d->d_Op) {
5421         case DOP_CLASS:
5422                 /* recursion already dealt with */
5423                 break;
5424         case DOP_ARGS_STORAGE:
5425         case DOP_STACK_STORAGE:
5426         case DOP_GROUP_STORAGE:
5427                 {
5428                         Type *type = d->d_StorDecl.ed_Type;
5429
5430                         resolveStorageTypeExpAlign(type, expalignp);
5431                         if (d->d_StorDecl.ed_AssExp) {
5432                                 resolveStorageExpAlign(d->d_StorDecl.ed_AssExp,
5433                                                        expalignp);
5434                         }
5435                 }
5436                 break;
5437         case DOP_GLOBAL_STORAGE:
5438                 {
5439                         Type *type = d->d_StorDecl.ed_Type;
5440
5441                         resolveStorageTypeExpAlign(type, expalignp);
5442                         if (d->d_StorDecl.ed_AssExp) {
5443                                 resolveStorageExpAlign(d->d_StorDecl.ed_AssExp,
5444                                                        expalignp);
5445                         }
5446                 }
5447                 break;
5448         case DOP_ALIAS:
5449                 /*
5450                  * Never try to resolve storage considerations for an
5451                  * alias's assignment in the declaration itself.  The
5452                  * run-time context depends on who and how many other
5453                  * parts of the program reference the alias and the expression
5454                  * tree will be duplicated for each.
5455                  */
5456 #if 0
5457                 resolveStorageExpExp(d->d_AliasDecl.ed_AssExp, expalignp);
5458 #endif
5459                 break;
5460         case DOP_TYPEDEF:
5461                 /* XXX what about ty_AssExp ? should be in global space */
5462                 break;
5463         case DOP_IMPORT:
5464                 /* recursion already dealt with */
5465                 break;
5466         case DOP_PROC:
5467                 /*
5468                  * Resolution of procedure declarations might have been
5469                  * deferred (see TOK_ID in resolveExp()).
5470                  */
5471                 resolveDecl(d, 0);
5472                 {
5473                         Stmt *st;
5474
5475                         if ((st = d->d_ProcDecl.ed_ProcBody) != NULL) {
5476                                 ResolveAlignment(st, 0);
5477                         }
5478                 }
5479                 break;
5480         default:
5481                 dassert_decl(d, 0);
5482         }
5483 }
5484
5485 static void
5486 resolveStorageDeclExp(Declaration *d, runesize_t *offset, runesize_t *goffset)
5487 {
5488         switch(d->d_Op) {
5489         case DOP_CLASS:
5490                 /* recursion already dealt with */
5491                 break;
5492         case DOP_ARGS_STORAGE:
5493         case DOP_STACK_STORAGE:
5494         case DOP_GROUP_STORAGE:
5495                 {
5496                         Type *type = d->d_StorDecl.ed_Type;
5497                         runesize_t save_offset = *offset;
5498
5499                         resolveStorageType(type, &save_offset, 0);
5500                         if (d->d_StorDecl.ed_AssExp) {
5501                                 resolveStorageExp(d->d_StorDecl.ed_AssExp,
5502                                                   offset);
5503                         }
5504                         if (*offset < save_offset)
5505                                 *offset = save_offset;
5506                 }
5507                 break;
5508         case DOP_GLOBAL_STORAGE:
5509                 {
5510                         Type *type = d->d_StorDecl.ed_Type;
5511                         runesize_t save_offset = *goffset;
5512
5513                         resolveStorageType(type, &save_offset, 1);
5514                         if (d->d_StorDecl.ed_AssExp) {
5515                                 resolveStorageExp(d->d_StorDecl.ed_AssExp,
5516                                                   goffset);
5517                         }
5518                         if (*goffset < save_offset)
5519                                 *goffset = save_offset;
5520                 }
5521                 break;
5522         case DOP_ALIAS:
5523                 /*
5524                  * Never try to resolve storage considerations for an
5525                  * alias's assignment in the declaration itself.  The
5526                  * run-time context depends on who and how many other
5527                  * parts of the program reference the alias and the expression
5528                  * tree will be duplicated for each.
5529                  */
5530 #if 0
5531                 if (d->d_ScopeFlags & SCOPE_GLOBAL)
5532                         resolveStorageExp(d->d_AliasDecl.ed_AssExp, NULL, NULL);
5533                 else
5534                         resolveStorageExp(d->d_AliasDecl.ed_AssExp, NULL, NULL);
5535 #endif
5536                 break;
5537         case DOP_TYPEDEF:
5538                 /* XXX what about ty_AssExp ? should be in global space */
5539                 break;
5540         case DOP_IMPORT:
5541                 /* recursion already dealt with */
5542                 break;
5543         case DOP_PROC:
5544                 {
5545                         Stmt *st;
5546
5547                         if ((st = d->d_ProcDecl.ed_ProcBody) != NULL) {
5548                                 ResolveStorage(st, 0);
5549                         }
5550                 }
5551                 break;
5552         default:
5553                 dassert_decl(d, 0);
5554         }
5555 }
5556
5557 /*
5558  * resolveStorageExp() - resolve the temporary storage required to
5559  *                       support the expression, if any.
5560  *
5561  * We do not need to assign storage for expressions which return
5562  * lvalues, because they will simply return a pointer into
5563  * non-temporary storage.
5564  */
5565 static runesize_t
5566 resolveStorageExpOnly(Exp *exp, runesize_t *offset)
5567 {
5568         Type *type;
5569
5570         /*
5571          * Stop if the expression resolves to a type rather then a value,
5572          * e.g. when you do something like switch (typeof(int)) { ... }
5573          * Types are handled as thin pointers.
5574          */
5575         exp->ex_Flags |= EXF_TMPRESOLVED;
5576         if (exp->ex_Flags & EXF_RET_TYPE) {
5577                 *offset = (*offset + POINTER_ALIGN - 1) & ~(POINTER_ALIGN - 1);
5578                 exp->ex_TmpOffset = *offset;
5579                 *offset += sizeof(void *);
5580                 return(*offset);
5581
5582         }
5583
5584         /*
5585          * Assign temporary offset.  This offset does not overlap temporary
5586          * space reserved for sub-expressions.
5587          *
5588          * We must have an assigned type.  Expression sequences like:
5589          * 'module.blah' are collapsed into 'blah' long before we get
5590          * here, or they should be.  We should not encounter any
5591          * TOK_TCMV_ID expression tokens.  Structural id's (the right hand
5592          * side of X.Y) are resolved by their parent expression node and
5593          * no typing or temporary space is required.
5594          *
5595          * Expressions that return lvalues do not need temporary space.
5596          */
5597         type = exp->ex_Type;
5598         if (type == NULL) {
5599                 switch(exp->ex_Token) {
5600                 case TOK_STRUCT_ID:
5601                 case TOK_SEMGRP_ID:
5602                         break;
5603                 default:
5604                         printf("EXP %p %04x %p\n",
5605                                exp, exp->ex_Token, exp->ex_Decl);
5606                         dassert_exp(exp, 0);
5607                         break;
5608                 }
5609                 exp->ex_TmpOffset = -3;
5610         } else if (type->ty_SQFlags & SF_LVALUE) {
5611                 /*
5612                  * Expressive elements which return lvalues do not get
5613                  * temporary space.  Note that this also prevents lvalues
5614                  * such as large arrays (int ary[999999999]) from reserving
5615                  * unnecessary stack space.
5616                  *
5617                  * NOTE: SF_LVALUE is unrelated to SCOPE_LVALUE.  SCOPE_LVALUE
5618                  *       applies to SemGroup storage (LValueStor).  SF_LVALUE
5619                  *       merely flags the type for an expression as expecting
5620                  *       or not expecting an lvalue.
5621                  */
5622 #if 0
5623                 /*
5624                  * XXX removeme, LValueStor only applies to semgroups
5625                  */
5626                 runesize_t lvmask = sizeof(LValueStor) - 1;
5627                 *offset = (*offset + lvmask) & ~lvmask;
5628                 exp->ex_TmpOffset = *offset;
5629                 *offset = *offset + (lvmask + 1);
5630 #endif
5631                 exp->ex_TmpOffset = -2;
5632         } else {
5633                 /*
5634                  * Reserve temporary space for potential intermediate
5635                  * results.
5636                  *
5637                  * Compound expressions may need extra space to default-init
5638                  * the compound value, it is expected to be available to the
5639                  * generator right after the nominal type in the TmpOffset.
5640                  * XXX also make available to the interpreter?
5641                  *
5642                  * Procedure calls also may need extra space to default-init
5643                  * the return value.  XXX also make available to the
5644                  * interpreter?
5645                  */
5646                 *offset = (*offset + type->ty_AlignMask) & ~type->ty_AlignMask;
5647                 exp->ex_TmpOffset = *offset;
5648                 *offset = *offset + type->ty_Bytes;
5649                 if (exp->ex_Token == TOK_COMPOUND) {
5650                         /*
5651                          * NOTE: type might not yet be changed to compound,
5652                          *       but single-element compound will use the
5653                          *       same temporary space.
5654                          */
5655                         *offset += type->ty_TmpBytes;
5656                 } else if (exp->ex_Token == TOK_CALL) {
5657                         *offset += type->ty_TmpBytes;
5658                 }
5659         }
5660         dassert(exp->ex_TmpOffset != -1);
5661         return (*offset);
5662 }
5663
5664 static void
5665 resolveStorageExpSub(Exp *exp, runesize_t *offset)
5666 {
5667 #if 0
5668         /*
5669          * Early term.  XXX don't do this.  For the moment we have an issue
5670          * with how typeof() processes temporary expression storage.  This
5671          * needs to be comprehensively fixed but it can be an issue if the
5672          * content is a dynamic type (via a ref or a var-args element)
5673          * so it is not trivial.
5674          */
5675         if (exp->ex_Flags & EXF_RET_TYPE)
5676                 return;
5677 #endif
5678         if (exp->ex_Type)
5679                 resolveStorageType(exp->ex_Type, offset, 0);
5680
5681         /*
5682          * Calculate the overlapping temporary space for sub-trees.
5683          */
5684         if (exp->ex_Flags & EXF_BINARY) {
5685                 /*
5686                  * Ensure lhs's NON-RECURSIVE temporary storage on-return
5687                  * does not intefere with rhs's, or vise-versa.
5688                  *
5689                  * To do this offset the rhs storage by the non-recursive
5690                  * lhs storage.
5691                  */
5692                 runesize_t xoffset;
5693                 runesize_t roffset;
5694
5695                 roffset = *offset;
5696                 xoffset = roffset;
5697                 resolveStorageExp(exp->ex_Lhs, &xoffset);
5698                 if (*offset < xoffset)
5699                         *offset = xoffset;
5700                 if (exp->ex_Lhs->ex_TmpOffset >= 0) {
5701                         xoffset = exp->ex_Lhs->ex_TmpOffset +
5702                                   exp->ex_Lhs->ex_Type->ty_Bytes;
5703                 } else {
5704                         xoffset = roffset;
5705                 }
5706                 resolveStorageExp(exp->ex_Rhs, &xoffset);
5707                 if (*offset < xoffset)
5708                         *offset = xoffset;
5709         } else if (exp->ex_Flags & EXF_UNARY) {
5710                 resolveStorageExp(exp->ex_Lhs, offset);
5711                 dassert_exp(exp, exp->ex_Lhs->ex_Next == NULL);
5712         } else if (exp->ex_Flags & EXF_COMPOUND) {
5713                 /*
5714                  * each element will be copied into the compound storage
5715                  * in turn, so we can union the temporary storage required
5716                  * for each element.
5717                  */
5718                 Exp *scan;
5719                 runesize_t noffset;
5720
5721                 noffset = *offset;
5722                 for (scan = exp->ex_Lhs; scan; scan = scan->ex_Next) {
5723                         runesize_t xoffset = *offset;
5724
5725                         dassert_exp(scan, scan->ex_Type != NULL);
5726
5727                         resolveStorageExp(scan, &xoffset);
5728                         if (noffset < xoffset)
5729                                 noffset = xoffset;
5730                 }
5731                 *offset = noffset;
5732         }
5733
5734 #if 0
5735         if (exp->ex_Token == TOK_CALL && exp->ex_Lhs->ex_Decl) {
5736                 Declaration *d = exp->ex_Lhs->ex_Decl;
5737                 fprintf(stderr, "FIXUP CALL %s type %p\n", d->d_Id, d->d_ProcDecl.ed_Type);
5738                 dassert(d->d_Op == DOP_PROC);
5739                 resolveStorageType(d->d_ProcDecl.ed_Type, offset, 0);
5740         }
5741 #endif
5742
5743 #if 0
5744         /* XXX what about alias assign-expressions */
5745         else if (exp->ex_Flags & EXF_ALIAS) {
5746 #if 0
5747                 dassert_decl(exp->ex_Decl,
5748                              (exp->ex_Decl->d_ScopeFlags & SCOPE_GLOBAL) == 0);
5749 #endif
5750                 resolveStorageExp(exp->ex_Decl->d_AliasDecl.ed_AssExp, offset);
5751         }
5752 #endif
5753 }
5754
5755 /*
5756  * [re]resolve temporary storage requirements.
5757  *
5758  * WARNING! This may be called more than once if an expression requires
5759  *          resolve-time interpretation to generate a constant.  In this
5760  *          ex_TmpOffset for the sub-chain may be regenerated from 0,
5761  *          and then just the top-level (post-constant-resolved)
5762  *          ex_TmpOffset will be restored by the caller.
5763  */
5764 static void
5765 resolveStorageExp(Exp *exp, runesize_t *offset)
5766 {
5767         runesize_t noffset;
5768         runesize_t xoffset;
5769
5770         xoffset = *offset;
5771         noffset = resolveStorageExpOnly(exp, &xoffset);
5772         xoffset = noffset;
5773         resolveStorageExpSub(exp, &xoffset);
5774         if (*offset < xoffset)
5775                 *offset = xoffset;
5776 }
5777
5778 static void
5779 resolveStorageExpAlign(Exp *exp, runesize_t *expalignp)
5780 {
5781         Type *type;
5782
5783         if (exp->ex_Flags & EXF_RET_TYPE) {
5784                 if (*expalignp < POINTER_ALIGN)
5785                         *expalignp = POINTER_ALIGN;
5786         }
5787 #if 0
5788         if (exp->ex_Decl) {
5789                 resolveDecl(exp->ex_Decl, 0);
5790         }
5791 #endif
5792
5793         type = exp->ex_Type;
5794         if (type == NULL) {
5795                 /*
5796                  * Do nothing
5797                  */
5798         } else {
5799                 if (type->ty_SQFlags & SF_LVALUE) {
5800                         if (*expalignp < POINTER_ALIGN)
5801                                 *expalignp = POINTER_ALIGN;
5802                 } else {
5803                         if (*expalignp < type->ty_AlignMask)
5804                                 *expalignp = type->ty_AlignMask;
5805                 }
5806                 resolveStorageTypeExpAlign(type, expalignp);
5807         }
5808
5809         if (exp->ex_Flags & EXF_BINARY) {
5810                 resolveStorageExpAlign(exp->ex_Lhs, expalignp);
5811                 resolveStorageExpAlign(exp->ex_Rhs, expalignp);
5812         } else if (exp->ex_Flags & EXF_UNARY) {
5813                 resolveStorageExpAlign(exp->ex_Lhs, expalignp);
5814         } else if (exp->ex_Flags & EXF_COMPOUND) {
5815                 Exp *scan;
5816
5817                 for (scan = exp->ex_Lhs; scan; scan = scan->ex_Next) {
5818                         resolveStorageExpAlign(scan, expalignp);
5819                 }
5820 #if 0
5821         } else if (exp->ex_Flags & EXF_ALIAS) {
5822                 resolveStorageExpAlign(exp->ex_Decl->d_AliasDecl.ed_AssExp,
5823                                        expalignp);
5824 #endif
5825         }
5826
5827 #if 0
5828         if (exp->ex_Token == TOK_CALL && exp->ex_Lhs->ex_Decl) {
5829                 Declaration *d = exp->ex_Lhs->ex_Decl;
5830                 dassert(d->d_Op == DOP_PROC);
5831                 resolveStorageTypeExpAlign(d->d_ProcDecl.ed_Type, expalignp);
5832                 if (d->d_ProcDecl.ed_ProcBody)
5833                         ResolveAlignment(d->d_ProcDecl.ed_ProcBody, 0);
5834         }
5835 #endif
5836 }
5837
5838 /*
5839  * resolveStorageType() - temporary space required to initialize type defaults
5840  *
5841  * Figure out the temporary space required to initialize a type's
5842  * defaults.  Note that the space will be figured independantly
5843  * for any SemGroup's.
5844  */
5845 static
5846 void
5847 resolveStorageTypeExpAlign(Type *type, runesize_t *expalignp)
5848 {
5849         SemGroup *sg = NULL;
5850         Type *subtype1 = NULL;
5851         Type *subtype2 = NULL;
5852
5853         if (type->ty_Flags & TF_ALIGNRESOLVED) {
5854                 if (*expalignp < type->ty_TmpAlignMask)
5855                         *expalignp = type->ty_TmpAlignMask;
5856                 return;
5857         }
5858         type->ty_Flags |= TF_ALIGNRESOLVED;
5859
5860         switch(type->ty_Op) {
5861         case TY_CLASS:
5862                 sg = type->ty_ClassType.et_SemGroup;
5863                 break;
5864         case TY_ARYOF:
5865                 subtype1 = type->ty_AryType.et_Type;
5866                 break;
5867         case TY_COMPOUND:
5868                 sg = type->ty_CompType.et_SemGroup;
5869                 break;
5870         case TY_PROC:
5871                 subtype1 = type->ty_ProcType.et_ArgsType;
5872                 subtype2 = type->ty_ProcType.et_RetType;
5873                 break;
5874         case TY_IMPORT:
5875                 sg = type->ty_ImportType.et_SemGroup;
5876                 break;
5877         case TY_ARGS:
5878                 sg = type->ty_ArgsType.et_SemGroup;
5879                 break;
5880         case TY_VAR:
5881                 sg = type->ty_VarType.et_SemGroup;
5882                 break;
5883         case TY_CPTRTO:
5884                 /* has nothing to do with initializing the pointer */
5885                 /* subtype1 = type->ty_CPtrType.et_Type; */
5886                 break;
5887         case TY_PTRTO:
5888                 /* has nothing to do with initializing the pointer */
5889                 /* subtype1 = type->ty_PtrType.et_Type; */
5890                 break;
5891         case TY_REFTO:
5892                 /* has nothing to do with initializing the pointer */
5893                 /* subtype1 = type->ty_RefType.et_Type; */
5894                 break;
5895         case TY_STORAGE:
5896         case TY_DYNAMIC:
5897                 /* 
5898                  * nothing to be done here.
5899                  */
5900                 break;
5901         case TY_UNRESOLVED: /* should be no unresolved types at this stage */
5902         default:
5903                 dassert_type(type, 0);
5904         }
5905
5906         if (subtype1) {
5907                 resolveStorageTypeExpAlign(subtype1, &subtype1->ty_TmpAlignMask);
5908                 if (subtype1->ty_AssExp) {
5909                         resolveStorageExpAlign(subtype1->ty_AssExp,
5910                                                &subtype1->ty_TmpAlignMask);
5911                 }
5912                 if (type->ty_TmpAlignMask < subtype1->ty_TmpAlignMask)
5913                         type->ty_TmpAlignMask = subtype1->ty_TmpAlignMask;
5914         }
5915         if (subtype2) {
5916                 resolveStorageTypeExpAlign(subtype2, &subtype2->ty_TmpAlignMask);
5917                 if (subtype2->ty_AssExp) {
5918                         resolveStorageExpAlign(subtype2->ty_AssExp,
5919                                                &subtype2->ty_TmpAlignMask);
5920                 }
5921                 if (type->ty_TmpAlignMask < subtype2->ty_TmpAlignMask)
5922                         type->ty_TmpAlignMask = subtype2->ty_TmpAlignMask;
5923         }
5924         if (type->ty_AssExp) {
5925                 resolveStorageExpAlign(type->ty_AssExp, &type->ty_TmpAlignMask);
5926         }
5927         if (sg) {
5928                 if (resolveSemGroup1(sg, 0) && resolveSemGroup2(sg, 0))
5929                         resolveSemGroup3(sg, 0);
5930                 resolveStorageSemGroupAlign(sg);
5931                 if (type->ty_TmpAlignMask < sg->sg_TmpAlignMask)
5932                         type->ty_TmpAlignMask = sg->sg_TmpAlignMask;
5933         }
5934         if (*expalignp < type->ty_TmpAlignMask)
5935                 *expalignp = type->ty_TmpAlignMask;
5936 }
5937
5938 static
5939 void
5940 resolveStorageType(Type *type, runesize_t *offset, int isglob)
5941 {
5942         SemGroup *sg = NULL;
5943         Type *subtype1 = NULL;
5944         Type *subtype2 = NULL;
5945         runesize_t save_offset1;
5946         runesize_t save_offset2;
5947         runesize_t save_offset3;
5948         runesize_t save_offsetx;
5949
5950         dassert(type->ty_Flags & TF_ALIGNRESOLVED);
5951         if (type->ty_Flags & TF_TMPRESOLVED)
5952                 return;
5953         type->ty_Flags |= TF_TMPRESOLVED;
5954
5955         switch(type->ty_Op) {
5956         case TY_CLASS:
5957                 sg = type->ty_ClassType.et_SemGroup;
5958                 break;
5959         case TY_ARYOF:
5960                 subtype1 = type->ty_AryType.et_Type;
5961                 break;
5962         case TY_COMPOUND:
5963                 sg = type->ty_CompType.et_SemGroup;
5964                 break;
5965         case TY_PROC:
5966                 subtype1 = type->ty_ProcType.et_ArgsType;
5967                 subtype2 = type->ty_ProcType.et_RetType;
5968                 break;
5969         case TY_IMPORT:
5970                 sg = type->ty_ImportType.et_SemGroup;
5971                 break;
5972         case TY_ARGS:
5973                 sg = type->ty_ArgsType.et_SemGroup;
5974                 break;
5975         case TY_VAR:
5976                 sg = type->ty_VarType.et_SemGroup;
5977                 break;
5978         case TY_CPTRTO:
5979                 /* has nothing to do with initializing the pointer */
5980                 /* subtype1 = type->ty_CPtrType.et_Type; */
5981                 break;
5982         case TY_PTRTO:
5983                 /* has nothing to do with initializing the pointer */
5984                 /* subtype1 = type->ty_PtrType.et_Type; */
5985                 break;
5986         case TY_REFTO:
5987                 /* has nothing to do with initializing the pointer */
5988                 /* subtype1 = type->ty_RefType.et_Type; */
5989                 break;
5990         case TY_STORAGE:
5991         case TY_DYNAMIC:
5992                 /* 
5993                  * nothing to be done here.
5994                  */
5995                 break;
5996         case TY_UNRESOLVED: /* should be no unresolved types at this stage */
5997         default:
5998                 dassert_type(type, 0);
5999         }
6000
6001         save_offset1 = *offset;
6002         save_offset2 = *offset;
6003         save_offset3 = *offset;
6004         save_offsetx = *offset;
6005         if (subtype1) {
6006                 /*resolveType(subtype1, NULL, 0);*/
6007                 resolveStorageType(subtype1, &subtype1->ty_TmpBytes, 0);
6008                 if (subtype1->ty_AssExp) {
6009                         resolveStorageExp(subtype1->ty_AssExp,
6010                                           &subtype1->ty_TmpBytes);
6011                 }
6012                 save_offset1 += subtype1->ty_TmpBytes;
6013                 if (type->ty_TmpAlignMask < subtype1->ty_TmpAlignMask)
6014                         type->ty_TmpAlignMask = subtype1->ty_TmpAlignMask;
6015         }
6016         if (subtype2) {
6017                 /*resolveType(subtype2, NULL, 0);*/
6018                 resolveStorageType(subtype2, &subtype2->ty_TmpBytes, 0);
6019                 if (subtype2->ty_AssExp) {
6020                         resolveStorageExp(subtype2->ty_AssExp,
6021                                           &subtype2->ty_TmpBytes);
6022                 }
6023                 save_offset2 += subtype2->ty_TmpBytes;
6024                 if (type->ty_TmpAlignMask < subtype2->ty_TmpAlignMask)
6025                         type->ty_TmpAlignMask = subtype2->ty_TmpAlignMask;
6026         }
6027         if (type->ty_AssExp) {
6028                 resolveStorageExp(type->ty_AssExp, &type->ty_TmpBytes);
6029         }
6030         if (sg) {
6031                 if (resolveSemGroup1(sg, 0) && resolveSemGroup2(sg, 0))
6032                         resolveSemGroup3(sg, 0);
6033                 resolveStorageSemGroup(sg, 0, 0);
6034                 if (isglob) {
6035                         save_offset3 += sg->sg_GlobalTmpBytes;
6036                 } else {
6037                         save_offset3 += sg->sg_TmpBytes;
6038                 }
6039
6040                 /*
6041                  * Re-resolve the type flags.  XXX mostly fixed once I handled
6042                  * CBase/DBase/GBase in resolveSemGroup1().
6043                  */
6044                 if (sg->sg_Flags & SGF_HASASS)
6045                         type->ty_Flags |= TF_HASASS;
6046                 if (sg->sg_SRBase)
6047                         type->ty_Flags |= TF_HASLVPTR;
6048                 if (sg->sg_Flags & SGF_VARARGS)
6049                         type->ty_Flags |= TF_HASLVPTR;  /* XXX TF_VARARGS */
6050                 if (sg->sg_CBase)
6051                         type->ty_Flags |= TF_HASCONSTRUCT;
6052                 if (sg->sg_DBase)
6053                         type->ty_Flags |= TF_HASDESTRUCT;
6054
6055         }
6056         if (*offset < save_offset1)
6057                 *offset = save_offset1;
6058         if (*offset < save_offset2)
6059                 *offset = save_offset2;
6060         if (*offset < save_offset3)
6061                 *offset = save_offset3;
6062         type->ty_TmpBytes = *offset - save_offsetx;
6063 }
6064
6065 /*
6066  * This is used to resolve temporary storage requirements for
6067  * SemGroup's related to classes and compound types.  Temporary storage
6068  * requirements are calculated on a SemGroup-by-SemGroup basis and not
6069  * aggregated into any parent.
6070  *
6071  * In the final pass we also reverse the constructor and destructor lists
6072  * (sg_CBase and sg_DBase), and the pointer/lvalue list (SRBase).  These
6073  * lists were originally constructed by prepending and are thus in the
6074  * wrong order.
6075  */
6076 static
6077 void
6078 resolveStorageSemGroupAlign(SemGroup *sg)
6079 {
6080         Declaration *d;
6081
6082         if (sg->sg_Flags & SGF_ALIGNRESOLVED)
6083                 return;
6084         sg->sg_Flags |= SGF_ALIGNRESOLVED;
6085
6086         /*
6087          * SGF_RESOLVED might not be set.  This can only happen because we
6088          * allow individual declarations in global SemGroups to be resolved
6089          * without having to resolve the whole group.  This allows unused
6090          * declarations to be omitted by the code generator.
6091          */
6092         if ((sg->sg_Flags & SGF_RESOLVED) == 0)
6093                 sg->sg_Flags |= SGF_RESOLVED;
6094
6095         RUNE_FOREACH(d, &sg->sg_DeclList, d_Node) {
6096                 resolveStorageDeclExpAlign(d, &sg->sg_TmpAlignMask);
6097                 if (d->d_ScopeFlags & SCOPE_GLOBAL) {
6098                         if (sg->sg_GlobalAlignMask < d->d_AlignMask)
6099                                 sg->sg_GlobalAlignMask = d->d_AlignMask;
6100                 } else {
6101                         if (sg->sg_AlignMask < d->d_AlignMask)
6102                                 sg->sg_AlignMask = d->d_AlignMask;
6103                 }
6104         }
6105 }
6106
6107 static
6108 void
6109 resolveStorageSemGroup(SemGroup *sg, runesize_t noffset, runesize_t ngoffset)
6110 {
6111         Declaration *d;
6112         Declaration *d2;
6113
6114 #if 0
6115         if ((sg->sg_Flags & SGF_RESOLVED) == 0) {
6116                 if (resolveSemGroup1(sg, 0) && resolveSemGroup2(sg, 0))
6117                         resolveSemGroup3(sg, 0);
6118         }
6119 #endif
6120         dassert(sg->sg_Flags & SGF_ALIGNRESOLVED);
6121         if (sg->sg_Flags & SGF_TMPRESOLVED)
6122                 return;
6123         sg->sg_Flags |= SGF_TMPRESOLVED;
6124
6125         /*
6126          * Final pass
6127          */
6128         RUNE_FOREACH(d, &sg->sg_DeclList, d_Node) {
6129                 runesize_t offset = 0;
6130                 runesize_t goffset = 0;
6131
6132                 resolveStorageDeclExp(d, &offset, &goffset);
6133                 if (noffset < offset)
6134                         noffset = offset;
6135                 if (ngoffset < goffset)
6136                         ngoffset = goffset;
6137         }
6138
6139         /*
6140          * Reverse order
6141          */
6142         if ((d2 = sg->sg_CBase) != NULL) {
6143                 sg->sg_CBase = NULL;
6144                 while ((d = d2) != NULL) {
6145                         d2 = d->d_CNext;
6146                         d->d_CNext = sg->sg_CBase;
6147                         sg->sg_CBase = d;
6148                 }
6149         }
6150         if ((d2 = sg->sg_DBase) != NULL) {
6151                 sg->sg_DBase = NULL;
6152                 while ((d = d2) != NULL) {
6153                         d2 = d->d_DNext;
6154                         d->d_DNext = sg->sg_DBase;
6155                         sg->sg_DBase = d;
6156                 }
6157         }
6158         if ((d2 = sg->sg_GBase) != NULL) {
6159                 sg->sg_GBase = NULL;
6160                 while ((d = d2) != NULL) {
6161                         d2 = d->d_GNext;
6162                         d->d_GNext = sg->sg_GBase;
6163                         sg->sg_GBase = d;
6164                 }
6165         }
6166         if ((d2 = sg->sg_SRBase) != NULL) {
6167                 sg->sg_SRBase = NULL;
6168                 while ((d = d2) != NULL) {
6169                         d2 = d->d_SRNext;
6170                         d->d_SRNext = sg->sg_SRBase;
6171                         sg->sg_SRBase = d;
6172                 }
6173         }
6174         sg->sg_TmpBytes = noffset;
6175         sg->sg_GlobalTmpBytes = ngoffset;
6176 }
6177
6178 /*
6179  * Return non-zero if the method procedure wants the 'this' variable
6180  * to be an lvalue-pointer rather than an lvalue-target-object.  In this
6181  * situation we do not want to indirect the pointer.
6182  */
6183 static
6184 int
6185 methodProcThisIsPointer(Type *type)
6186 {
6187         Declaration *d;
6188         SemGroup *sg;
6189         int r;
6190
6191         dassert(type->ty_Op == TY_PROC);
6192         dassert(type->ty_ProcType.et_ArgsType->ty_Op == TY_ARGS);
6193         sg = type->ty_ProcType.et_ArgsType->ty_CompType.et_SemGroup;
6194         d = RUNE_FIRST(&sg->sg_DeclList);
6195         dassert(d->d_Id == String_This);
6196         switch (d->d_StorDecl.ed_Type->ty_Op) {
6197         case TY_REFTO:
6198                 r = 1;
6199                 break;
6200         case TY_PTRTO:
6201                 r = 1;
6202                 break;
6203         case TY_CPTRTO:
6204                 fprintf(stderr,
6205                         "methodProcThisIsPointer(): method call through "
6206                         "C pointer is illegal\n");
6207                 dassert_decl(d, 0);
6208                 r = 1;
6209                 break;
6210         default:
6211                 r = 0;
6212                 break;
6213         }
6214         return r;
6215 }
6216
6217 /*
6218  * Calculate SG dependencies
6219  */
6220 #define SGDEP_HSIZE     1024
6221 #define SGDEP_HMASK     (SGDEP_HSIZE - 1)
6222
6223 SGDepend *SGDepHash[SGDEP_HSIZE];
6224 SemGroup *SGCurrentDep;
6225
6226 static
6227 SGDepend **
6228 resolveSGDependHash(SemGroup *src, SemGroup *dst)
6229 {
6230         intptr_t hv;
6231
6232         hv = ((intptr_t)src >> 7) ^ ((intptr_t)dst >> 5);
6233         hv ^= hv >> 16;
6234         return (&SGDepHash[hv & SGDEP_HMASK]);
6235 }
6236
6237 static
6238 SemGroup *
6239 resolvePushSGDepend(SemGroup *sg)
6240 {
6241         SemGroup *last;
6242         SGDepend *dep;
6243         SGDepend **depp;
6244
6245         depp = resolveSGDependHash(SGCurrentDep, sg);
6246         for (dep = *depp; dep; dep = dep->hnext) {
6247                 if (dep->src == SGCurrentDep && dep->dst == sg)
6248                         break;
6249         }
6250         if (dep == NULL) {
6251                 dep = zalloc(sizeof(SGDepend));
6252                 dep->hnext = *depp;
6253                 dep->src = SGCurrentDep;
6254                 dep->dst = sg;
6255                 *depp = dep;
6256                 if (SGCurrentDep) {
6257                         dep->next = SGCurrentDep->sg_DepFirst;
6258                         SGCurrentDep->sg_DepFirst = dep;
6259                 }
6260         }
6261         last = SGCurrentDep;
6262         SGCurrentDep = sg;
6263
6264         return last;
6265 }
6266
6267 static
6268 void
6269 resolvePopSGDepend(SemGroup *dep)
6270 {
6271         SGCurrentDep = dep;
6272 }