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