1 /**
2  * Compiler implementation of the
3  * $(LINK2 http://www.dlang.org, D programming language).
4  *
5  * Copyright:   Copyright (C) 1985-1998 by Symantec
6  *              Copyright (C) 2000-2021 by The D Language Foundation, All Rights Reserved
7  * Authors:     $(LINK2 http://www.digitalmars.com, Walter Bright)
8  * License:     $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
9  * Source:      $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/backend/cdef.d, backend/_cdef.d)
10  */
11 
12 module dmd.backend.cdef;
13 
14 // Online documentation: https://dlang.org/phobos/dmd_backend_cdef.html
15 
16 import dmd.backend.cc: Classsym, Symbol, param_t, config;
17 import dmd.backend.el;
18 import dmd.backend.ty : I32;
19 
20 import dmd.backend.dlist;
21 
22 extern (C++):
23 @nogc:
24 nothrow:
25 
26 enum VERSION = "9.00.0";        // for banner and imbedding in .OBJ file
27 enum VERSIONHEX = "0x900";      // for __DMC__ macro
28 enum VERSIONINT = 0x900;        // for precompiled headers and DLL version
29 
30 version (SCPP)
31     version = XVERSION;
32 version (SPP)
33     version = XVERSION;
34 version (HTOD)
35     version = XVERSION;
36 version (MARS)
37     version = XVERSION;
38 
39 version (XVERSION)
40 {
41     extern (D) template xversion(string s)
42     {
43         enum xversion = mixin(`{ version (` ~ s ~ `) return true; else return false; }`)();
44     }
45 
46     enum TARGET_LINUX   = xversion!`linux`;
47     enum TARGET_OSX     = xversion!`OSX`;
48     enum TARGET_FREEBSD = xversion!`FreeBSD`;
49     enum TARGET_OPENBSD = xversion!`OpenBSD`;
50     enum TARGET_SOLARIS = xversion!`Solaris`;
51     enum TARGET_WINDOS  = xversion!`Windows`;
52     enum TARGET_DRAGONFLYBSD  = xversion!`DragonFlyBSD`;
53 }
54 
55 
56 //
57 //      Attributes
58 //
59 
60 //      Types of attributes
61 enum
62 {
63     ATTR_LINKMOD    = 1,     // link modifier
64     ATTR_TYPEMOD    = 2,     // basic type modifier
65     ATTR_FUNCINFO   = 4,     // function information
66     ATTR_DATAINFO   = 8,     // data information
67     ATTR_TRANSU     = 0x10,  // transparent union
68     ATTR_IGNORED    = 0x20,  // attribute can be ignored
69     ATTR_WARNING    = 0x40,  // attribute was ignored
70     ATTR_SEGMENT    = 0x80,  // segment secified
71 }
72 
73 //      attribute location in code
74 enum
75 {
76     ALOC_DECSTART   = 1,   // start of declaration
77     ALOC_SYMDEF     = 2,   // symbol defined
78     ALOC_PARAM      = 4,   // follows function parameter
79     ALOC_FUNC       = 8,   // follows function declaration
80 }
81 
82 //#define ATTR_LINK_MODIFIERS (mTYconst|mTYvolatile|mTYcdecl|mTYstdcall)
83 //#define ATTR_CAN_IGNORE(a) (((a) & (ATTR_LINKMOD|ATTR_TYPEMOD|ATTR_FUNCINFO|ATTR_DATAINFO|ATTR_TRANSU)) == 0)
84 //#define LNX_CHECK_ATTRIBUTES(a,x) assert(((a) & ~(x|ATTR_IGNORED|ATTR_WARNING)) == 0)
85 
86 version (_WINDLL)
87     enum SUFFIX = "nd";
88 else version (_WIN64)
89     enum SUFFIX = "a";
90 else version (Win32)
91     enum SUFFIX = "n";
92 else
93     enum SUFFIX = "";
94 
95 // Generate cleanup code
96 enum TERMCODE = 0;
97 
98 // C++ Language Features
99 enum ANGLE_BRACKET_HACK = 0;       // >> means two template arglist closes
100 
101 // C/C++ Language Features
102 enum IMPLIED_PRAGMA_ONCE = 1;       // include guards count as #pragma once
103 enum bool HEADER_LIST = true;
104 
105 // Support generating code for 16 bit memory models
106 version (SCPP)
107     enum SIXTEENBIT = TARGET_WINDOS != 0;
108 else
109     enum SIXTEENBIT = false;
110 
111 /* Set for supporting the FLAT memory model.
112  * This is not quite the same as !SIXTEENBIT, as one could
113  * have near/far with 32 bit code.
114  */
115 version (MARS)
116     enum TARGET_SEGMENTED = false;
117 else
118     enum TARGET_SEGMENTED = TARGET_WINDOS;
119 
120 
121 bool LDOUBLE() { return config.exe == EX_WIN32; }   // support true long doubles
122 
123 
124 // NT structured exception handling
125 //      0: no support
126 //      1: old style
127 //      2: new style
128 enum NTEXCEPTIONS = 2;
129 
130 // For Shared Code Base
131 //#if _WINDLL
132 //#define dbg_printf dll_printf
133 //#else
134 //#define dbg_printf printf
135 //#endif
136 
137 //#ifndef ERRSTREAM
138 //#define ERRSTREAM stdout
139 //#endif
140 //#define err_printf printf
141 //#define err_vprintf vfprintf
142 //#define err_fputc fputc
143 //#define dbg_fputc fputc
144 //#define LF '\n'
145 //#define LF_STR "\n"
146 //#define CR '\r'
147 //#define ANSI        config.ansi_c
148 //#define ANSI_STRICT config.ansi_c
149 //#define ANSI_RELAX  config.ansi_c
150 //#define TRIGRAPHS   ANSI
151 //#define T80x86(x)       x
152 
153 // For Share MEM_ macros - default to mem_xxx package
154 // PH           precompiled header
155 // PARF         parser, life of function
156 // PARC         parser, life of compilation
157 // BEF          back end, function
158 // BEC          back end, compilation
159 
160 //#define MEM_PH_FREE      mem_free
161 //#define MEM_PARF_FREE    mem_free
162 //#define MEM_PARC_FREE    mem_free
163 //#define MEM_BEF_FREE     mem_free
164 //#define MEM_BEC_FREE     mem_free
165 
166 //#define MEM_PH_CALLOC    mem_calloc
167 //#define MEM_PARC_CALLOC  mem_calloc
168 //#define MEM_PARF_CALLOC  mem_calloc
169 //#define MEM_BEF_CALLOC   mem_calloc
170 //#define MEM_BEC_CALLOC   mem_calloc
171 
172 //#define MEM_PH_MALLOC    mem_malloc
173 //#define MEM_PARC_MALLOC  mem_malloc
174 //#define MEM_PARF_MALLOC  mem_malloc
175 //#define MEM_BEF_MALLOC   mem_malloc
176 //#define MEM_BEC_MALLOC   mem_malloc
177 
178 //#define MEM_PH_STRDUP    mem_strdup
179 //#define MEM_PARC_STRDUP  mem_strdup
180 //#define MEM_PARF_STRDUP  mem_strdup
181 //#define MEM_BEF_STRDUP   mem_strdup
182 //#define MEM_BEC_STRDUP   mem_strdup
183 
184 //#define MEM_PH_REALLOC   mem_realloc
185 //#define MEM_PARC_REALLOC mem_realloc
186 //#define MEM_PARF_REALLOC mem_realloc
187 //#define MEM_PERM_REALLOC mem_realloc
188 //#define MEM_BEF_REALLOC  mem_realloc
189 //#define MEM_BEC_REALLOC  mem_realloc
190 
191 //#define MEM_PH_FREEFP    mem_freefp
192 //#define MEM_PARC_FREEFP  mem_freefp
193 //#define MEM_PARF_FREEFP  mem_freefp
194 //#define MEM_BEF_FREEFP   mem_freefp
195 //#define MEM_BEC_FREEFP   mem_freefp
196 
197 
198 // If we can use 386 instruction set (possible in 16 bit code)
199 //#define I386 (config.target_cpu >= TARGET_80386)
200 
201 // If we are generating 32 bit code
202 //#if MARS
203 //#define I16     0               // no 16 bit code for D
204 //#define I32     (NPTRSIZE == 4)
205 //#define I64     (NPTRSIZE == 8) // 1 if generating 64 bit code
206 //#else
207 //#define I16     (NPTRSIZE == 2)
208 //#define I32     (NPTRSIZE == 4)
209 //#define I64     (NPTRSIZE == 8) // 1 if generating 64 bit code
210 //#endif
211 
212 /**********************************
213  * Limits & machine dependent stuff.
214  */
215 
216 /* Define stuff that's different between VAX and IBMPC.
217  * HOSTBYTESWAPPED      TRUE if on the host machine the bytes are
218  *                      swapped (TRUE for 6809, 68000, FALSE for 8088
219  *                      and VAX).
220  */
221 
222 
223 enum EXIT_BREAK = 255;     // aborted compile with ^C
224 
225 /* Take advantage of machines that can store a word, lsb first  */
226 //#if _M_I86              // if Intel processor
227 //#define TOWORD(ptr,val) (*(unsigned short *)(ptr) = (unsigned short)(val))
228 //#define TOLONG(ptr,val) (*(unsigned *)(ptr) = (unsigned)(val))
229 //#else
230 //#define TOWORD(ptr,val) (((ptr)[0] = (unsigned char)(val)),\
231 //                         ((ptr)[1] = (unsigned char)((val) >> 8)))
232 //#define TOLONG(ptr,val) (((ptr)[0] = (unsigned char)(val)),\
233 //                         ((ptr)[1] = (unsigned char)((val) >> 8)),\
234 //                         ((ptr)[2] = (unsigned char)((val) >> 16)),\
235 //                         ((ptr)[3] = (unsigned char)((val) >> 24)))
236 //#endif
237 //
238 //#define TOOFFSET(a,b)   (I32 ? TOLONG(a,b) : TOWORD(a,b))
239 
240 /***************************
241  * Target machine data types as they appear on the host.
242  */
243 
244 import core.stdc.stdint : int64_t, uint64_t;
245 
246 alias targ_char = byte;
247 alias targ_uchar = ubyte;
248 alias targ_schar = byte;
249 alias targ_short = short;
250 alias targ_ushort= ushort;
251 alias targ_long = int;
252 alias targ_ulong = uint;
253 alias targ_llong = int64_t;
254 alias targ_ullong = uint64_t;
255 alias targ_float = float;
256 alias targ_double = double;
257 public import dmd.root.longdouble : targ_ldouble = longdouble;
258 
259 // Extract most significant register from constant
260 int REGSIZE();
261 ulong MSREG(ulong p) { return (REGSIZE == 2) ? p >> 16 : ((targ_llong.sizeof == 8) ? p >> 32 : 0); }
262 
263 alias targ_int = int;
264 alias targ_uns = uint;
265 
266 /* Sizes of base data types in bytes */
267 enum
268 {
269     CHARSIZE       = 1,
270     SHORTSIZE      = 2,
271     WCHARSIZE      = 2,       // 2 for WIN32, 4 for linux/OSX/FreeBSD/OpenBSD/DragonFlyBSD/Solaris
272     LONGSIZE       = 4,
273     LLONGSIZE      = 8,
274     CENTSIZE       = 16,
275     FLOATSIZE      = 4,
276     DOUBLESIZE     = 8,
277     TMAXSIZE       = 16,      // largest size a constant can be
278 }
279 
280 //#define intsize         _tysize[TYint]
281 //#define REGSIZE         _tysize[TYnptr]
282 //@property @nogc nothrow auto NPTRSIZE() { return _tysize[TYnptr]; }
283 //#define FPTRSIZE        _tysize[TYfptr]
284 enum REGMASK = 0xFFFF;
285 
286 // targ_llong is also used to store host pointers, so it should have at least their size
287 
288 // 64 bit support
289 alias targ_ptrdiff_t = int64_t;   // ptrdiff_t for target machine
290 alias targ_size_t = uint64_t;     // size_t for the target machine
291 
292 /* Enable/disable various features
293    (Some features may no longer work the old way when compiled out,
294     I don't test the old ways once the new way is set.)
295  */
296 //#define NEWTEMPMANGLE   (!(config.flags4 & CFG4oldtmangle))     // do new template mangling
297 //#define USEDLLSHELL     _WINDLL
298 bool MFUNC() { return I32 != 0; } // && config.exe == EX_WIN32)       // member functions are TYmfunc
299 enum CV3 = 0;          // 1 means support CV3 debug format
300 
301 /* Object module format
302  */
303 //#ifndef OMFOBJ
304 //#define OMFOBJ          TARGET_WINDOS
305 //#endif
306 enum ELFOBJ = TARGET_LINUX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_DRAGONFLYBSD || TARGET_SOLARIS;
307 enum MACHOBJ = TARGET_OSX;
308 
309 version (XVERSION)
310 {
311     enum SYMDEB_CODEVIEW = TARGET_WINDOS;
312     enum SYMDEB_DWARF = TARGET_LINUX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_DRAGONFLYBSD || TARGET_SOLARIS || TARGET_OSX;
313 }
314 
315 //#define TOOLKIT_H
316 
317 enum
318 {
319     Smodel = 0,        // 64k code, 64k data, or flat model
320     Mmodel = 1,        // large code, 64k data
321     Cmodel = 2,        // 64k code, large data
322     Lmodel = 3,        // large code, large data
323     Vmodel = 4,        // large code, large data, vcm
324 }
325 
326 version (MARS)
327     enum MEMMODELS = 1; // number of memory models
328 else
329     enum MEMMODELS = 5;
330 
331 /* Segments     */
332 enum
333 {
334     CODE      = 1,     // code segment
335     DATA      = 2,     // initialized data
336     CDATA     = 3,     // constant data
337     UDATA     = 4,     // uninitialized data
338     CDATAREL  = 5,     // constant data with relocs
339     UNKNOWN   = -1,    // unknown segment
340     DGROUPIDX = 1,     // group index of DGROUP
341 }
342 
343 enum REGMAX = 29;      // registers are numbered 0..10
344 
345 alias tym_t = uint;    // data type big enough for type masks
346 
347 
348 version (MARS)
349 {
350 }
351 else
352 {
353 version (_WINDLL)
354 {
355 /* We reference the required Windows-1252 encoding of the copyright symbol
356    by escaping its character code (0xA9) rather than directly embedding it in
357    the source text. The character code is invalid in UTF-8, which causes some
358    of our source-code preprocessing tools (e.g. tolf) to choke.
359  */
360     enum COPYRIGHT_SYMBOL = "\xA9";
361     enum COPYRIGHT = "Copyright " ~ COPYRIGHT_SYMBOL ~ " 2001 Digital Mars";
362 }
363 else
364 {
365     debug
366     {
367         enum COPYRIGHT = "Copyright (C) Digital Mars 2000-2019.  All Rights Reserved.
368 Written by Walter Bright
369 *****BETA TEST VERSION*****";
370     }
371     else
372     {
373         version (linux)
374         {
375             enum COPYRIGHT = "Copyright (C) Digital Mars 2000-2019.  All Rights Reserved.
376 Written by Walter Bright, Linux version by Pat Nelson";
377         }
378         else
379         {
380             enum COPYRIGHT = "Copyright (C) Digital Mars 2000-2019.  All Rights Reserved.
381 Written by Walter Bright";
382         }
383     }
384 }
385 }
386 
387 /**********************************
388  * Configuration
389  */
390 
391 /* Linkage type         */
392 enum linkage_t
393 {
394     LINK_C,                     /* C style                              */
395     LINK_CPP,                   /* C++ style                            */
396     LINK_PASCAL,                /* Pascal style                         */
397     LINK_FORTRAN,
398     LINK_SYSCALL,
399     LINK_STDCALL,
400     LINK_D,                     // D code
401     LINK_MAXDIM                 /* array dimension                      */
402 }
403 
404 /**********************************
405  * Exception handling method
406  */
407 
408 enum EHmethod
409 {
410     EH_NONE,                    // no exception handling
411     EH_SEH,                     // SEH __try, __except, __finally only
412     EH_WIN32,                   // Win32 SEH
413     EH_WIN64,                   // Win64 SEH (not supported yet)
414     EH_DM,                      // Digital Mars method
415     EH_DWARF,                   // Dwarf method
416 }
417 
418 // CPU target
419 alias cpu_target_t = byte;
420 enum
421 {
422     TARGET_8086             = 0,
423     TARGET_80286            = 2,
424     TARGET_80386            = 3,
425     TARGET_80486            = 4,
426     TARGET_Pentium          = 5,
427     TARGET_PentiumMMX       = 6,
428     TARGET_PentiumPro       = 7,
429     TARGET_PentiumII        = 8,
430 }
431 
432 // Symbolic debug info
433 alias symbolic_debug_t = byte;
434 enum
435 {
436     CVNONE    = 0,           // No symbolic info
437     CVOLD     = 1,           // Codeview 1 symbolic info
438     CV4       = 2,           // Codeview 4 symbolic info
439     CVSYM     = 3,           // Symantec format
440     CVTDB     = 4,           // Symantec format written to file
441     CVDWARF_C = 5,           // Dwarf in C format
442     CVDWARF_D = 6,           // Dwarf in D format
443     CVSTABS   = 7,           // Elf Stabs in C format
444     CV8       = 8,           // Codeview 8 symbolic info
445 }
446 
447 // Windows code gen flags
448 alias windows_flags_t = uint;
449 enum
450 {
451     WFwindows    = 1,      // generating code for Windows app or DLL
452     WFdll        = 2,      // generating code for Windows DLL
453     WFincbp      = 4,      // mark far stack frame with inc BP / dec BP
454     WFloadds     = 8,      // assume __loadds for all functions
455     WFexpdef     = 0x10,   // generate export definition records for
456                            // exported functions
457     WFss         = 0x20,   // load DS from SS
458     WFreduced    = 0x40,   // skip DS load for non-exported functions
459     WFdgroup     = 0x80,   // load DS from DGROUP
460     WFexport     = 0x100,  // assume __export for all far functions
461     WFds         = 0x200,  // load DS from DS
462     WFmacros     = 0x400,  // define predefined windows macros
463     WFssneds     = 0x800,  // SS != DS
464     WFthunk      = 0x1000, // use fixups instead of direct ref to CS
465     WFsaveds     = 0x2000, // use push/pop DS for far functions
466     WFdsnedgroup = 0x4000, // DS != DGROUP
467     WFexe        = 0x8000, // generating code for Windows EXE
468 }
469 
470 // Object file format
471 alias objfmt_t = uint;
472 enum
473 {
474     OBJ_OMF         = 1,
475     OBJ_MSCOFF      = 2,
476     OBJ_ELF         = 4,
477     OBJ_MACH        = 8,
478 }
479 
480 // Executable file format
481 alias exefmt_t = uint;
482 enum
483 {
484     EX_DOSX         = 1,       // DOSX 386 program
485     EX_ZPM          = 2,       // ZPM 286 program
486     EX_RATIONAL     = 4,       // RATIONAL 286 program
487     EX_PHARLAP      = 8,       // PHARLAP 386 program
488     EX_COM          = 0x10,    // MSDOS .COM program
489     EX_OS2          = 0x40,    // OS/2 2.0 32 bit program
490     EX_OS1          = 0x80,    // OS/2 1.x 16 bit program
491     EX_WIN32        = 0x100,
492     EX_MZ           = 0x200,   // MSDOS real mode program
493     EX_LINUX        = 0x2000,
494     EX_WIN64        = 0x4000,  // AMD64 and Windows (64 bit mode)
495     EX_LINUX64      = 0x8000,  // AMD64 and Linux (64 bit mode)
496     EX_OSX          = 0x10000,
497     EX_OSX64        = 0x20000,
498     EX_FREEBSD      = 0x40000,
499     EX_FREEBSD64    = 0x80000,
500     EX_SOLARIS      = 0x100000,
501     EX_SOLARIS64    = 0x200000,
502     EX_OPENBSD      = 0x400000,
503     EX_OPENBSD64    = 0x800000,
504     EX_DRAGONFLYBSD64 = 0x1000000,
505 }
506 
507 // All of them
508 enum exefmt_t EX_all =
509     EX_DOSX      |
510     EX_ZPM       |
511     EX_RATIONAL  |
512     EX_PHARLAP   |
513     EX_COM       |
514     EX_OS2       |
515     EX_OS1       |
516     EX_WIN32     |
517     EX_MZ        |
518     EX_LINUX     |
519     EX_WIN64     |
520     EX_LINUX64   |
521     EX_OSX       |
522     EX_OSX64     |
523     EX_FREEBSD   |
524     EX_FREEBSD64 |
525     EX_SOLARIS   |
526     EX_SOLARIS64 |
527     EX_OPENBSD   |
528     EX_OPENBSD64 |
529     EX_DRAGONFLYBSD64;
530 
531 // All segmented memory models
532 enum exefmt_t EX_segmented = EX_DOSX | EX_ZPM | EX_RATIONAL | EX_PHARLAP |
533                         EX_COM | EX_OS1 | EX_MZ;
534 
535 // All flat memory models (no segment registers)
536 enum exefmt_t EX_flat = EX_OS2 | EX_WIN32 | EX_WIN64 | EX_posix;
537 
538 // All DOS executable types
539 enum exefmt_t EX_dos =  EX_DOSX | EX_ZPM | EX_RATIONAL | EX_PHARLAP |
540                          EX_COM | EX_MZ;
541 
542 // Windows and DOS executable types
543 enum exefmt_t EX_windos = EX_dos | EX_OS1 | EX_OS2 | EX_WIN32 | EX_WIN64;
544 
545 // All POSIX systems
546 enum exefmt_t EX_posix = EX_LINUX   | EX_LINUX64   |
547                          EX_OSX     | EX_OSX64     |
548                          EX_FREEBSD | EX_FREEBSD64 |
549                          EX_SOLARIS | EX_SOLARIS64 |
550                          EX_OPENBSD | EX_OPENBSD64 |
551                          EX_DRAGONFLYBSD64;
552 
553 // All 16 bit targets
554 enum exefmt_t EX_16 = EX_ZPM | EX_RATIONAL | EX_COM | EX_OS1 | EX_MZ;
555 
556 // All 32 bit targets
557 enum exefmt_t EX_32 = EX_DOSX | EX_OS2 | EX_PHARLAP |
558                 EX_WIN32   |
559                 EX_LINUX   |
560                 EX_OSX     |
561                 EX_FREEBSD |
562                 EX_SOLARIS |
563                 EX_OPENBSD;
564 
565 // All 64 bit targets
566 enum exefmt_t EX_64 =
567                 EX_WIN64     |
568                 EX_LINUX64   |
569                 EX_OSX64     |
570                 EX_FREEBSD64 |
571                 EX_SOLARIS64 |
572                 EX_OPENBSD64 |
573                 EX_DRAGONFLYBSD64;
574 
575 // Constraints
576 static assert(EX_all == (EX_segmented ^ EX_flat));
577 static assert(EX_all == (EX_16 ^ EX_32 ^ EX_64));
578 static assert(EX_all == (EX_windos ^ EX_posix));
579 
580 alias config_flags_t = uint;
581 enum
582 {
583     CFGuchar        = 1,       // chars are unsigned
584     CFGsegs         = 2,       // new code seg for each far func
585     CFGtrace        = 4,       // output trace functions
586     CFGglobal       = 8,       // make all static functions global
587     CFGstack        = 0x10,    // add stack overflow checking
588     CFGalwaysframe  = 0x20,    // always generate stack frame
589     CFGnoebp        = 0x40,    // do not use EBP as general purpose register
590     CFGromable      = 0x80,    // put switch tables in code segment
591     CFGeasyomf      = 0x100,   // generate Pharlap Easy-OMF format
592     CFGfarvtbls     = 0x200,   // store vtables in far segments
593     CFGnoinlines    = 0x400,   // do not inline functions
594     CFGnowarning    = 0x800,   // disable warnings
595 }
596 
597 alias config_flags2_t = uint;
598 enum
599 {
600     CFG2comdat      = 1,       // use initialized common blocks
601     CFG2nodeflib    = 2,       // no default library imbedded in OBJ file
602     CFG2browse      = 4,       // generate browse records
603     CFG2dyntyping   = 8,       // generate dynamic typing information
604     CFG2fulltypes   = 0x10,    // don't optimize CV4 class info
605     CFG2warniserr   = 0x20,    // treat warnings as errors
606     CFG2phauto      = 0x40,    // automatic precompiled headers
607     CFG2phuse       = 0x80,    // use precompiled headers
608     CFG2phgen       = 0x100,   // generate precompiled header
609     CFG2once        = 0x200,   // only include header files once
610     CFG2hdrdebug    = 0x400,   // generate debug info for header
611     CFG2phautoy     = 0x800,   // fast build precompiled headers
612     CFG2noobj       = 0x1000,  // we are not generating a .OBJ file
613     CFG2noerrmax    = 0x2000,  // no error count maximum
614     CFG2expand      = 0x4000,  // expanded output to list file
615     CFG2stomp       = 0x8000,  // enable stack stomping code
616     CFG2gms         = 0x10000, // optimize debug symbols for microsoft debuggers
617 }
618 
619 alias config_flags3_t = uint;
620 enum
621 {
622     CFG3ju          = 1,       // char == unsigned char
623     CFG3eh          = 2,       // generate exception handling stuff
624     CFG3strcod      = 4,       // strings are placed in code segment
625     CFG3eseqds      = 8,       // ES == DS at all times
626     CFG3ptrchk      = 0x10,    // generate pointer validation code
627     CFG3strictproto = 0x20,    // strict prototyping
628     CFG3autoproto   = 0x40,    // auto prototyping
629     CFG3rtti        = 0x80,    // add RTTI support
630     CFG3relax       = 0x100,   // relaxed type checking (C only)
631     CFG3cpp         = 0x200,   // C++ compile
632     CFG3igninc      = 0x400,   // ignore standard include directory
633     CFG3mars        = 0x800,   // use mars libs and headers
634     CFG3nofar       = 0x1000,  // ignore __far and __huge keywords
635     CFG3noline      = 0x2000,  // do not output #line directives
636     CFG3comment     = 0x4000,  // leave comments in preprocessed output
637     CFG3cppcomment  = 0x8000,  // allow C++ style comments
638     CFG3wkfloat     = 0x10000, // make floating point references weak externs
639     CFG3digraphs    = 0x20000, // support ANSI C++ digraphs
640     CFG3semirelax   = 0x40000, // moderate relaxed type checking (non-Windows targets)
641     CFG3pic         = 0x80000, // position independent code
642     CFG3pie         = 0x10_0000, // position independent executable (CFG3pic also set)
643 }
644 
645 alias config_flags4_t = uint;
646 enum
647 {
648     CFG4speed            = 1,          // optimized for speed
649     CFG4space            = 2,          // optimized for space
650     CFG4allcomdat        = 4,          // place all functions in COMDATs
651     CFG4fastfloat        = 8,          // fast floating point (-ff)
652     CFG4fdivcall         = 0x10,       // make function call for FDIV opcodes
653     CFG4tempinst         = 0x20,       // instantiate templates for undefined functions
654     CFG4oldstdmangle     = 0x40,       // do stdcall mangling without @
655     CFG4pascal           = 0x80,       // default to pascal linkage
656     CFG4stdcall          = 0x100,      // default to std calling convention
657     CFG4cacheph          = 0x200,      // cache precompiled headers in memory
658     CFG4alternate        = 0x400,      // if alternate digraph tokens
659     CFG4bool             = 0x800,      // support 'bool' as basic type
660     CFG4wchar_t          = 0x1000,     // support 'wchar_t' as basic type
661     CFG4notempexp        = 0x2000,     // no instantiation of template functions
662     CFG4anew             = 0x4000,     // allow operator new[] and delete[] overloading
663     CFG4oldtmangle       = 0x8000,     // use old template name mangling
664     CFG4dllrtl           = 0x10000,    // link with DLL RTL
665     CFG4noemptybaseopt   = 0x20000,    // turn off empty base class optimization
666     CFG4nowchar_t        = 0x40000,    // use unsigned short name mangling for wchar_t
667     CFG4forscope         = 0x80000,    // new C++ for scoping rules
668     CFG4warnccast        = 0x100000,   // warn about C style casts
669     CFG4adl              = 0x200000,   // argument dependent lookup
670     CFG4enumoverload     = 0x400000,   // enum overloading
671     CFG4implicitfromvoid = 0x800000,   // allow implicit cast from void* to T*
672     CFG4dependent        = 0x1000000,  // dependent / non-dependent lookup
673     CFG4wchar_is_long    = 0x2000000,  // wchar_t is 4 bytes
674     CFG4underscore       = 0x4000000,  // prepend _ for C mangling
675 }
676 
677 enum config_flags4_t CFG4optimized  = CFG4speed | CFG4space;
678 enum config_flags4_t CFG4stackalign = CFG4speed;       // align stack to 8 bytes
679 
680 alias config_flags5_t = uint;
681 enum
682 {
683     CFG5debug       = 1,      // compile in __debug code
684     CFG5in          = 2,      // compile in __in code
685     CFG5out         = 4,      // compile in __out code
686     CFG5invariant   = 8,      // compile in __invariant code
687 }
688 
689 /* CFGX: flags ignored in precompiled headers
690  * CFGY: flags copied from precompiled headers into current config
691  */
692 enum config_flags_t CFGX   = CFGnowarning;
693 enum config_flags2_t CFGX2 = CFG2warniserr | CFG2phuse | CFG2phgen | CFG2phauto |
694                              CFG2once | CFG2hdrdebug | CFG2noobj | CFG2noerrmax |
695                              CFG2expand | CFG2nodeflib | CFG2stomp | CFG2gms;
696 enum config_flags3_t CFGX3 = CFG3strcod | CFG3ptrchk;
697 enum config_flags4_t CFGX4 = CFG4optimized | CFG4fastfloat | CFG4fdivcall |
698                              CFG4tempinst | CFG4cacheph | CFG4notempexp |
699                              CFG4stackalign | CFG4dependent;
700 
701 enum config_flags4_t CFGY4 = CFG4nowchar_t | CFG4noemptybaseopt | CFG4adl |
702                              CFG4enumoverload | CFG4implicitfromvoid |
703                              CFG4wchar_is_long | CFG4underscore;
704 
705 // Configuration flags for HTOD executable
706 alias htod_flags_t = uint;
707 enum
708 {
709     HTODFinclude    = 1,      // -hi drill down into #include files
710     HTODFsysinclude = 2,      // -hs drill down into system #include files
711     HTODFtypedef    = 4,      // -ht drill down into typedefs
712     HTODFcdecl      = 8,      // -hc skip C declarations as comments
713 }
714 
715 // This part of the configuration is saved in the precompiled header for use
716 // in comparing to make sure it hasn't changed.
717 
718 struct Config
719 {
720     char language;              // 'C' = C, 'D' = C++
721     string _version;            /// Compiler version
722     char[3] exetype;            // distinguish exe types so PH
723                                 // files are distinct (= SUFFIX)
724 
725     cpu_target_t target_cpu;       // instruction selection
726     cpu_target_t target_scheduler; // instruction scheduling (normally same as selection)
727 
728     short versionint;           // intermediate file version (= VERSIONINT)
729     int defstructalign;         // struct alignment specified by command line
730     short hxversion;            // HX version number
731     symbolic_debug_t fulltypes; // format of symbolic debug info
732 
733     windows_flags_t wflags;     // flags for Windows code generation
734 
735     bool fpxmmregs;             // use XMM registers for floating point
736     ubyte avx;                  // use AVX instruction set (0, 1, 2)
737     ubyte inline8087;           /* 0:   emulator
738                                    1:   IEEE 754 inline 8087 code
739                                    2:   fast inline 8087 code
740                                  */
741     short memmodel;             // 0:S,X,N,F, 1:M, 2:C, 3:L, 4:V
742     objfmt_t objfmt;            // target object format
743     exefmt_t exe;               // target operating system
744 
745     config_flags_t  flags;
746     config_flags2_t flags2;
747     config_flags3_t flags3;
748     config_flags4_t flags4;
749     config_flags5_t flags5;
750 
751     htod_flags_t htodFlags;     // configuration for htod
752     ubyte ansi_c;               // strict ANSI C
753                                 // 89 for ANSI C89, 99 for ANSI C99
754     ubyte asian_char;           // 0: normal, 1: Japanese, 2: Chinese
755                                 // and Taiwanese, 3: Korean
756     uint threshold;             // data larger than threshold is assumed to
757                                 // be far (16 bit models only)
758                                 // if threshold == THRESHMAX, all data defaults
759                                 // to near
760     linkage_t linkage;          // default function call linkage
761     EHmethod ehmethod;          // exception handling method
762     bool useModuleInfo;         // implement ModuleInfo
763     bool useTypeInfo;           // implement TypeInfo
764     bool useExceptions;         // implement exception handling
765     ubyte dwarf;                // DWARF version
766 }
767 
768 enum THRESHMAX = 0xFFFF;
769 
770 // Language for error messages
771 enum LANG
772 {
773     english,
774     german,
775     french,
776     japanese,
777 }
778 
779 // Configuration that is not saved in precompiled header
780 
781 struct Configv
782 {
783     ubyte addlinenumbers;       // put line number info in .OBJ file
784     ubyte verbose;              // 0: compile quietly (no messages)
785                                 // 1: show progress to DLL (default)
786                                 // 2: full verbosity
787     char* csegname;             // code segment name
788     char* deflibname;           // default library name
789     LANG language;              // message language
790     int errmax;                 // max error count
791 }
792 
793 alias reg_t = ubyte;            // register number
794 alias regm_t = uint;            // Register mask type
795 struct immed_t
796 {
797     targ_size_t[REGMAX] value;  // immediate values in registers
798     regm_t mval;                // Mask of which values in regimmed.value[] are valid
799 }
800 
801 
802 struct cse_t
803 {
804     elem*[REGMAX] value;        // expression values in registers
805     regm_t mval;                // mask of which values in value[] are valid
806     regm_t mops;                // subset of mval that contain common subs that need
807                                 // to be stored in csextab[] if they are destroyed
808 }
809 
810 struct con_t
811 {
812     cse_t cse;                  // CSEs in registers
813     immed_t immed;              // immediate values in registers
814     regm_t mvar;                // mask of register variables
815     regm_t mpvar;               // mask of SCfastpar, SCshadowreg register variables
816     regm_t indexregs;           // !=0 if more than 1 uncommitted index register
817     regm_t used;                // mask of registers used
818     regm_t params;              // mask of registers which still contain register
819                                 // function parameters
820 }
821 
822 /*********************************
823  * Bootstrap complex types.
824  */
825 
826 import dmd.backend.bcomplex;
827 
828 /*********************************
829  * Union of all data types. Storage allocated must be the right
830  * size of the data on the TARGET, not the host.
831  */
832 
833 struct Cent
834 {
835     targ_ullong lsw;
836     targ_ullong msw;
837 }
838 
839 union eve
840 {
841         targ_char       Vchar;
842         targ_schar      Vschar;
843         targ_uchar      Vuchar;
844         targ_short      Vshort;
845         targ_ushort     Vushort;
846         targ_int        Vint;
847         targ_uns        Vuns;
848         targ_long       Vlong;
849         targ_ulong      Vulong;
850         targ_llong      Vllong;
851         targ_ullong     Vullong;
852         Cent            Vcent;
853         targ_float      Vfloat;
854         targ_double     Vdouble;
855         targ_ldouble    Vldouble;
856         Complex_f       Vcfloat;   // 2x float
857         Complex_d       Vcdouble;  // 2x double
858         Complex_ld      Vcldouble; // 2x long double
859         targ_size_t     Vpointer;
860         targ_ptrdiff_t  Vptrdiff;
861         targ_uchar      Vreg;   // register number for OPreg elems
862 
863         // 16 byte vector types
864         targ_float[4]   Vfloat4;   // float[4]
865         targ_double[2]  Vdouble2;  // double[2]
866         targ_schar[16]  Vschar16;  // byte[16]
867         targ_uchar[16]  Vuchar16;  // ubyte[16]
868         targ_short[8]   Vshort8;   // short[8]
869         targ_ushort[8]  Vushort8;  // ushort[8]
870         targ_long[4]    Vlong4;    // int[4]
871         targ_ulong[4]   Vulong4;   // uint[4]
872         targ_llong[2]   Vllong2;   // long[2]
873         targ_ullong[2]  Vullong2;  // ulong[2]
874 
875         // 32 byte vector types
876         targ_float[8]   Vfloat8;   // float[8]
877         targ_double[4]  Vdouble4;  // double[4]
878         targ_schar[32]  Vschar32;  // byte[32]
879         targ_uchar[32]  Vuchar32;  // ubyte[32]
880         targ_short[16]  Vshort16;  // short[16]
881         targ_ushort[16] Vushort16; // ushort[16]
882         targ_long[8]    Vlong8;    // int[8]
883         targ_ulong[8]   Vulong8;   // uint[8]
884         targ_llong[4]   Vllong4;   // long[4]
885         targ_ullong[4]  Vullong4;  // ulong[4]
886 
887         struct                  // 48 bit 386 far pointer
888         {   targ_long   Voff;
889             targ_ushort Vseg;
890         }
891         struct
892         {
893             targ_size_t Voffset;// offset from symbol
894             Symbol *Vsym;       // pointer to symbol table
895             union
896             {
897                 param_t* Vtal;  // template-argument-list for SCfunctempl,
898                                 // used only to transmit it to cpp_overload()
899                 LIST* Erd;      // OPvar: reaching definitions
900             }
901         }
902         struct
903         {
904             targ_size_t Voffset2;// member pointer offset
905             Classsym* Vsym2;    // struct tag
906             elem* ethis;        // OPrelconst: 'this' for member pointer
907         }
908         struct
909         {
910             targ_size_t Voffset3;// offset from string
911             char* Vstring;      // pointer to string (OPstring or OPasm)
912             size_t Vstrlen;     // length of string
913         }
914         struct
915         {
916             elem* E1;           // left child for unary & binary nodes
917             elem* E2;           // right child for binary nodes
918             Symbol* Edtor;      // OPctor: destructor
919         }
920         struct
921         {
922             elem* Eleft2;       // left child for OPddtor
923             void* Edecl;        // VarDeclaration being constructed
924         }                       // OPdctor,OPddtor
925 }                               // variants for each type of elem
926 
927 // Symbols
928 
929 //#ifdef DEBUG
930 //#define IDSYMBOL        IDsymbol,
931 //#else
932 //#define IDSYMBOL
933 //#endif
934 
935 alias SYMFLGS = uint;
936 
937 
938 /**********************************
939  * Storage classes
940  */
941 
942 alias SC = int;
943 enum
944 {
945     SCunde,           // undefined
946     SCauto,           // automatic (stack)
947     SCstatic,         // statically allocated
948     SCthread,         // thread local
949     SCextern,         // external
950     SCregister,       // registered variable
951     SCpseudo,         // pseudo register variable
952     SCglobal,         // top level global definition
953     SCcomdat,         // initialized common block
954     SCparameter,      // function parameter
955     SCregpar,         // function register parameter
956     SCfastpar,        // function parameter passed in register
957     SCshadowreg,      // function parameter passed in register, shadowed on stack
958     SCtypedef,        // type definition
959     SCexplicit,       // explicit
960     SCmutable,        // mutable
961     SClabel,          // goto label
962     SCstruct,         // struct/class/union tag name
963     SCenum,           // enum tag name
964     SCfield,          // bit field of struct or union
965     SCconst,          // constant integer
966     SCmember,         // member of struct or union
967     SCanon,           // member of anonymous union
968     SCinline,         // for inline functions
969     SCsinline,        // for static inline functions
970     SCeinline,        // for extern inline functions
971     SCoverload,       // for overloaded function names
972     SCfriend,         // friend of a class
973     SCvirtual,        // virtual function
974     SClocstat,        // static, but local to a function
975     SCtemplate,       // class template
976     SCfunctempl,      // function template
977     SCftexpspec,      // function template explicit specialization
978     SClinkage,        // function linkage symbol
979     SCpublic,         // generate a pubdef for this
980     SCcomdef,         // uninitialized common block
981     SCbprel,          // variable at fixed offset from frame pointer
982     SCnamespace,      // namespace
983     SCalias,          // alias to another symbol
984     SCfuncalias,      // alias to another function symbol
985     SCmemalias,       // alias to base class member
986     SCstack,          // offset from stack pointer (not frame pointer)
987     SCadl,            // list of ADL symbols for overloading
988     SCMAX
989 }
990 
991 int ClassInline(int c) { return c == SCinline || c == SCsinline || c == SCeinline; }
992 int SymInline(Symbol* s) { return ClassInline(s.Sclass); }
993