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