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