1 /**
2  * Compiler implementation of the
3  * $(LINK2 http://www.dlang.org, D programming language).
4  *
5  * Copyright:   Copyright (C) 1985-1998 by Symantec
6  *              Copyright (C) 2000-2020 by The D Language Foundation, All Rights Reserved
7  * Authors:     $(LINK2 http://www.digitalmars.com, Walter Bright)
8  * License:     $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
9  * Source:      $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/backend/cc.d, backend/_cc.d)
10  */
11 
12 module dmd.backend.cc;
13 
14 // Online documentation: https://dlang.org/phobos/dmd_backend_cc.html
15 
16 import dmd.backend.barray;
17 import dmd.backend.cdef;        // host and target compiler definition
18 import dmd.backend.code_x86;
19 import dmd.backend.dlist;
20 import dmd.backend.dt;
21 import dmd.backend.el;
22 import dmd.backend.type;
23 
24 extern (C++):
25 @nogc:
26 nothrow:
27 
28 enum GENOBJ = 1;       // generating .obj file
29 
30 uint mskl(uint i) { return 1 << i; }     // convert int to mask
31 
32 // Warnings
33 enum WM
34 {
35     WM_no_inline    = 1,    //function '%s' is too complicated to inline
36     WM_assignment   = 2,    //possible unintended assignment
37     WM_nestcomment  = 3,    //comments do not nest
38     WM_assignthis   = 4,    //assignment to 'this' is obsolete, use X::operator new/delete
39     WM_notagname    = 5,    //no tag name for struct or enum
40     WM_valuenotused = 6,    //value of expression is not used
41     WM_extra_semi   = 7,    //possible extraneous ';'
42     WM_large_auto   = 8,    //very large automatic
43     WM_obsolete_del = 9,    //use delete[] rather than delete[expr], expr ignored
44     WM_obsolete_inc = 10,   //using operator++() (or --) instead of missing operator++(int)
45     WM_init2tmp     = 11,   //non-const reference initialized to temporary
46     WM_used_b4_set  = 12,   //variable '%s' used before set
47     WM_bad_op       = 13,   //Illegal type/size of operands for the %s instruction
48     WM_386_op       = 14,   //Reference to '%s' caused a 386 instruction to be generated
49     WM_ret_auto     = 15,   //returning address of automatic '%s'
50     WM_ds_ne_dgroup = 16,   //DS is not equal to DGROUP
51     WM_unknown_pragma = 17, //unrecognized pragma
52     WM_implied_ret  = 18,   //implied return at closing '}' does not return value
53     WM_num_args     = 19,   //%d actual arguments expected for %s, had %d
54     WM_before_pch   = 20,   //symbols or macros defined before #include of precompiled header
55     WM_pch_first    = 21,   //precompiled header must be first #include when -H is used
56     WM_pch_config   = 22,
57     WM_divby0       = 23,
58     WM_badnumber    = 24,
59     WM_ccast        = 25,
60     WM_obsolete     = 26,
61 
62     // if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_DRAGONFLYBSD || TARGET_SOLARIS
63     WM_skip_attribute   = 27, // skip GNUC attribute specification
64     WM_warning_message  = 28, // preprocessor warning message
65     WM_bad_vastart      = 29, // args for builtin va_start bad
66     WM_undefined_inline = 30, // static inline not expanded or defined
67 }
68 
69 static if (MEMMODELS == 1)
70 {
71     enum LARGEDATA = 0;     // don't want 48 bit pointers
72     enum LARGECODE = 0;
73 }
74 else
75 {
76     bool LARGEDATA() { return (config.memmodel & 6) != 0; }
77     bool LARGECODE() { return (config.memmodel & 5) != 0; }
78 }
79 
80 // Language for error messages
81 enum LANG
82 {
83     LANGenglish,
84     LANGgerman,
85     LANGfrench,
86     LANGjapanese,
87 }
88 
89 
90 //#if SPP || SCPP
91 //#include        "msgs2.h"
92 //#endif
93 //#include        "ty.h"
94 //#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_DRAGONFLYBSD || TARGET_SOLARIS
95 //#include        "../tk/mem.h"
96 //#else
97 //#include        "mem.h"
98 //#endif
99 //#include        "list.h"
100 //#include        "vec.h"
101 
102 version (SPP)
103 {
104     enum COMPILER = "Preprocessor";
105     enum ACTIVITY = "preprocessing...";
106 }
107 else version (HTOD)
108 {
109     enum COMPILER = ".h to D Migration Tool";
110     enum ACTIVITY = "migrating...";
111 }
112 else version (SCPP)
113 {
114     enum COMPILER = "C/C++ Compiler";
115     enum ACTIVITY = "compiling...";
116 }
117 
118 //#ifdef DEBUG
119 //#   define debug(a)     (a)
120 //#   define debugx(a)    (a)
121 //#   define debug_assert assert
122 //#else
123 //#   define debug(a)
124 //#   define debugx(a)
125 //#   define debug_assert(e)
126 //#endif
127 
128 /***************************
129  * Print out debugging information.
130  */
131 
132 //#ifdef DEBUG
133 //#define debugmes(s)     (debugw && dbg_printf(s))
134 //#define cmes(s)         (debugc && dbg_printf(s))
135 //#define cmes2(s,b)      (debugc && dbg_printf((s),(b)))
136 //#define cmes3(s,b,c)    (debugc && dbg_printf((s),(b),(c)))
137 //#else
138 //#define debugmes(s)
139 //#define cmes(s)
140 //#define cmes2(s,b)
141 //#define cmes3(s,b,c)
142 //#endif
143 
144 
145 //#define arraysize(array)        (sizeof(array) / sizeof(array[0]))
146 
147 enum IDMAX = 900;              // identifier max (excluding terminating 0)
148 enum IDOHD = 4+1+int.sizeof*3; // max amount of overhead to ID added by
149 enum STRMAX = 65000;           // max length of string (determined by
150                                // max ph size)
151 
152 //enum SC;
153 struct Thunk
154 {   Symbol *sfunc;
155     Symbol *sthunk;
156     targ_size_t d;
157     targ_size_t d2;
158     int i;
159 }
160 
161 
162 version (MARS)
163     struct token_t;
164 else
165     import dtoken : token_t;
166 
167 //struct param_t;
168 //struct block;
169 //struct Classsym;
170 //struct Nspacesym;
171 //struct Outbuffer;
172 //struct Aliassym;
173 //struct dt_t;
174 //typedef struct TYPE type;
175 //typedef struct Symbol symbol;
176 alias Funcsym = Symbol;
177 //#if !MARS
178 //typedef struct MACRO macro_t;
179 version (MARS)
180     struct blklst;
181 else
182     import parser : blklst;
183 //#endif
184 //typedef list_t symlist_t;       /* list of pointers to Symbols          */
185 alias symlist_t = list_t;
186 alias vec_t = size_t*;
187 alias enum_TK = ubyte;
188 
189 __gshared Config config;
190 
191 uint CPP() { return config.flags3 & CFG3cpp; }
192 
193 
194 /////////// Position in source file
195 
196 struct Srcpos
197 {
198 nothrow:
199     uint Slinnum;           // 0 means no info available
200     uint Scharnum;
201     version (SCPP)
202     {
203         Sfile **Sfilptr;            // file
204         short Sfilnum;              // file number
205     }
206     version (SPP)
207     {
208         Sfile **Sfilptr;            // file
209         short Sfilnum;              // file number
210     }
211     version (HTOD)
212     {
213         Sfile **Sfilptr;            // file
214         short Sfilnum;              // file number
215     }
216 
217     version (MARS)
218     {
219         const(char)* Sfilename;
220 
221         const(char*) name() const { return Sfilename; }
222 
223         static Srcpos create(const(char)* filename, uint linnum, int charnum)
224         {
225             // Cannot have constructor because Srcpos is used in a union
226             Srcpos sp;
227             sp.Sfilename = filename;
228             sp.Slinnum = linnum;
229             sp.Scharnum = charnum;
230             return sp;
231         }
232 
233         /*******
234          * Set fields of Srcpos
235          * Params:
236          *      filename = file name
237          *      linnum = line number
238          *      charnum = character number
239          */
240         void set(const(char)* filename, uint linnum, int charnum) pure
241         {
242             Sfilename = filename;
243             Slinnum = linnum;
244             Scharnum = charnum;
245         }
246     }
247 
248     void print(const(char)* func) const { Srcpos_print(this, func); }
249 }
250 
251 version (SCPP)
252 {
253     static Sfile srcpos_sfile(Srcpos p) { return **(p).Sfilptr; }
254     static char* srcpos_name(Srcpos p)   { return srcpos_sfile(p).SFname; }
255 }
256 version (SPP)
257 {
258     static Sfile srcpos_sfile(Srcpos p) { return **(p).Sfilptr; }
259     static char* srcpos_name(Srcpos p)   { return srcpos_sfile(p).SFname; }
260 }
261 version (HTOD)
262 {
263     static Sfile srcpos_sfile(Srcpos p) { return **(p).Sfilptr; }
264     static char* srcpos_name(Srcpos p)   { return srcpos_sfile(p).SFname; }
265 }
266 
267 void Srcpos_print(ref const Srcpos srcpos, const(char)* func);
268 
269 //#include "token.h"
270 
271 alias stflags_t = uint;
272 enum
273 {
274     PFLpreprocessor  = 1,       // in preprocessor
275     PFLmasm          = 2,       // in Microsoft-style inline assembler
276     PFLbasm          = 4,       // in Borland-style inline assembler
277     PFLsemi          = 8,       // ';' means start of comment
278 //  PFLautogen       = 0x10,    // automatically generate HX ph file
279     PFLmftemp        = 0x20,    // if expanding member function template
280     PFLextdef        = 0x40,    // we had an external def
281     PFLhxwrote       = 0x80,    // already generated HX ph file
282     PFLhxdone        = 0x100,   // done with HX ph file
283 
284     // if TX86
285     PFLhxread        = 0x200,   // have read in an HX ph file
286     PFLhxgen         = 0x400,   // need to generate HX ph file
287     PFLphread        = 0x800,   // read a ph file
288     PFLcomdef        = 0x1000,  // had a common block
289     PFLmacdef        = 0x2000,  // defined a macro in the source code
290     PFLsymdef        = 0x4000,  // declared a global Symbol in the source
291     PFLinclude       = 0x8000,  // read a .h file
292     PFLmfc           = 0x10000, // something will affect MFC compatibility
293 }
294 
295 alias sthflags_t = char;
296 enum
297 {
298     FLAG_INPLACE    = 0,       // in place hydration
299     FLAG_HX         = 1,       // HX file hydration
300     FLAG_SYM        = 2,       // .SYM file hydration
301 }
302 
303 /**********************************
304  * Current 'state' of the compiler.
305  * Used to gather together most global variables.
306  * This struct is saved/restored during function body parsing.
307  */
308 
309 struct Pstate
310 {
311     ubyte STinopeq;             // if in n2_createopeq()
312     ubyte STinarglist;          // if !=0, then '>' is the end of a template
313                                 // argument list, not an operator
314     ubyte STinsizeof;           // !=0 if in a sizeof expression. Useful to
315                                 // prevent <array of> being converted to
316                                 // <pointer to>.
317     ubyte STintemplate;         // if !=0, then expanding a function template
318                                 // (do not expand template Symbols)
319     ubyte STdeferDefaultArg;    // defer parsing of default arg for parameter
320     ubyte STnoexpand;           // if !=0, don't expand template symbols
321     ubyte STignoretal;          // if !=0 ignore template argument list
322     ubyte STexplicitInstantiation;      // if !=0, then template explicit instantiation
323     ubyte STexplicitSpecialization;     // if !=0, then template explicit specialization
324     ubyte STinconstexp;         // if !=0, then parsing a constant expression
325     ubyte STisaddr;             // is this a possible pointer to member expression?
326     uint STinexp;               // if !=0, then in an expression
327 
328     static if (NTEXCEPTIONS)
329     {
330         ubyte STinfilter;       // if !=0 then in exception filter
331         ubyte STinexcept;       // if !=0 then in exception handler
332         block *STbfilter;       // current exception filter
333     }
334 
335     version (MARS)
336     {
337     }
338     else
339     {
340         int STinitseg;          // segment for static constructor function pointer
341     }
342     Funcsym *STfuncsym_p;       // if inside a function, then this is the
343                                 // function Symbol.
344 
345     stflags_t STflags;
346 
347     version (MARS)
348     {
349     }
350     else
351     {
352         int STinparamlist;      // if != 0, then parser is in
353                                 // function parameter list
354         int STingargs;          // in template argument list
355         list_t STincalias;      // list of include aliases
356         list_t STsysincalias;   // list of system include aliases
357     }
358 
359     // should probably be inside #if HYDRATE, but unclear for the dmc source
360     sthflags_t SThflag;         // FLAG_XXXX: hydration flag
361 
362     Classsym *STclasssym;       // if in the scope of this class
363     symlist_t STclasslist;      // list of classes that have deferred inline
364                                 // functions to parse
365     Classsym *STstag;           // returned by struct_searchmember() and with_search()
366     SYMIDX STmarksi;            // to determine if temporaries are created
367     ubyte STnoparse;            // add to classlist instead of parsing
368     ubyte STdeferparse;         // defer member func parse
369     SC STgclass;                // default function storage class
370     int STdefertemps;           // defer allocation of temps
371     int STdeferaccesscheck;     // defer access check for members (BUG: it
372                                 // never does get done later)
373     int STnewtypeid;            // parsing new-type-id
374     int STdefaultargumentexpression;    // parsing default argument expression
375     block *STbtry;              // current try block
376     block *STgotolist;          // threaded goto scoping list
377     int STtdbtimestamp;         // timestamp of tdb file
378     Symbol *STlastfunc;         // last function symbol parsed by ext_def()
379 
380     // For "point of definition" vs "point of instantiation" template name lookup
381     uint STsequence;            // sequence number (Ssequence) of next Symbol
382     uint STmaxsequence;         // won't find Symbols with STsequence larger
383                                 // than STmaxsequence
384 }
385 
386 void funcsym_p(Funcsym* fp) { pstate.STfuncsym_p = fp; }
387 Funcsym* funcsym_p() { return pstate.STfuncsym_p; }
388 
389 stflags_t preprocessor() { return pstate.STflags & PFLpreprocessor; }
390 stflags_t inline_asm()   { return pstate.STflags & (PFLmasm | PFLbasm); }
391 
392 extern __gshared Pstate pstate;
393 
394 /****************************
395  * Global variables.
396  */
397 
398 struct Cstate
399 {
400     blklst* CSfilblk;           // current source file we are parsing
401     Symbol* CSlinkage;          // table of forward referenced linkage pragmas
402     list_t CSlist_freelist;     // free list for list package
403     symtab_t* CSpsymtab;        // pointer to current Symbol table
404 //#if MEMORYHX
405 //    void **CSphx;               // pointer to HX data block
406 //#endif
407     char* modname;              // module unique identifier
408 }
409 
410 extern __gshared Cstate cstate;
411 
412 /* Bits for sytab[] that give characteristics of storage classes        */
413 enum
414 {
415     SCEXP = 1,      // valid inside expressions
416     SCKEP = 2,      // Symbol should be kept even when function is done
417     SCSCT = 4,      // storage class is valid for use in static ctor
418     SCSS  = 8,      // storage class is on the stack
419     SCRD  = 0x10,   // we can do reaching definitions on these
420 }
421 
422 // Determine if Symbol has a Ssymnum associated with it.
423 // (That is, it is allocated on the stack or has live variable analysis
424 //  done on it, so it is stack and register variables.)
425 //char symbol_isintab(Symbol *s) { return sytab[s.Sclass] & SCSS; }
426 
427 //version (Windows)
428     alias enum_SC = char;
429 //else
430 //    alias SC enum_SC;
431 
432 
433 /******************************************
434  * Basic blocks:
435  *      Basic blocks are a linked list of all the basic blocks
436  *      in a function. startblock heads the list.
437  */
438 
439 alias ClassDeclaration_ = void*;
440 alias Declaration_ = void*;
441 alias Module_ = void*;
442 
443 struct Blockx
444 {
445   version (MARS)
446   {
447     block* startblock;
448     block* curblock;
449     Funcsym* funcsym;
450     Symbol* context;            // eh frame context variable
451     int scope_index;            // current scope index
452     int next_index;             // value for next scope index
453     uint flags;                 // value to OR into Bflags
454     block* tryblock;            // current enclosing try block
455     elem* init;                 // static initializer
456     ClassDeclaration_ classdec;
457     Declaration_ member;        // member we're compiling for
458     Module_ _module;            // module we're in
459   }
460 }
461 
462 alias bflags_t = ushort;
463 enum
464 {
465     BFLvisited       = 1,       // set if block is visited
466     BFLmark          = 2,       // set if block is visited
467     BFLjmpoptdone    = 4,       // set when no more jump optimizations
468                                 //  are possible for this block
469     BFLnostackopt    = 8,       // set when stack elimination should not
470                                 // be done
471     // NTEXCEPTIONS
472     BFLehcode        = 0x10,    // BC_filter: need to load exception code
473     BFLunwind        = 0x1000,  // do local_unwind following block (unused)
474 
475     BFLnomerg        = 0x20,    // do not merge with other blocks
476     BFLprolog        = 0x80,    // generate function prolog
477     BFLepilog        = 0x100,   // generate function epilog
478     BFLrefparam      = 0x200,   // referenced parameter
479     BFLreflocal      = 0x400,   // referenced local
480     BFLoutsideprolog = 0x800,   // outside function prolog/epilog
481     BFLlabel         = 0x2000,  // block preceded by label
482     BFLvolatile      = 0x4000,  // block is volatile
483     BFLnounroll      = 0x8000,  // do not unroll loop
484 }
485 
486 struct block
487 {
488 nothrow:
489     union
490     {
491         elem *Belem;            // pointer to elem tree
492         list_t  Blist;          // list of expressions
493     }
494 
495     block *Bnext;               // pointer to next block in list
496     list_t Bsucc;               // linked list of pointers to successors
497                                 //     of this block
498     list_t Bpred;               // and the predecessor list
499     int Bindex;                 // into created object stack
500     int Bendindex;              // index at end of block
501     block *Btry;                // BCtry,BC_try: enclosing try block, if any
502                                 // BC???: if in try-block, points to BCtry or BC_try
503                                 // note that can't have a BCtry and BC_try in
504                                 // the same function.
505     union
506     {
507         targ_llong*      Bswitch;      // BCswitch: pointer to switch data
508         struct
509         {
510             regm_t usIasmregs;         // Registers modified
511             ubyte bIasmrefparam;       // References parameters?
512         }
513 
514         struct
515         {
516             Symbol* catchvar;           // __throw() fills in this
517         }                               // BCtry
518 
519         version (SCPP)
520         {
521             struct
522             {
523                 type *Bcatchtype;       // one type for each catch block
524             }                           // BCcatch
525         }
526 
527         version (HTOD)
528         {
529             struct
530             {
531                 type *Bcatchtype;       // one type for each catch block
532             }                           // BCcatch
533         }
534 
535         version (MARS)
536         {
537             struct
538             {
539                 Symbol* Bcatchtype;     // one type for each catch block
540                 uint* actionTable;      // EH_DWARF: indices into typeTable, first is # of entries
541             }                           // BCjcatch
542         }
543 
544         struct
545         {
546             version (MARS)
547             {
548                 Symbol *jcatchvar;      // __d_throw() fills in this
549             }
550             int Bscope_index;           // index into scope table
551             int Blast_index;            // enclosing index into scope table
552         }                               // BC_try
553 
554         struct
555         {
556             Symbol *flag;               // EH_DWARF: set to 'flag' symbol that encloses finally
557             block *b_ret;               // EH_DWARF: associated BC_ret block
558         }                               // finally
559 
560         // add member mimicking the largest of the other elements of this union, so it can be copied
561         struct _BS { version (MARS) { Symbol *jcvar; } int Bscope_idx, Blast_idx; }
562         _BS BS;
563     }
564     Srcpos      Bsrcpos;        // line number (0 if not known)
565     ubyte       BC;             // exit condition (enum BC)
566 
567     ubyte       Balign;         // alignment
568 
569     bflags_t    Bflags;         // flags (BFLxxxx)
570     code*       Bcode;          // code generated for this block
571 
572     uint        Bweight;        // relative number of times this block
573                                 // is executed (optimizer and codegen)
574 
575     uint        Bdfoidx;        // index of this block in dfo[]
576     uint        Bnumber;        // sequence number of block
577     union
578     {
579         uint _BLU;              // start of the union
580 
581         // CPP
582         struct
583         {
584             SYMIDX      Bsymstart;      // (symstart <= symnum < symend) Symbols
585             SYMIDX      Bsymend;        // are declared in this block
586             block*      Bendscope;      // block that forms the end of the
587                                         // scope for the declared Symbols
588             uint        Bblknum;        // position of block from startblock
589             Symbol*     Binitvar;       // !=NULL points to an auto variable with
590                                         // an explicit or implicit initializer
591             block*      Bgotolist;      // BCtry, BCcatch: backward list of try scopes
592             block*      Bgotothread;    // BCgoto: threaded list of goto's to
593                                         // unknown labels
594         }
595 
596         // OPTIMIZER
597         struct
598         {
599             vec_t       Bdom;           // mask of dominators for this block
600             vec_t       Binrd;
601             vec_t       Boutrd;         // IN and OUT for reaching definitions
602             vec_t       Binlv;
603             vec_t       Boutlv;         // IN and OUT for live variables
604             vec_t       Bin;
605             vec_t       Bout;           // IN and OUT for other flow analyses
606             vec_t       Bgen;
607             vec_t       Bkill;          // pointers to bit vectors used by data
608                                         // flow analysis
609 
610             // BCiftrue can have different vectors for the 2nd successor:
611             vec_t       Bout2;
612             vec_t       Bgen2;
613             vec_t       Bkill2;
614         }
615 
616         // CODGEN
617         struct
618         {
619             // For BCswitch, BCjmptab
620             targ_size_t Btablesize;     // size of generated table
621             targ_size_t Btableoffset;   // offset to start of table
622             targ_size_t Btablebase;     // offset to instruction pointer base
623 
624             targ_size_t Boffset;        // code offset of start of this block
625             targ_size_t Bsize;          // code size of this block
626             con_t       Bregcon;        // register state at block exit
627             targ_size_t Btryoff;        // BCtry: offset of try block data
628         }
629     }
630 
631     void appendSucc(block* b)        { list_append(&this.Bsucc, b); }
632     void prependSucc(block* b)       { list_prepend(&this.Bsucc, b); }
633     int numSucc()                    { return list_nitems(this.Bsucc); }
634     block* nthSucc(int n)            { return cast(block*)list_ptr(list_nth(Bsucc, n)); }
635     void setNthSucc(int n, block *b) { list_nth(Bsucc, n).ptr = b; }
636 }
637 
638 inout(block)* list_block(inout list_t lst) { return cast(inout(block)*)list_ptr(lst); }
639 
640 /** Basic block control flow operators. **/
641 
642 alias BC = int;
643 enum
644 {
645     BCgoto      = 1,    // goto Bsucc block
646     BCiftrue    = 2,    // if (Belem) goto Bsucc[0] else Bsucc[1]
647     BCret       = 3,    // return (no return value)
648     BCretexp    = 4,    // return with return value
649     BCexit      = 5,    // never reaches end of block (like exit() was called)
650     BCasm       = 6,    // inline assembler block (Belem is NULL, Bcode
651                         // contains code generated).
652                         // These blocks have one or more successors in Bsucc,
653                         // never 0
654     BCswitch    = 7,    // switch statement
655                         // Bswitch points to switch data
656                         // Default is Bsucc
657                         // Cases follow in linked list
658     BCifthen    = 8,    // a BCswitch is converted to if-then
659                         // statements
660     BCjmptab    = 9,    // a BCswitch is converted to a jump
661                         // table (switch value is index into
662                         // the table)
663     BCtry       = 10,   // C++ try block
664                         // first block in a try-block. The first block in
665                         // Bsucc is the next one to go to, subsequent
666                         // blocks are the catch blocks
667     BCcatch     = 11,   // C++ catch block
668     BCjump      = 12,   // Belem specifies (near) address to jump to
669     BC_try      = 13,   // SEH: first block of try-except or try-finally
670                         // D: try-catch or try-finally
671     BC_filter   = 14,   // SEH exception-filter (always exactly one block)
672     BC_finally  = 15,   // first block of SEH termination-handler,
673                         // or D finally block
674     BC_ret      = 16,   // last block of SEH termination-handler or D _finally block
675     BC_except   = 17,   // first block of SEH exception-handler
676     BCjcatch    = 18,   // D catch block
677     BC_lpad     = 19,   // EH_DWARF: landing pad for BC_except
678     BCMAX
679 }
680 
681 /********************************
682  * Range for blocks.
683  */
684 struct BlockRange
685 {
686   pure nothrow @nogc @safe:
687 
688     this(block* b)
689     {
690         this.b = b;
691     }
692 
693     block* front() return  { return b; }
694     void popFront() { b = b.Bnext; }
695     bool empty() const { return !b; }
696 
697   private:
698     block* b;
699 }
700 
701 /**********************************
702  * Functions
703  */
704 
705 struct symtab_t
706 {
707     SYMIDX top;                 // 1 past end
708     SYMIDX symmax;              // max # of entries in tab[] possible
709     Symbol **tab;               // local Symbol table
710 }
711 
712 alias func_flags_t = uint;
713 enum
714 {
715     Fpending    = 1,           // if function has been queued for being written
716     Foutput     = 2,           // if function has been written out
717     Foperator   = 4,           // if operator overload
718     Fcast       = 8,           // if cast overload
719     Finline     = 0x10,        // if SCinline, and function really is inline
720     Foverload   = 0x20,        // if function can be overloaded
721     Ftypesafe   = 0x40,        // if function name needs type appended
722     Fmustoutput = 0x80,        // set for forward ref'd functions that
723                                // must be output
724     Fvirtual    = 0x100,       // if function is a virtual function
725     Fctor       = 0x200,       // if function is a constructor
726     Fdtor       = 0x400,       // if function is a destructor
727     Fnotparent  = 0x800,       // if function is down Foversym chain
728     Finlinenest = 0x1000,      // used as a marker to prevent nested
729                                // inlines from expanding
730     Flinkage    = 0x2000,      // linkage is already specified
731     Fstatic     = 0x4000,      // static member function (no this)
732     Fbitcopy    = 0x8000,      // it's a simple bitcopy (op=() or X(X&))
733     Fpure       = 0x10000,     // pure function
734     Finstance   = 0x20000,     // function is an instance of a template
735     Ffixed      = 0x40000,     // ctor has had cpp_fixconstructor() run on it,
736                                // dtor has had cpp_fixdestructor()
737     Fintro      = 0x80000,     // function doesn't hide a previous virtual function
738 //  unused      = 0x100000,    // unused bit
739     Fkeeplink   = 0x200000,    // don't change linkage to default
740     Fnodebug    = 0x400000,    // do not generate debug info for this function
741     Fgen        = 0x800000,    // compiler generated function
742     Finvariant  = 0x1000000,   // __invariant function
743     Fexplicit   = 0x2000000,   // explicit constructor
744     Fsurrogate  = 0x4000000,   // surrogate call function
745 }
746 
747 alias func_flags3_t = uint;
748 enum
749 {
750     Fvtblgen         = 1,       // generate vtbl[] when this function is defined
751     Femptyexc        = 2,       // empty exception specification (obsolete, use Tflags & TFemptyexc)
752     Fcppeh           = 4,       // uses C++ EH
753     Fnteh            = 8,       // uses NT Structured EH
754     Fdeclared        = 0x10,    // already declared function Symbol
755     Fmark            = 0x20,    // has unbalanced OPctor's
756     Fdoinline        = 0x40,    // do inline walk
757     Foverridden      = 0x80,    // ignore for overriding purposes
758     Fjmonitor        = 0x100,   // Mars synchronized function
759     Fnosideeff       = 0x200,   // function has no side effects
760     F3badoparrow     = 0x400,   // bad operator->()
761     Fmain            = 0x800,   // function is main() or wmain()
762     Fnested          = 0x1000,  // D nested function with 'this'
763     Fmember          = 0x2000,  // D member function with 'this'
764     Fnotailrecursion = 0x4000,  // no tail recursion optimizations
765     Ffakeeh          = 0x8000,  // allocate space for NT EH context sym anyway
766     Fnothrow         = 0x10000, // function does not throw (even if not marked 'nothrow')
767     Feh_none         = 0x20000, // ehmethod==EH_NONE for this function only
768 }
769 
770 struct func_t
771 {
772     symlist_t Fsymtree;         // local Symbol table
773     block *Fstartblock;         // list of blocks comprising function
774     symtab_t Flocsym;           // local Symbol table
775     Srcpos Fstartline;          // starting line # of function
776     Srcpos Fendline;            // line # of closing brace of function
777     Symbol *F__func__;          // symbol for __func__[] string
778     func_flags_t Fflags;
779     func_flags3_t Fflags3;
780     ubyte Foper;                // operator number (OPxxxx) if Foperator
781 
782     Symbol *Fparsescope;        // use this scope to parse friend functions
783                                 // which are defined within a class, so the
784                                 // class is in scope, but are not members
785                                 // of the class
786 
787     Classsym *Fclass;           // if member of a class, this is the class
788                                 // (I think this is redundant with Sscope)
789     Funcsym *Foversym;          // overloaded function at same scope
790     symlist_t Fclassfriends;    // Symbol list of classes of which this
791                                 // function is a friend
792     block *Fbaseblock;          // block where base initializers get attached
793     block *Fbaseendblock;       // block where member destructors get attached
794     elem *Fbaseinit;            // list of member initializers (meminit_t)
795                                 // this field has meaning only for
796                                 // functions which are constructors
797     token_t *Fbody;             // if deferred parse, this is the list
798                                 // of tokens that make up the function
799                                 // body
800                                 // also used if SCfunctempl, SCftexpspec
801     uint Fsequence;             // sequence number at point of definition
802     union
803     {
804         Symbol* Ftempl;         // if Finstance this is the template that generated it
805         Thunk* Fthunk;          // !=NULL if this function is actually a thunk
806     }
807     Funcsym *Falias;            // SCfuncalias: function Symbol referenced
808                                 // by using-declaration
809     symlist_t Fthunks;          // list of thunks off of this function
810     param_t *Farglist;          // SCfunctempl: the template-parameter-list
811     param_t *Fptal;             // Finstance: this is the template-argument-list
812                                 // SCftexpspec: for explicit specialization, this
813                                 // is the template-argument-list
814     list_t Ffwdrefinstances;    // SCfunctempl: list of forward referenced instances
815     list_t Fexcspec;            // List of types in the exception-specification
816                                 // (NULL if none or empty)
817     Funcsym *Fexplicitspec;     // SCfunctempl, SCftexpspec: threaded list
818                                 // of SCftexpspec explicit specializations
819     Funcsym *Fsurrogatesym;     // Fsurrogate: surrogate cast function
820 
821     char *Fredirect;            // redirect function name to this name in object
822 
823     // Array of catch types for EH_DWARF Types Table generation
824     Barray!(Symbol*) typesTable;
825 
826     union
827     {
828         uint LSDAoffset;        // ELFOBJ: offset in LSDA segment of the LSDA data for this function
829         Symbol* LSDAsym;        // MACHOBJ: GCC_except_table%d
830     }
831 }
832 
833 //func_t* func_calloc() { return cast(func_t *) mem_fcalloc(func_t.sizeof); }
834 //void    func_free(func_t *f) { mem_ffree(f); }
835 
836 /**************************
837  * Item in list for member initializer.
838  */
839 
840 struct meminit_t
841 {
842     list_t  MIelemlist;         // arg list for initializer
843     Symbol *MIsym;              // if NULL, then this initializer is
844                                 // for the base class. Otherwise, this
845                                 // is the member that needs the ctor
846                                 // called for it
847 }
848 
849 alias baseclass_flags_t = uint;
850 enum
851 {
852      BCFpublic     = 1,         // base class is public
853      BCFprotected  = 2,         // base class is protected
854      BCFprivate    = 4,         // base class is private
855 
856      BCFvirtual    = 8,         // base class is virtual
857      BCFvfirst     = 0x10,      // virtual base class, and this is the
858                                 // first virtual appearance of it
859      BCFnewvtbl    = 0x20,      // new vtbl generated for this base class
860      BCFvirtprim   = 0x40,      // Primary base class of a virtual base class
861      BCFdependent  = 0x80,      // base class is a dependent type
862 }
863 enum baseclass_flags_t BCFpmask = BCFpublic | BCFprotected | BCFprivate;
864 
865 
866 /************************************
867  * Base classes are a list of these.
868  */
869 
870 struct baseclass_t
871 {
872     Classsym*         BCbase;           // base class Symbol
873     baseclass_t*      BCnext;           // next base class
874     targ_size_t       BCoffset;         // offset from start of derived class to this
875     ushort            BCvbtbloff;       // for BCFvirtual, offset from start of
876                                         //     vbtbl[] to entry for this virtual base.
877                                         //     Valid in Sbase list
878     symlist_t         BCpublics;        // public members of base class (list is freeable)
879     list_t            BCmptrlist;       // (in Smptrbase only) this is the vtbl
880                                         // (NULL if not different from base class's vtbl
881     Symbol*           BCvtbl;           // Symbol for vtbl[] array (in Smptrbase list)
882                                         // Symbol for vbtbl[] array (in Svbptrbase list)
883     baseclass_flags_t BCflags;          // base class flags
884     Classsym*         BCparent;         // immediate parent of this base class
885                                         //     in Smptrbase
886     baseclass_t*      BCpbase;          // parent base, NULL if did not come from a parent
887 }
888 
889 //baseclass_t* baseclass_malloc() { return cast(baseclass_t*) mem_fmalloc(baseclass_t.sizeof); }
890 void baseclass_free(baseclass_t *b) { }
891 
892 /*************************
893  * For virtual tables.
894  */
895 
896 alias mptr_flags_t = char;
897 enum
898 {
899     MPTRvirtual     = 1,       // it's an offset to a virtual base
900     MPTRcovariant   = 2,       // need covariant return pointer adjustment
901 }
902 
903 struct mptr_t
904 {
905     targ_short     MPd;
906     targ_short     MPi;
907     Symbol        *MPf;
908     Symbol        *MPparent;    // immediate parent of this base class
909                                 //   in Smptrbase
910     mptr_flags_t   MPflags;
911 }
912 
913 inout(mptr_t)* list_mptr(inout(list_t) lst) { return cast(inout(mptr_t)*) list_ptr(lst); }
914 
915 
916 /***********************************
917  * Information gathered about externally defined template member functions,
918  * member data, and member classes.
919  */
920 
921 struct TMF
922 {
923     Classsym *stag;             // if !=NULL, this is the enclosing class
924     token_t *tbody;             // tokens making it up
925     token_t *to;                // pointer within tbody where we left off in
926                                 // template_function_decl()
927     param_t *temp_arglist;      // template parameter list
928     int member_class;           // 1: it's a member class
929 
930     // These are for member templates
931     int castoverload;           // 1: it's a user defined cast
932     char *name;                 // name of template (NULL if castoverload)
933     int member_template;        // 0: regular template
934                                 // 1: member template
935     param_t *temp_arglist2;     // if member template,
936                                 // then member's template parameter list
937 
938     param_t *ptal;              // if explicit specialization, this is the
939                                 // explicit template-argument-list
940     Symbol *sclassfriend;       // if member function is a friend of class X,
941                                 // this is class X
942     uint access_specifier;
943 }
944 
945 /***********************************
946  * Information gathered about primary member template explicit specialization.
947  */
948 
949 struct TME
950 {
951     /* Given:
952      *  template<> template<class T2> struct A<short>::B { };
953      *  temp_arglist2 = <class T2>
954      *  name = "B"
955      *  ptal = <short>
956      */
957     param_t *ptal;              // explicit template-argument-list for enclosing
958                                 // template A
959     Symbol *stempl;             // template symbol for B
960 }
961 
962 /***********************************
963  * Information gathered about nested explicit specializations.
964  */
965 
966 struct TMNE
967 {
968     /* For:
969      *  template<> template<> struct A<short>::B<double> { };
970      */
971 
972     enum_TK tk;                 // TKstruct / TKclass / TKunion
973     char *name;                 // name of template, i.e. "B"
974     param_t *ptal;              // explicit template-argument-list for enclosing
975                                 // template A, i.e. "short"
976     token_t *tdecl;             // the tokens "<double> { }"
977 }
978 
979 /***********************************
980  * Information gathered about nested class friends.
981  */
982 
983 struct TMNF
984 {
985     /* Given:
986      *  template<class T> struct A { struct B { }; };
987      *  class C { template<class T> friend struct A<T>::B;
988      */
989     token_t *tdecl;             // the tokens "A<T>::B;"
990     param_t *temp_arglist;      // <class T>
991     Classsym *stag;             // the class symbol C
992     Symbol *stempl;             // the template symbol A
993 }
994 
995 /***********************************
996  * Special information for class templates.
997  */
998 
999 struct template_t
1000 {
1001     symlist_t     TMinstances;  // list of Symbols that are instances
1002     param_t*      TMptpl;       // template-parameter-list
1003     token_t*      TMbody;       // tokens making up class body
1004     uint TMsequence;            // sequence number at point of definition
1005     list_t TMmemberfuncs;       // templates for member functions (list of TMF's)
1006     list_t TMexplicit;          // list of TME's: primary member template explicit specializations
1007     list_t TMnestedexplicit;    // list of TMNE's: primary member template nested explicit specializations
1008     Symbol* TMnext;             // threaded list of template classes headed
1009                                 // up by template_class_list
1010     enum_TK        TMtk;        // TKstruct, TKclass or TKunion
1011     int            TMflags;     // STRxxx flags
1012 
1013     Symbol* TMprimary;          // primary class template
1014     Symbol* TMpartial;          // next class template partial specialization
1015     param_t* TMptal;            // template-argument-list for partial specialization
1016                                 // (NULL for primary class template)
1017     list_t TMfriends;           // list of Classsym's for which any instantiated
1018                                 // classes of this template will be friends of
1019     list_t TMnestedfriends;     // list of TMNF's
1020     int TMflags2;               // !=0 means dummy template created by template_createargtab()
1021 }
1022 
1023 /***********************************
1024  * Special information for enums.
1025  */
1026 
1027 alias enum_flags_t = uint;
1028 enum
1029 {
1030     SENnotagname  = 1,       // no tag name for enum
1031     SENforward    = 2,       // forward referenced enum
1032 }
1033 
1034 struct enum_t
1035 {
1036     enum_flags_t SEflags;
1037     Symbol* SEalias;            // pointer to identifier E to use if
1038                                 // enum was defined as:
1039                                 //      typedef enum { ... } E;
1040     symlist_t SEenumlist;       // all members of enum
1041 }
1042 
1043 /***********************************
1044  * Special information for structs.
1045  */
1046 
1047 alias struct_flags_t = uint;
1048 enum
1049 {
1050     STRanonymous     = 1,          // set for unions with no tag names
1051     STRglobal        = 2,          // defined at file scope
1052     STRnotagname     = 4,          // struct/class with no tag name
1053     STRoutdef        = 8,          // we've output the debug definition
1054     STRbitfields     = 0x10,       // set if struct contains bit fields
1055     STRabstract      = 0x20,       // abstract class
1056     STRbitcopy       = 0x40,       // set if operator=() is merely a bit copy
1057     STRanyctor       = 0x80,       // set if any constructors were defined
1058                                    // by the user
1059     STRnoctor        = 0x100,      // no constructors allowed
1060     STRgen           = 0x200,      // if struct is an instantiation of a
1061                                    // template class, and was generated by
1062                                    // that template
1063     STRvtblext       = 0x400,      // generate vtbl[] only when first member function
1064                                    // definition is encountered (see Fvtblgen)
1065     STRexport        = 0x800,      // all member functions are to be _export
1066     STRpredef        = 0x1000,     // a predefined struct
1067     STRunion         = 0x2000,     // actually, it's a union
1068     STRclass         = 0x4000,     // it's a class, not a struct
1069     STRimport        = 0x8000,     // imported class
1070     STRstaticmems    = 0x10000,    // class has static members
1071     STR0size         = 0x20000,    // zero sized struct
1072     STRinstantiating = 0x40000,    // if currently being instantiated
1073     STRexplicit      = 0x80000,    // if explicit template instantiation
1074     STRgenctor0      = 0x100000,   // need to gen X::X()
1075     STRnotpod        = 0x200000,   // struct is not POD
1076 }
1077 
1078 struct struct_t
1079 {
1080     targ_size_t Sstructsize;    // size of struct
1081     symlist_t Sfldlst;          // all members of struct (list freeable)
1082     Symbol *Sroot;              // root of binary tree Symbol table
1083     uint Salignsize;            // size of struct for alignment purposes
1084     ubyte Sstructalign;         // struct member alignment in effect
1085     struct_flags_t Sflags;
1086     tym_t ptrtype;              // type of pointer to refer to classes by
1087     ushort access;              // current access privilege, here so
1088                                 // enum declarations can get at it
1089     targ_size_t Snonvirtsize;   // size of struct excluding virtual classes
1090     list_t Svirtual;            // freeable list of mptrs
1091                                 // that go into vtbl[]
1092     list_t *Spvirtder;          // pointer into Svirtual that points to start
1093                                 // of virtual functions for this (derived) class
1094     symlist_t Sopoverload;      // overloaded operator funcs (list freeable)
1095     symlist_t Scastoverload;    // overloaded cast funcs (list freeable)
1096     symlist_t Sclassfriends;    // list of classes of which this is a friend
1097                                 // (list is freeable)
1098     symlist_t Sfriendclass;     // classes which are a friend to this class
1099                                 // (list is freeable)
1100     symlist_t Sfriendfuncs;     // functions which are a friend to this class
1101                                 // (list is freeable)
1102     symlist_t Sinlinefuncs;     // list of tokenized functions
1103     baseclass_t *Sbase;         // list of direct base classes
1104     baseclass_t *Svirtbase;     // list of all virtual base classes
1105     baseclass_t *Smptrbase;     // list of all base classes that have
1106                                 // their own vtbl[]
1107     baseclass_t *Sprimary;      // if not NULL, then points to primary
1108                                 // base class
1109     Funcsym *Svecctor;          // constructor for use by vec_new()
1110     Funcsym *Sctor;             // constructor function
1111 
1112     Funcsym *Sdtor;             // basic destructor
1113     Funcsym *Sprimdtor;         // primary destructor
1114     Funcsym *Spriminv;          // primary invariant
1115     Funcsym *Sscaldeldtor;      // scalar deleting destructor
1116 
1117     Funcsym *Sinvariant;        // basic invariant function
1118 
1119     Symbol *Svptr;              // Symbol of vptr
1120     Symbol *Svtbl;              // Symbol of vtbl[]
1121     Symbol *Svbptr;             // Symbol of pointer to vbtbl[]
1122     Symbol *Svbptr_parent;      // base class for which Svbptr is a member.
1123                                 // NULL if Svbptr is a member of this class
1124     targ_size_t Svbptr_off;     // offset of Svbptr member
1125     Symbol *Svbtbl;             // virtual base offset table
1126     baseclass_t *Svbptrbase;    // list of all base classes in canonical
1127                                 // order that have their own vbtbl[]
1128     Funcsym *Sopeq;             // X& X::operator =(X&)
1129     Funcsym *Sopeq2;            // Sopeq, but no copy of virtual bases
1130     Funcsym *Scpct;             // copy constructor
1131     Funcsym *Sveccpct;          // vector copy constructor
1132     Symbol *Salias;             // pointer to identifier S to use if
1133                                 // struct was defined as:
1134                                 //      typedef struct { ... } S;
1135 
1136     Symbol *Stempsym;           // if this struct is an instantiation
1137                                 // of a template class, this is the
1138                                 // template class Symbol
1139 
1140     // For 64 bit Elf function ABI
1141     type *Sarg1type;
1142     type *Sarg2type;
1143 
1144     /* For:
1145      *  template<class T> struct A { };
1146      *  template<class T> struct A<T *> { };
1147      *
1148      *  A<int> a;               // primary
1149      * Gives:
1150      *  Sarglist = <int>
1151      *  Spr_arglist = NULL;
1152      *
1153      *  A<int*> a;              // specialization
1154      * Gives:
1155      *  Sarglist = <int>
1156      *  Spr_arglist = <int*>;
1157      */
1158 
1159     param_t *Sarglist;          // if this struct is an instantiation
1160                                 // of a template class, this is the
1161                                 // actual arg list used
1162     param_t *Spr_arglist;       // if this struct is an instantiation
1163                                 // of a specialized template class, this is the
1164                                 // actual primary arg list used.
1165                                 // It is NULL for the
1166                                 // primary template class (since it would be
1167                                 // identical to Sarglist).
1168 }
1169 
1170 /**********************************
1171  * Symbol Table
1172  */
1173 
1174 inout(Symbol)* list_symbol(inout list_t lst) { return cast(inout(Symbol)*) list_ptr(lst); }
1175 void list_setsymbol(list_t lst, Symbol* s) { lst.ptr = s; }
1176 inout(Classsym)* list_Classsym(inout list_t lst) { return cast(inout(Classsym)*) list_ptr(lst); }
1177 
1178 enum
1179 {
1180     SFLvalue        = 1,           // Svalue contains const expression
1181     SFLimplem       = 2,           // if seen implementation of Symbol
1182                                    // (function body for functions,
1183                                    // initializer for variables)
1184     SFLdouble       = 2,           // SCregpar or SCparameter, where float
1185                                    // is really passed as a double
1186     SFLfree         = 4,           // if we can symbol_free() a Symbol in
1187                                    // a Symbol table[]
1188     SFLmark         = 8,           // temporary marker
1189     SFLexit         = 0x10,        // tyfunc: function does not return
1190                                    // (ex: exit,abort,_assert,longjmp)
1191     SFLtrue         = 0x200,       // value of Symbol != 0
1192     SFLreplace      = SFLmark,     // variable gets replaced in inline expansion
1193     SFLskipinit     = 0x10000,     // SCfield, SCmember: initializer is skipped
1194     SFLnodebug      = 0x20000,     // don't generate debug info
1195     SFLwasstatic    = 0x800000,    // was an uninitialized static
1196     SFLweak         = 0x1000000,   // resolve to NULL if not found
1197     SFLhidden       = 0x2000000,   // not visible outside of DSOs (-fvisibility=hidden)
1198     SFLartifical    = 0x4000000,   // compiler generated symbol
1199 
1200     // CPP
1201     SFLnodtor       = 0x10,        // set if destructor for Symbol is already called
1202     SFLdtorexp      = 0x80,        // Svalue has expression to tack onto dtor
1203     SFLmutable      = 0x100000,    // SCmember or SCfield is mutable
1204     SFLdyninit      = 0x200000,    // symbol has dynamic initializer
1205     SFLtmp          = 0x400000,    // symbol is a generated temporary
1206     SFLthunk        = 0x40000,     // symbol is temporary for thunk
1207 
1208     // Possible values for protection bits
1209     SFLprivate      = 0x60,
1210     SFLprotected    = 0x40,
1211     SFLpublic       = 0x20,
1212     SFLnone         = 0x00,
1213     SFLpmask        = 0x60,        // mask for the protection bits
1214 
1215     SFLvtbl         = 0x2000,      // VEC_VTBL_LIST: Symbol is a vtable or vbtable
1216 
1217     // OPTIMIZER and CODGEN
1218     GTregcand       = 0x100,       // if Symbol is a register candidate
1219     SFLdead         = 0x800,       // this variable is dead
1220     GTunregister    = 0x8000000,   // 'unregister' a previous register assignment
1221 
1222     // OPTIMIZER only
1223     SFLunambig      = 0x400,       // only accessible by unambiguous reference,
1224                                    // i.e. cannot be addressed via pointer
1225                                    // (GTregcand is a subset of this)
1226                                    // P.S. code generator turns off this
1227                                    // flag if any reads are done from it.
1228                                    // This is to eliminate stores to it
1229                                    // that are never read.
1230     SFLlivexit      = 0x1000,      // live on exit from function
1231     SFLnotbasiciv   = 0x4000,      // not a basic induction variable
1232     SFLnord         = SFLdouble,   // SCauto,SCregister,SCtmp: disallow redundant warnings
1233 
1234     // CODGEN only
1235     GTtried         = SFLmark,     // tried to place in register
1236     GTbyte          = 0x8000,      // variable is sometimes accessed as
1237     SFLread         = 0x40000,     // variable is actually read from
1238                                    // (to eliminate dead stores)
1239     SFLspill        = 0x80000,     // only in register part of the time
1240 }
1241 
1242 struct Symbol
1243 {
1244 //#ifdef DEBUG
1245     debug ushort      id;
1246     enum IDsymbol = 0x5678;
1247 //#define class_debug(s) assert((s)->id == IDsymbol)
1248 //#else
1249 //#define class_debug(s)
1250 //#endif
1251 
1252     nothrow:
1253 
1254     Symbol* Sl, Sr;             // left, right child
1255     Symbol* Snext;              // next in threaded list
1256     dt_t* Sdt;                  // variables: initializer
1257     int Salignment;             // variables: alignment, 0 or -1 means default alignment
1258 
1259     int Salignsize()            // variables: return alignment
1260     { return Symbol_Salignsize(&this); }
1261 
1262     type* Stype;                // type of Symbol
1263     tym_t ty() const { return Stype.Tty; }
1264 
1265     union                       // variants for different Symbol types
1266     {
1267         enum_t* Senum;          // SCenum
1268 
1269         struct
1270         {
1271              func_t* Sfunc;     // tyfunc
1272              list_t Spath1;     // SCfuncalias member functions: same as Spath
1273                                 // and in same position
1274                                 // SCadl: list of associated functions for ADL lookup
1275         }
1276 
1277         struct                  // SClabel
1278         {
1279             int Slabel;         // TRUE if label was defined
1280             block* Slabelblk_;  // label block
1281         }
1282 
1283         //#define Senumlist Senum->SEenumlist
1284 
1285         version (SCPP)
1286         {
1287             struct               // SClinkage
1288             {
1289                 uint Slinkage;   // tym linkage bits
1290                 uint Smangle;
1291             }
1292         }
1293 
1294         version (HTOD)
1295         {
1296             struct               // SClinkage
1297             {
1298                 uint Slinkage;   // tym linkage bits
1299                 uint Smangle;
1300             }
1301         }
1302 
1303         struct
1304         {
1305             ubyte Sbit;         // SCfield: bit position of start of bit field
1306             ubyte Swidth;       // SCfield: width in bits of bit field
1307             targ_size_t Smemoff; // SCmember,SCfield: offset from start of struct
1308         }
1309 
1310         elem* Svalue;           /* SFLvalue: value of const
1311                                    SFLdtorexp: for objects with destructor,
1312                                    conditional expression to precede dtor call
1313                                  */
1314 
1315         struct_t* Sstruct;      // SCstruct
1316         template_t* Stemplate;  // SCtemplate
1317 
1318         version (SCPP)
1319         {
1320             struct                  // SCnamespace
1321             {
1322                 Symbol* Snameroot;  // the Symbol table for the namespace
1323                 list_t Susing;      // other namespaces from using-directives
1324             }
1325             struct
1326             {
1327                 Symbol* Smemalias;  // SCalias: pointer to Symbol to use instead
1328                                     // (generated by using-declarations and
1329                                     // namespace-alias-definitions)
1330                                     // SCmemalias: pointer to member of base class
1331                                     // to use instead (using-declarations)
1332                 symlist_t Spath;    // SCmemalias: path of classes to get to base
1333                                     // class of which Salias is a member
1334             }
1335             Symbol* Simport ;       // SCextern: if dllimport Symbol, this is the
1336                                     // Symbol it was imported from
1337         }
1338         version (HTOD)
1339         {
1340             struct                  // SCnamespace
1341             {
1342                 Symbol* Snameroot;  // the Symbol table for the namespace
1343                 list_t Susing;      // other namespaces from using-directives
1344             }
1345             struct
1346             {
1347                 Symbol* Smemalias;  // SCalias: pointer to Symbol to use instead
1348                                     // (generated by using-declarations and
1349                                     // namespace-alias-definitions)
1350                                     // SCmemalias: pointer to member of base class
1351                                     // to use instead (using-declarations)
1352                 symlist_t Spath;    // SCmemalias: path of classes to get to base
1353                                     // class of which Salias is a member
1354             }
1355             Symbol* Simport ;       // SCextern: if dllimport Symbol, this is the
1356                                     // Symbol it was imported from
1357         }
1358 
1359         struct                  // SCfastpar, SCshadowreg
1360         {
1361             reg_t Spreg;        // register parameter is passed in
1362             reg_t Spreg2;       // if 2 registers, this is the most significant, else NOREG
1363         }
1364     }
1365 
1366     regm_t Spregm()             // return mask of Spreg and Spreg2
1367     {
1368         return (1 << Spreg) | (Spreg2 == NOREG ? 0 : (1 << Spreg2));
1369     }
1370 
1371 //#if SCPP || MARS
1372     Symbol *Sscope;             // enclosing scope (could be struct tag,
1373                                 // enclosing inline function for statics,
1374                                 // or namespace)
1375 //#endif
1376 
1377     version (SCPP)
1378     {
1379         Symbol *Scover;             // if there is a tag name and a regular name
1380                                     // of the same identifier, Scover is the tag
1381                                     // Scover can be SCstruct, SCenum, SCtemplate
1382                                     // or an SCalias to them.
1383         uint Ssequence;             // sequence number (used for 2 level lookup)
1384                                     // also used as 'parameter number' for SCTtemparg
1385     }
1386     version (HTOD)
1387     {
1388         Symbol *Scover;             // if there is a tag name and a regular name
1389                                     // of the same identifier, Scover is the tag
1390                                     // Scover can be SCstruct, SCenum, SCtemplate
1391                                     // or an SCalias to them.
1392         uint Ssequence;             // sequence number (used for 2 level lookup)
1393                                     // also used as 'parameter number' for SCTtemparg
1394     }
1395     version (MARS)
1396     {
1397         const(char)* prettyIdent;   // the symbol identifier as the user sees it
1398     }
1399 
1400 //#if TARGET_OSX
1401     targ_size_t Slocalgotoffset;
1402 //#endif
1403 
1404     enum_SC Sclass;             // storage class (SCxxxx)
1405     char Sfl;                   // flavor (FLxxxx)
1406     SYMFLGS Sflags;             // flag bits (SFLxxxx)
1407 
1408     vec_t       Srange;         // live range, if any
1409     vec_t       Slvreg;         // when symbol is in register
1410     targ_size_t Ssize;          // tyfunc: size of function
1411     targ_size_t Soffset;        // variables: offset of Symbol in its storage class
1412 
1413     // CPP || OPTIMIZER
1414     SYMIDX Ssymnum;             // Symbol number (index into globsym.tab[])
1415                                 // SCauto,SCparameter,SCtmp,SCregpar,SCregister
1416     // CODGEN
1417     int Sseg;                   // segment index
1418     int Sweight;                // usage count, the higher the number,
1419                                 // the more worthwhile it is to put in
1420                                 // a register
1421     int Sdw_ref_idx;            // !=0 means index of DW.ref.name symbol (Dwarf EH)
1422 
1423     union
1424     {
1425         uint Sxtrnnum;          // SCcomdef,SCextern,SCcomdat: external symbol # (starting from 1)
1426         uint Stypidx;           // SCstruct,SCunion,SCclass,SCenum,SCtypedef: debug info type index
1427         struct
1428         {
1429             ubyte Sreglsw;
1430             ubyte Sregmsw;
1431           regm_t Sregm;         // mask of registers
1432         }                       // SCregister,SCregpar,SCpseudo: register number
1433     }
1434     regm_t      Sregsaved;      // mask of registers not affected by this func
1435 
1436     uint lnoscopestart;         // life time of var
1437     uint lnoscopeend;           // the line after the scope
1438 
1439     /**
1440      * Identifier for this symbol
1441      *
1442      * Note that this is used as a flexible array member.
1443      * When allocating a Symbol, the allocation is for
1444      * `sizeof(Symbol - 1 + strlen(identifier) + "\0".length)`.
1445      */
1446     char[1] Sident;
1447 
1448     int needThis()              // !=0 if symbol needs a 'this' pointer
1449     { return Symbol_needThis(&this); }
1450 
1451     bool Sisdead(bool anyiasm)  // if variable is not referenced
1452     { return Symbol_Sisdead(&this, anyiasm); }
1453 }
1454 
1455 void symbol_debug(const Symbol* s)
1456 {
1457     debug assert(s.id == s.IDsymbol);
1458 }
1459 
1460 int Symbol_Salignsize(Symbol* s);
1461 bool Symbol_Sisdead(const Symbol* s, bool anyInlineAsm);
1462 int Symbol_needThis(const Symbol* s);
1463 bool Symbol_isAffected(const ref Symbol s);
1464 
1465 bool isclassmember(const Symbol* s) { return s.Sscope && s.Sscope.Sclass == SCstruct; }
1466 
1467 // Class, struct or union
1468 
1469 alias Classsym = Symbol;
1470 
1471 // Namespace Symbol
1472 alias Nspacesym = Symbol;
1473 
1474 // Alias for another Symbol
1475 alias Aliassym = Symbol;
1476 
1477 // Function symbol
1478 //alias Funcsym = Symbol;
1479 
1480 // Determine if this Symbol is stored in a COMDAT
1481 //#if MARS
1482 //#define symbol_iscomdat(s)      ((s)->Sclass == SCcomdat ||             \
1483 //        config.flags2 & CFG2comdat && (s)->Sclass == SCinline ||        \
1484 //        config.flags4 & CFG4allcomdat && ((s)->Sclass == SCglobal))
1485 //#else
1486 //#define symbol_iscomdat(s)      ((s)->Sclass == SCcomdat ||             \
1487 //        config.flags2 & CFG2comdat && (s)->Sclass == SCinline ||        \
1488 //        config.flags4 & CFG4allcomdat && ((s)->Sclass == SCglobal || (s)->Sclass == SCstatic))
1489 //#endif
1490 
1491 /* Format the identifier for presentation to the user   */
1492 version (SCPP)
1493 {
1494     const(char)* cpp_prettyident (const Symbol *s);
1495     const(char)* prettyident(const Symbol *s) { return CPP ? cpp_prettyident(s) : &s.Sident[0]; }
1496 }
1497 
1498 version (SPP)
1499 {
1500     const(char)* cpp_prettyident (const Symbol *s);
1501     const(char)* prettyident(const Symbol *s) { return &s.Sident[0]; }
1502 }
1503 
1504 version (HTOD)
1505 {
1506     const(char)* cpp_prettyident (const Symbol *s);
1507     const(char)* prettyident(const Symbol *s) { return &s.Sident[0]; }
1508 }
1509 
1510 version (MARS)
1511     const(char)* prettyident(const Symbol *s) { return &s.Sident[0]; }
1512 
1513 
1514 /**********************************
1515  * Function parameters:
1516  *      Pident          identifier of parameter
1517  *      Ptype           type of argument
1518  *      Pelem           default value for argument
1519  *      Psym            symbol corresponding to Pident when using the
1520  *                      parameter list as a symbol table
1521  * For template-parameter-list:
1522  *      Pident          identifier of parameter
1523  *      Ptype           if NULL, this is a type-parameter
1524  *                      else the type for a parameter-declaration value argument
1525  *      Pelem           default value for value argument
1526  *      Pdeftype        default value for type-parameter
1527  *      Pptpl           template-parameter-list for template-template-parameter
1528  *      Psym            default value for template-template-parameter
1529  * For template-arg-list: (actual arguments)
1530  *      Pident          NULL
1531  *      Ptype           type-name
1532  *      Pelem           expression (either Ptype or Pelem is NULL)
1533  *      Psym            SCtemplate for template-template-argument
1534  */
1535 
1536 alias pflags_t = uint;
1537 enum
1538 {
1539     PFexplicit = 1,       // this template argument was explicit, i.e. in < >
1540 }
1541 
1542 /************************
1543  * Params:
1544  *      f = function symbol
1545  * Returns:
1546  *      exception method for f
1547  */
1548 EHmethod ehmethod(Symbol *f)
1549 {
1550     return f.Sfunc.Fflags3 & Feh_none ? EHmethod.EH_NONE : config.ehmethod;
1551 }
1552 
1553 
1554 struct param_t
1555 {
1556 nothrow:
1557     debug ushort      id;
1558     enum IDparam = 0x7050;
1559 
1560     char* Pident;               // identifier
1561     type* Ptype;                // type of parameter (NULL if not known yet)
1562     elem* Pelem;                // default value
1563     token_t* PelemToken;        // tokens making up default elem
1564     type* Pdeftype;             // Ptype==NULL: default type for type-argument
1565     param_t* Pptpl;             // template-parameter-list for template-template-parameter
1566     Symbol* Psym;
1567     param_t* Pnext;             // next in list
1568     pflags_t Pflags;
1569 
1570     param_t* createTal(param_t* p) // create template-argument-list blank from
1571                                 // template-parameter-list
1572     { return param_t_createTal(&this, p); }
1573 
1574     param_t* search(char* id)   // look for Pident matching id
1575     { return param_t_search(&this, id); }
1576 
1577     int searchn(char* id);      // look for Pident matching id, return index
1578 
1579     uint length()               // number of parameters in list
1580     { return param_t_length(&this); }
1581 
1582     void print()                // print this param_t
1583     { param_t_print(&this); }
1584 
1585     void print_list()           // print this list of param_t's
1586     { param_t_print_list(&this); }
1587 }
1588 
1589 void param_t_print(const param_t* p);
1590 void param_t_print_list(param_t* p);
1591 uint param_t_length(param_t* p);
1592 param_t *param_t_createTal(param_t* p, param_t *ptali);
1593 param_t *param_t_search(param_t* p, char *id);
1594 int param_t_searchn(param_t* p, char *id);
1595 
1596 
1597 void param_debug(const param_t *p)
1598 {
1599     debug assert(p.id == p.IDparam);
1600 }
1601 
1602 /**************************************
1603  * Element types.
1604  * These should be combined with storage classes.
1605  */
1606 
1607 alias FL = int;
1608 enum
1609 {
1610     // Change this, update debug.c too
1611     FLunde,
1612     FLconst,        // numerical constant
1613     FLoper,         // operator node
1614     FLfunc,         // function symbol
1615     FLdata,         // ref to data segment variable
1616     FLreg,          // ref to register variable
1617     FLpseudo,       // pseuodo register variable
1618     FLauto,         // ref to automatic variable
1619     FLfast,         // ref to variable passed as register
1620     FLpara,         // ref to function parameter variable
1621     FLextern,       // ref to external variable
1622     FLcode,         // offset to code
1623     FLblock,        // offset to block
1624     FLudata,        // ref to udata segment variable
1625     FLcs,           // ref to common subexpression number
1626     FLswitch,       // ref to offset of switch data block
1627     FLfltreg,       // ref to floating reg on stack, int contains offset
1628     FLoffset,       // offset (a variation on constant, needed so we
1629                     // can add offsets (different meaning for FLconst))
1630     FLdatseg,       // ref to data segment offset
1631     FLctor,         // constructed object
1632     FLdtor,         // destructed object
1633     FLregsave,      // ref to saved register on stack, int contains offset
1634     FLasm,          // (code) an ASM code
1635 
1636     FLndp,          // saved 8087 register
1637 
1638     // Segmented systems
1639     FLfardata,      // ref to far data segment
1640     FLcsdata,       // ref to code segment variable
1641 
1642     FLlocalsize,    // replaced with # of locals in the stack frame
1643     FLtlsdata,      // thread local storage
1644     FLbprel,        // ref to variable at fixed offset from frame pointer
1645     FLframehandler, // ref to C++ frame handler for NT EH
1646     FLblockoff,     // address of block
1647     FLallocatmp,    // temp for built-in alloca()
1648     FLstack,        // offset from ESP rather than EBP
1649     FLdsymbol,      // it's a Dsymbol
1650 
1651     // Global Offset Table
1652     FLgot,          // global offset table entry outside this object file
1653     FLgotoff,       // global offset table entry inside this object file
1654 
1655     FLfuncarg,      // argument to upcoming function call
1656 
1657     FLMAX
1658 }
1659 
1660 ////////// Srcfiles
1661 
1662 version (MARS)
1663 {
1664 }
1665 else
1666 {
1667 // Collect information about a source file.
1668 alias sfile_flags_t = uint;
1669 enum
1670 {
1671     SFonce    = 1,      // file is to be #include'd only once
1672     SFhx      = 2,      // file is in an HX file and has not been loaded
1673     SFtop     = 4,      // file is a top level source file
1674     SFloaded  = 8,      // read from PH file
1675 }
1676 
1677 private import parser : macro_t;
1678 
1679 struct Sfile
1680 {
1681     debug ushort      id;
1682     enum IDsfile = (('f' << 8) | 's');
1683 
1684     char     *SFname;           // name of file
1685     sfile_flags_t  SFflags;
1686     list_t    SFfillist;        // file pointers of Sfile's that this Sfile is
1687                                 //     dependent on (i.e. they were #include'd).
1688                                 //     Does not include nested #include's
1689     macro_t  *SFmacdefs;        // threaded list of macros #defined by this file
1690     macro_t **SFpmacdefs;       // end of macdefs list
1691     Symbol   *SFsymdefs;        // threaded list of global symbols declared by this file
1692     symlist_t SFcomdefs;        // comdefs defined in PH
1693     symlist_t SFtemp_ft;        // template_ftlist
1694     symlist_t SFtemp_class;     // template_class_list
1695     Symbol   *SFtagsymdefs;     // list of tag names (C only)
1696     char     *SFinc_once_id;    // macro include guard identifier
1697     uint SFhashval;             // hash of file name
1698 }
1699 
1700 void sfile_debug(const Sfile* sf)
1701 {
1702     debug assert(sf.id == Sfile.IDsfile);
1703 }
1704 
1705 // Source files are referred to by a pointer into pfiles[]. This is so that
1706 // when PH files are hydrated, only pfiles[] needs updating. Of course, this
1707 // means that pfiles[] cannot be reallocated to larger numbers, its size is
1708 // fixed at SRCFILES_MAX.
1709 
1710 version (SPP)
1711 {
1712     enum SRCFILES_MAX = (2*512*4);      // no precompiled headers for SPP
1713 }
1714 else
1715 {
1716     enum SRCFILES_MAX = (2*512);
1717 }
1718 
1719 struct Srcfiles
1720 {
1721 //  Sfile *arr;         // array of Sfiles
1722     Sfile **pfiles;     // parallel array of pointers into arr[]
1723     uint dim;       // dimension of array
1724     uint idx;       // # used in array
1725 }
1726 
1727 Sfile* sfile(uint fi)
1728 {
1729     import dmd.backend.global : srcfiles;
1730     return srcfiles.pfiles[fi];
1731 }
1732 
1733 char* srcfiles_name(uint fi) { return sfile(fi).SFname; }
1734 }
1735 
1736 /**************************************************
1737  * This is to support compiling expressions within the context of a function.
1738  */
1739 
1740 struct EEcontext
1741 {
1742     uint EElinnum;              // line number to insert expression
1743     char *EEexpr;               // expression
1744     char *EEtypedef;            // typedef identifier
1745     byte EEpending;             // !=0 means we haven't compiled it yet
1746     byte EEimminent;            // we've installed it in the source text
1747     byte EEcompile;             // we're compiling for the EE expression
1748     byte EEin;                  // we are parsing an EE expression
1749     elem *EEelem;               // compiled version of EEexpr
1750     Symbol *EEfunc;             // function expression is in
1751     code *EEcode;               // generated code
1752 }
1753 
1754 extern __gshared EEcontext eecontext;
1755 
1756 
1757 // Different goals for el_optimize()
1758 alias goal_t = uint;
1759 enum
1760 {
1761     GOALnone        = 0,       // evaluate for side effects only
1762     GOALvalue       = 1,       // evaluate for value
1763     GOALflags       = 2,       // evaluate for flags
1764     GOALagain       = 4,
1765     GOALstruct      = 8,
1766     GOALhandle      = 0x10,    // don't replace handle'd objects
1767     GOALignore_exceptions = 0x20, // ignore floating point exceptions
1768 }
1769 
1770 /* Globals returned by declar() */
1771 struct Declar
1772 {
1773     Classsym *class_sym;
1774     Nspacesym *namespace_sym;
1775     int oper;
1776     bool constructor;
1777     bool destructor;
1778     bool _invariant;
1779     param_t *ptal;
1780     bool explicitSpecialization;
1781     int hasExcSpec;             // has exception specification
1782 }
1783 
1784 extern __gshared Declar gdeclar;
1785 
1786 /**********************************
1787  * Data definitions
1788  *      DTibytes        1..7 bytes
1789  *      DTabytes        offset of bytes of data
1790  *                      a { a data bytes }
1791  *      DTnbytes        bytes of data
1792  *                      a { a data bytes }
1793  *                      a = offset
1794  *      DTazeros        # of 0 bytes
1795  *                      a
1796  *      DTsymsize       same as DTazeros, but the type of the symbol gives
1797  *                      the size
1798  *      DTcommon        # of 0 bytes (in a common block)
1799  *                      a
1800  *      DTxoff          offset from symbol
1801  *                      w a
1802  *                      w = symbol number (pointer for CPP)
1803  *                      a = offset
1804  *      DTcoff          offset into code segment
1805  */
1806 
1807 struct dt_t
1808 {
1809     dt_t *DTnext;                       // next in list
1810     char dt;                            // type (DTxxxx)
1811     ubyte Dty;                          // pointer type
1812     ubyte DTn;                          // DTibytes: number of bytes
1813     union
1814     {
1815         struct                          // DTibytes
1816         {
1817             enum DTibytesMax = (char*).sizeof + uint.sizeof + int.sizeof + targ_size_t.sizeof;
1818             byte[DTibytesMax] DTdata;   // data
1819         }
1820         targ_size_t DTazeros;           // DTazeros,DTcommon,DTsymsize
1821         struct                          // DTabytes
1822         {
1823             byte *DTpbytes;             // pointer to the bytes
1824             uint DTnbytes;              // # of bytes
1825             int DTseg;                  // segment it went into
1826             targ_size_t DTabytes;       // offset of abytes for DTabytes
1827         }
1828         struct                          // DTxoff
1829         {
1830             Symbol *DTsym;              // symbol pointer
1831             targ_size_t DToffset;       // offset from symbol
1832         }
1833     }
1834 }
1835 
1836 enum
1837 {
1838     DT_abytes = 0,
1839     DT_azeros = 1,
1840     DT_xoff   = 2,
1841     DT_nbytes = 3,
1842     DT_common = 4,
1843     DT_coff   = 5,
1844     DT_ibytes = 6,
1845 }
1846 
1847 // An efficient way to clear aligned memory
1848 //#define MEMCLEAR(p,sz)                  \
1849 //    if ((sz) == 10 * sizeof(size_t))    \
1850 //    {                                   \
1851 //        ((size_t *)(p))[0] = 0;         \
1852 //        ((size_t *)(p))[1] = 0;         \
1853 //        ((size_t *)(p))[2] = 0;         \
1854 //        ((size_t *)(p))[3] = 0;         \
1855 //        ((size_t *)(p))[4] = 0;         \
1856 //        ((size_t *)(p))[5] = 0;         \
1857 //        ((size_t *)(p))[6] = 0;         \
1858 //        ((size_t *)(p))[7] = 0;         \
1859 //        ((size_t *)(p))[8] = 0;         \
1860 //        ((size_t *)(p))[9] = 0;         \
1861 //    }                                   \
1862 //    else if ((sz) == 14 * sizeof(size_t))       \
1863 //    {                                   \
1864 //        ((size_t *)(p))[0] = 0;         \
1865 //        ((size_t *)(p))[1] = 0;         \
1866 //        ((size_t *)(p))[2] = 0;         \
1867 //        ((size_t *)(p))[3] = 0;         \
1868 //        ((size_t *)(p))[4] = 0;         \
1869 //        ((size_t *)(p))[5] = 0;         \
1870 //        ((size_t *)(p))[6] = 0;         \
1871 //        ((size_t *)(p))[7] = 0;         \
1872 //        ((size_t *)(p))[8] = 0;         \
1873 //        ((size_t *)(p))[9] = 0;         \
1874 //        ((size_t *)(p))[10] = 0;        \
1875 //        ((size_t *)(p))[11] = 0;        \
1876 //        ((size_t *)(p))[12] = 0;        \
1877 //        ((size_t *)(p))[13] = 0;        \
1878 //    }                                   \
1879 //    else                                \
1880 //    {                                   \
1881 //        /*printf("%s(%d) sz = %d\n",__FILE__,__LINE__,(sz));fflush(stdout);*(char*)0=0;*/  \
1882 //        for (size_t i = 0; i < sz / sizeof(size_t); ++i)        \
1883 //            ((size_t *)(p))[i] = 0;                             \
1884 //    }