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