1 /**
2  * Compiler implementation of the
3  * $(LINK2 http://www.dlang.org, D programming language).
4  *
5  * Copyright:   Copyright (C) 1985-1998 by Symantec
6  *              Copyright (C) 2000-2020 by The D Language Foundation, All Rights Reserved
7  * Authors:     $(LINK2 http://www.digitalmars.com, Walter Bright)
8  * License:     $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
9  * Source:      $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/backend/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 version (SCPP)
288 {
289     // No 64 bit support yet
290     alias targ_ptrdiff_t = targ_int;  // ptrdiff_t for target machine
291     alias targ_size_t = targ_uns;     // size_t for the target machine
292 }
293 else version (SPP)
294 {
295     alias targ_ptrdiff_t = targ_int;  // ptrdiff_t for target machine
296     alias targ_size_t = targ_uns;     // size_t for the target machine
297 }
298 else version (HTOD)
299 {
300     alias targ_ptrdiff_t = targ_int;  // ptrdiff_t for target machine
301     alias targ_size_t = targ_uns;     // size_t for the target machine
302 }
303 else
304 {
305     // Support 64 bit targets
306     alias targ_ptrdiff_t = int64_t;  // ptrdiff_t for target machine
307     alias targ_size_t = uint64_t;    // size_t for the target machine
308 }
309 
310 /* Enable/disable various features
311    (Some features may no longer work the old way when compiled out,
312     I don't test the old ways once the new way is set.)
313  */
314 //#define NEWTEMPMANGLE   (!(config.flags4 & CFG4oldtmangle))     // do new template mangling
315 //#define USEDLLSHELL     _WINDLL
316 bool MFUNC() { return I32 != 0; } // && config.exe == EX_WIN32)       // member functions are TYmfunc
317 enum CV3 = 0;          // 1 means support CV3 debug format
318 
319 /* Object module format
320  */
321 //#ifndef OMFOBJ
322 //#define OMFOBJ          TARGET_WINDOS
323 //#endif
324 enum ELFOBJ = TARGET_LINUX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_DRAGONFLYBSD || TARGET_SOLARIS;
325 enum MACHOBJ = TARGET_OSX;
326 
327 version (XVERSION)
328 {
329     enum SYMDEB_CODEVIEW = TARGET_WINDOS;
330     enum SYMDEB_DWARF = TARGET_LINUX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_DRAGONFLYBSD || TARGET_SOLARIS || TARGET_OSX;
331 }
332 
333 //#define TOOLKIT_H
334 
335 enum
336 {
337     Smodel = 0,        // 64k code, 64k data, or flat model
338     Mmodel = 1,        // large code, 64k data
339     Cmodel = 2,        // 64k code, large data
340     Lmodel = 3,        // large code, large data
341     Vmodel = 4,        // large code, large data, vcm
342 }
343 
344 version (MARS)
345     enum MEMMODELS = 1; // number of memory models
346 else
347     enum MEMMODELS = 5;
348 
349 /* Segments     */
350 enum
351 {
352     CODE      = 1,     // code segment
353     DATA      = 2,     // initialized data
354     CDATA     = 3,     // constant data
355     UDATA     = 4,     // uninitialized data
356     CDATAREL  = 5,     // constant data with relocs
357     UNKNOWN   = -1,    // unknown segment
358     DGROUPIDX = 1,     // group index of DGROUP
359 }
360 
361 enum REGMAX = 29;      // registers are numbered 0..10
362 
363 alias tym_t = uint;    // data type big enough for type masks
364 alias SYMIDX = int;    // symbol table index
365 
366 
367 version (MARS)
368 {
369 }
370 else
371 {
372 version (_WINDLL)
373 {
374 /* We reference the required Windows-1252 encoding of the copyright symbol
375    by escaping its character code (0xA9) rather than directly embedding it in
376    the source text. The character code is invalid in UTF-8, which causes some
377    of our source-code preprocessing tools (e.g. tolf) to choke.
378  */
379     enum COPYRIGHT_SYMBOL = "\xA9";
380     enum COPYRIGHT = "Copyright " ~ COPYRIGHT_SYMBOL ~ " 2001 Digital Mars";
381 }
382 else
383 {
384     debug
385     {
386         enum COPYRIGHT = "Copyright (C) Digital Mars 2000-2019.  All Rights Reserved.
387 Written by Walter Bright
388 *****BETA TEST VERSION*****";
389     }
390     else
391     {
392         version (linux)
393         {
394             enum COPYRIGHT = "Copyright (C) Digital Mars 2000-2019.  All Rights Reserved.
395 Written by Walter Bright, Linux version by Pat Nelson";
396         }
397         else
398         {
399             enum COPYRIGHT = "Copyright (C) Digital Mars 2000-2019.  All Rights Reserved.
400 Written by Walter Bright";
401         }
402     }
403 }
404 }
405 
406 /**********************************
407  * Configuration
408  */
409 
410 /* Linkage type         */
411 enum linkage_t
412 {
413     LINK_C,                     /* C style                              */
414     LINK_CPP,                   /* C++ style                            */
415     LINK_PASCAL,                /* Pascal style                         */
416     LINK_FORTRAN,
417     LINK_SYSCALL,
418     LINK_STDCALL,
419     LINK_D,                     // D code
420     LINK_MAXDIM                 /* array dimension                      */
421 }
422 
423 /**********************************
424  * Exception handling method
425  */
426 
427 enum EHmethod
428 {
429     EH_NONE,                    // no exception handling
430     EH_SEH,                     // SEH __try, __except, __finally only
431     EH_WIN32,                   // Win32 SEH
432     EH_WIN64,                   // Win64 SEH (not supported yet)
433     EH_DM,                      // Digital Mars method
434     EH_DWARF,                   // Dwarf method
435 }
436 
437 // CPU target
438 alias cpu_target_t = byte;
439 enum
440 {
441     TARGET_8086             = 0,
442     TARGET_80286            = 2,
443     TARGET_80386            = 3,
444     TARGET_80486            = 4,
445     TARGET_Pentium          = 5,
446     TARGET_PentiumMMX       = 6,
447     TARGET_PentiumPro       = 7,
448     TARGET_PentiumII        = 8,
449 }
450 
451 // Symbolic debug info
452 alias symbolic_debug_t = byte;
453 enum
454 {
455     CVNONE    = 0,           // No symbolic info
456     CVOLD     = 1,           // Codeview 1 symbolic info
457     CV4       = 2,           // Codeview 4 symbolic info
458     CVSYM     = 3,           // Symantec format
459     CVTDB     = 4,           // Symantec format written to file
460     CVDWARF_C = 5,           // Dwarf in C format
461     CVDWARF_D = 6,           // Dwarf in D format
462     CVSTABS   = 7,           // Elf Stabs in C format
463     CV8       = 8,           // Codeview 8 symbolic info
464 }
465 
466 // Windows code gen flags
467 alias windows_flags_t = uint;
468 enum
469 {
470     WFwindows    = 1,      // generating code for Windows app or DLL
471     WFdll        = 2,      // generating code for Windows DLL
472     WFincbp      = 4,      // mark far stack frame with inc BP / dec BP
473     WFloadds     = 8,      // assume __loadds for all functions
474     WFexpdef     = 0x10,   // generate export definition records for
475                            // exported functions
476     WFss         = 0x20,   // load DS from SS
477     WFreduced    = 0x40,   // skip DS load for non-exported functions
478     WFdgroup     = 0x80,   // load DS from DGROUP
479     WFexport     = 0x100,  // assume __export for all far functions
480     WFds         = 0x200,  // load DS from DS
481     WFmacros     = 0x400,  // define predefined windows macros
482     WFssneds     = 0x800,  // SS != DS
483     WFthunk      = 0x1000, // use fixups instead of direct ref to CS
484     WFsaveds     = 0x2000, // use push/pop DS for far functions
485     WFdsnedgroup = 0x4000, // DS != DGROUP
486     WFexe        = 0x8000, // generating code for Windows EXE
487 }
488 
489 // Object file format
490 alias objfmt_t = uint;
491 enum
492 {
493     OBJ_OMF         = 1,
494     OBJ_MSCOFF      = 2,
495     OBJ_ELF         = 4,
496     OBJ_MACH        = 8,
497 }
498 
499 // Executable file format
500 alias exefmt_t = uint;
501 enum
502 {
503     EX_DOSX         = 1,       // DOSX 386 program
504     EX_ZPM          = 2,       // ZPM 286 program
505     EX_RATIONAL     = 4,       // RATIONAL 286 program
506     EX_PHARLAP      = 8,       // PHARLAP 386 program
507     EX_COM          = 0x10,    // MSDOS .COM program
508 //  EX_WIN16        = 0x20,    // Windows 3.x 16 bit program (no longer supported)
509     EX_OS2          = 0x40,    // OS/2 2.0 32 bit program
510     EX_OS1          = 0x80,    // OS/2 1.x 16 bit program
511     EX_WIN32        = 0x100,
512     EX_MZ           = 0x200,   // MSDOS real mode program
513     EX_XENIX        = 0x400,
514     EX_SCOUNIX      = 0x800,
515     EX_UNIXSVR4     = 0x1000,
516     EX_LINUX        = 0x2000,
517     EX_WIN64        = 0x4000,  // AMD64 and Windows (64 bit mode)
518     EX_LINUX64      = 0x8000,  // AMD64 and Linux (64 bit mode)
519     EX_OSX          = 0x10000,
520     EX_OSX64        = 0x20000,
521     EX_FREEBSD      = 0x40000,
522     EX_FREEBSD64    = 0x80000,
523     EX_SOLARIS      = 0x100000,
524     EX_SOLARIS64    = 0x200000,
525     EX_OPENBSD      = 0x400000,
526     EX_OPENBSD64    = 0x800000,
527     EX_DRAGONFLYBSD64 = 0x1000000,
528 }
529 
530 
531 // All flat memory models (no segment registers)
532 enum exefmt_t EX_flat = EX_OS2 | EX_WIN32 | EX_LINUX | EX_WIN64 | EX_LINUX64 |
533                          EX_OSX | EX_OSX64 | EX_FREEBSD | EX_FREEBSD64 |
534                          EX_OPENBSD | EX_OPENBSD64 |
535                          EX_DRAGONFLYBSD64 |
536                          EX_SOLARIS | EX_SOLARIS64;
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 /*| EX_WIN16*/;
541 
542 alias config_flags_t = uint;
543 enum
544 {
545     CFGuchar        = 1,       // chars are unsigned
546     CFGsegs         = 2,       // new code seg for each far func
547     CFGtrace        = 4,       // output trace functions
548     CFGglobal       = 8,       // make all static functions global
549     CFGstack        = 0x10,    // add stack overflow checking
550     CFGalwaysframe  = 0x20,    // always generate stack frame
551     CFGnoebp        = 0x40,    // do not use EBP as general purpose register
552     CFGromable      = 0x80,    // put switch tables in code segment
553     CFGeasyomf      = 0x100,   // generate Pharlap Easy-OMF format
554     CFGfarvtbls     = 0x200,   // store vtables in far segments
555     CFGnoinlines    = 0x400,   // do not inline functions
556     CFGnowarning    = 0x800,   // disable warnings
557 }
558 
559 alias config_flags2_t = uint;
560 enum
561 {
562     CFG2comdat      = 1,       // use initialized common blocks
563     CFG2nodeflib    = 2,       // no default library imbedded in OBJ file
564     CFG2browse      = 4,       // generate browse records
565     CFG2dyntyping   = 8,       // generate dynamic typing information
566     CFG2fulltypes   = 0x10,    // don't optimize CV4 class info
567     CFG2warniserr   = 0x20,    // treat warnings as errors
568     CFG2phauto      = 0x40,    // automatic precompiled headers
569     CFG2phuse       = 0x80,    // use precompiled headers
570     CFG2phgen       = 0x100,   // generate precompiled header
571     CFG2once        = 0x200,   // only include header files once
572     CFG2hdrdebug    = 0x400,   // generate debug info for header
573     CFG2phautoy     = 0x800,   // fast build precompiled headers
574     CFG2noobj       = 0x1000,  // we are not generating a .OBJ file
575     CFG2noerrmax    = 0x2000,  // no error count maximum
576     CFG2expand      = 0x4000,  // expanded output to list file
577     CFG2stomp       = 0x8000,  // enable stack stomping code
578     CFG2gms         = 0x10000, // optimize debug symbols for microsoft debuggers
579 }
580 
581 alias config_flags3_t = uint;
582 enum
583 {
584     CFG3ju          = 1,       // char == unsigned char
585     CFG3eh          = 2,       // generate exception handling stuff
586     CFG3strcod      = 4,       // strings are placed in code segment
587     CFG3eseqds      = 8,       // ES == DS at all times
588     CFG3ptrchk      = 0x10,    // generate pointer validation code
589     CFG3strictproto = 0x20,    // strict prototyping
590     CFG3autoproto   = 0x40,    // auto prototyping
591     CFG3rtti        = 0x80,    // add RTTI support
592     CFG3relax       = 0x100,   // relaxed type checking (C only)
593     CFG3cpp         = 0x200,   // C++ compile
594     CFG3igninc      = 0x400,   // ignore standard include directory
595     CFG3mars        = 0x800,   // use mars libs and headers
596     CFG3nofar       = 0x1000,  // ignore __far and __huge keywords
597     CFG3noline      = 0x2000,  // do not output #line directives
598     CFG3comment     = 0x4000,  // leave comments in preprocessed output
599     CFG3cppcomment  = 0x8000,  // allow C++ style comments
600     CFG3wkfloat     = 0x10000, // make floating point references weak externs
601     CFG3digraphs    = 0x20000, // support ANSI C++ digraphs
602     CFG3semirelax   = 0x40000, // moderate relaxed type checking (non-Windows targets)
603     CFG3pic         = 0x80000, // position independent code
604     CFG3pie         = 0x10_0000, // position independent executable (CFG3pic also set)
605 }
606 
607 alias config_flags4_t = uint;
608 enum
609 {
610     CFG4speed            = 1,          // optimized for speed
611     CFG4space            = 2,          // optimized for space
612     CFG4allcomdat        = 4,          // place all functions in COMDATs
613     CFG4fastfloat        = 8,          // fast floating point (-ff)
614     CFG4fdivcall         = 0x10,       // make function call for FDIV opcodes
615     CFG4tempinst         = 0x20,       // instantiate templates for undefined functions
616     CFG4oldstdmangle     = 0x40,       // do stdcall mangling without @
617     CFG4pascal           = 0x80,       // default to pascal linkage
618     CFG4stdcall          = 0x100,      // default to std calling convention
619     CFG4cacheph          = 0x200,      // cache precompiled headers in memory
620     CFG4alternate        = 0x400,      // if alternate digraph tokens
621     CFG4bool             = 0x800,      // support 'bool' as basic type
622     CFG4wchar_t          = 0x1000,     // support 'wchar_t' as basic type
623     CFG4notempexp        = 0x2000,     // no instantiation of template functions
624     CFG4anew             = 0x4000,     // allow operator new[] and delete[] overloading
625     CFG4oldtmangle       = 0x8000,     // use old template name mangling
626     CFG4dllrtl           = 0x10000,    // link with DLL RTL
627     CFG4noemptybaseopt   = 0x20000,    // turn off empty base class optimization
628     CFG4nowchar_t        = 0x40000,    // use unsigned short name mangling for wchar_t
629     CFG4forscope         = 0x80000,    // new C++ for scoping rules
630     CFG4warnccast        = 0x100000,   // warn about C style casts
631     CFG4adl              = 0x200000,   // argument dependent lookup
632     CFG4enumoverload     = 0x400000,   // enum overloading
633     CFG4implicitfromvoid = 0x800000,   // allow implicit cast from void* to T*
634     CFG4dependent        = 0x1000000,  // dependent / non-dependent lookup
635     CFG4wchar_is_long    = 0x2000000,  // wchar_t is 4 bytes
636     CFG4underscore       = 0x4000000,  // prepend _ for C mangling
637 }
638 
639 enum config_flags4_t CFG4optimized  = CFG4speed | CFG4space;
640 enum config_flags4_t CFG4stackalign = CFG4speed;       // align stack to 8 bytes
641 
642 alias config_flags5_t = uint;
643 enum
644 {
645     CFG5debug       = 1,      // compile in __debug code
646     CFG5in          = 2,      // compile in __in code
647     CFG5out         = 4,      // compile in __out code
648     CFG5invariant   = 8,      // compile in __invariant code
649 }
650 
651 /* CFGX: flags ignored in precompiled headers
652  * CFGY: flags copied from precompiled headers into current config
653  */
654 enum config_flags_t CFGX   = CFGnowarning;
655 enum config_flags2_t CFGX2 = CFG2warniserr | CFG2phuse | CFG2phgen | CFG2phauto |
656                              CFG2once | CFG2hdrdebug | CFG2noobj | CFG2noerrmax |
657                              CFG2expand | CFG2nodeflib | CFG2stomp | CFG2gms;
658 enum config_flags3_t CFGX3 = CFG3strcod | CFG3ptrchk;
659 enum config_flags4_t CFGX4 = CFG4optimized | CFG4fastfloat | CFG4fdivcall |
660                              CFG4tempinst | CFG4cacheph | CFG4notempexp |
661                              CFG4stackalign | CFG4dependent;
662 
663 enum config_flags4_t CFGY4 = CFG4nowchar_t | CFG4noemptybaseopt | CFG4adl |
664                              CFG4enumoverload | CFG4implicitfromvoid |
665                              CFG4wchar_is_long | CFG4underscore;
666 
667 // Configuration flags for HTOD executable
668 alias htod_flags_t = uint;
669 enum
670 {
671     HTODFinclude    = 1,      // -hi drill down into #include files
672     HTODFsysinclude = 2,      // -hs drill down into system #include files
673     HTODFtypedef    = 4,      // -ht drill down into typedefs
674     HTODFcdecl      = 8,      // -hc skip C declarations as comments
675 }
676 
677 // This part of the configuration is saved in the precompiled header for use
678 // in comparing to make sure it hasn't changed.
679 
680 struct Config
681 {
682     char language;              // 'C' = C, 'D' = C++
683     string _version;            /// Compiler version
684     char[3] exetype;            // distinguish exe types so PH
685                                 // files are distinct (= SUFFIX)
686 
687     cpu_target_t target_cpu;       // instruction selection
688     cpu_target_t target_scheduler; // instruction scheduling (normally same as selection)
689 
690     short versionint;           // intermediate file version (= VERSIONINT)
691     int defstructalign;         // struct alignment specified by command line
692     short hxversion;            // HX version number
693     symbolic_debug_t fulltypes; // format of symbolic debug info
694 
695     windows_flags_t wflags;     // flags for Windows code generation
696 
697     bool fpxmmregs;             // use XMM registers for floating point
698     ubyte avx;                  // use AVX instruction set (0, 1, 2)
699     ubyte inline8087;           /* 0:   emulator
700                                    1:   IEEE 754 inline 8087 code
701                                    2:   fast inline 8087 code
702                                  */
703     short memmodel;             // 0:S,X,N,F, 1:M, 2:C, 3:L, 4:V
704     objfmt_t objfmt;            // target object format
705     exefmt_t exe;               // target operating system
706 
707     config_flags_t  flags;
708     config_flags2_t flags2;
709     config_flags3_t flags3;
710     config_flags4_t flags4;
711     config_flags5_t flags5;
712 
713     htod_flags_t htodFlags;     // configuration for htod
714     ubyte ansi_c;               // strict ANSI C
715                                 // 89 for ANSI C89, 99 for ANSI C99
716     ubyte asian_char;           // 0: normal, 1: Japanese, 2: Chinese
717                                 // and Taiwanese, 3: Korean
718     uint threshold;             // data larger than threshold is assumed to
719                                 // be far (16 bit models only)
720                                 // if threshold == THRESHMAX, all data defaults
721                                 // to near
722     linkage_t linkage;          // default function call linkage
723     EHmethod ehmethod;          // exception handling method
724     bool useModuleInfo;         // implement ModuleInfo
725     bool useTypeInfo;           // implement TypeInfo
726     bool useExceptions;         // implement exception handling
727 }
728 
729 enum THRESHMAX = 0xFFFF;
730 
731 // Language for error messages
732 enum LANG
733 {       LANGenglish,
734         LANGgerman,
735         LANGfrench,
736         LANGjapanese,
737 }
738 
739 // Configuration that is not saved in precompiled header
740 
741 struct Configv
742 {
743     ubyte addlinenumbers;       // put line number info in .OBJ file
744     ubyte verbose;              // 0: compile quietly (no messages)
745                                 // 1: show progress to DLL (default)
746                                 // 2: full verbosity
747     char* csegname;             // code segment name
748     char* deflibname;           // default library name
749     LANG language;              // message language
750     int errmax;                 // max error count
751 }
752 
753 alias reg_t = ubyte;            // register number
754 alias regm_t = uint;            // Register mask type
755 struct immed_t
756 {
757     targ_size_t[REGMAX] value;  // immediate values in registers
758     regm_t mval;                // Mask of which values in regimmed.value[] are valid
759 }
760 
761 
762 struct cse_t
763 {
764     elem*[REGMAX] value;        // expression values in registers
765     regm_t mval;                // mask of which values in value[] are valid
766     regm_t mops;                // subset of mval that contain common subs that need
767                                 // to be stored in csextab[] if they are destroyed
768 }
769 
770 struct con_t
771 {
772     cse_t cse;                  // CSEs in registers
773     immed_t immed;              // immediate values in registers
774     regm_t mvar;                // mask of register variables
775     regm_t mpvar;               // mask of SCfastpar, SCshadowreg register variables
776     regm_t indexregs;           // !=0 if more than 1 uncommitted index register
777     regm_t used;                // mask of registers used
778     regm_t params;              // mask of registers which still contain register
779                                 // function parameters
780 }
781 
782 /*********************************
783  * Bootstrap complex types.
784  */
785 
786 import dmd.backend.bcomplex;
787 
788 /*********************************
789  * Union of all data types. Storage allocated must be the right
790  * size of the data on the TARGET, not the host.
791  */
792 
793 struct Cent
794 {
795     targ_ullong lsw;
796     targ_ullong msw;
797 }
798 
799 union eve
800 {
801         targ_char       Vchar;
802         targ_schar      Vschar;
803         targ_uchar      Vuchar;
804         targ_short      Vshort;
805         targ_ushort     Vushort;
806         targ_int        Vint;
807         targ_uns        Vuns;
808         targ_long       Vlong;
809         targ_ulong      Vulong;
810         targ_llong      Vllong;
811         targ_ullong     Vullong;
812         Cent            Vcent;
813         targ_float      Vfloat;
814         targ_double     Vdouble;
815         targ_ldouble    Vldouble;
816         Complex_f       Vcfloat;   // 2x float
817         Complex_d       Vcdouble;  // 2x double
818         Complex_ld      Vcldouble; // 2x long double
819         targ_size_t     Vpointer;
820         targ_ptrdiff_t  Vptrdiff;
821         targ_uchar      Vreg;   // register number for OPreg elems
822 
823         // 16 byte vector types
824         targ_float[4]   Vfloat4;   // float[4]
825         targ_double[2]  Vdouble2;  // double[2]
826         targ_schar[16]  Vschar16;  // byte[16]
827         targ_uchar[16]  Vuchar16;  // ubyte[16]
828         targ_short[8]   Vshort8;   // short[8]
829         targ_ushort[8]  Vushort8;  // ushort[8]
830         targ_long[4]    Vlong4;    // int[4]
831         targ_ulong[4]   Vulong4;   // uint[4]
832         targ_llong[2]   Vllong2;   // long[2]
833         targ_ullong[2]  Vullong2;  // ulong[2]
834 
835         // 32 byte vector types
836         targ_float[8]   Vfloat8;   // float[8]
837         targ_double[4]  Vdouble4;  // double[4]
838         targ_schar[32]  Vschar32;  // byte[32]
839         targ_uchar[32]  Vuchar32;  // ubyte[32]
840         targ_short[16]  Vshort16;  // short[16]
841         targ_ushort[16] Vushort16; // ushort[16]
842         targ_long[8]    Vlong8;    // int[8]
843         targ_ulong[8]   Vulong8;   // uint[8]
844         targ_llong[4]   Vllong4;   // long[4]
845         targ_ullong[4]  Vullong4;  // ulong[4]
846 
847         struct                  // 48 bit 386 far pointer
848         {   targ_long   Voff;
849             targ_ushort Vseg;
850         }
851         struct
852         {
853             targ_size_t Voffset;// offset from symbol
854             Symbol *Vsym;       // pointer to symbol table
855             union
856             {
857                 param_t* Vtal;  // template-argument-list for SCfunctempl,
858                                 // used only to transmit it to cpp_overload()
859                 LIST* Erd;      // OPvar: reaching definitions
860             }
861         }
862         struct
863         {
864             targ_size_t Voffset2;// member pointer offset
865             Classsym* Vsym2;    // struct tag
866             elem* ethis;        // OPrelconst: 'this' for member pointer
867         }
868         struct
869         {
870             targ_size_t Voffset3;// offset from string
871             char* Vstring;      // pointer to string (OPstring or OPasm)
872             targ_size_t Vstrlen;// length of string
873         }
874         struct
875         {
876             elem* E1;           // left child for unary & binary nodes
877             elem* E2;           // right child for binary nodes
878             Symbol* Edtor;      // OPctor: destructor
879         }
880         struct
881         {
882             elem* Eleft2;       // left child for OPddtor
883             void* Edecl;        // VarDeclaration being constructed
884         }                       // OPdctor,OPddtor
885 }                               // variants for each type of elem
886 
887 // Symbols
888 
889 //#ifdef DEBUG
890 //#define IDSYMBOL        IDsymbol,
891 //#else
892 //#define IDSYMBOL
893 //#endif
894 
895 alias SYMFLGS = uint;
896 
897 
898 /**********************************
899  * Storage classes
900  */
901 
902 alias SC = int;
903 enum
904 {
905     SCunde,           // undefined
906     SCauto,           // automatic (stack)
907     SCstatic,         // statically allocated
908     SCthread,         // thread local
909     SCextern,         // external
910     SCregister,       // registered variable
911     SCpseudo,         // pseudo register variable
912     SCglobal,         // top level global definition
913     SCcomdat,         // initialized common block
914     SCparameter,      // function parameter
915     SCregpar,         // function register parameter
916     SCfastpar,        // function parameter passed in register
917     SCshadowreg,      // function parameter passed in register, shadowed on stack
918     SCtypedef,        // type definition
919     SCexplicit,       // explicit
920     SCmutable,        // mutable
921     SClabel,          // goto label
922     SCstruct,         // struct/class/union tag name
923     SCenum,           // enum tag name
924     SCfield,          // bit field of struct or union
925     SCconst,          // constant integer
926     SCmember,         // member of struct or union
927     SCanon,           // member of anonymous union
928     SCinline,         // for inline functions
929     SCsinline,        // for static inline functions
930     SCeinline,        // for extern inline functions
931     SCoverload,       // for overloaded function names
932     SCfriend,         // friend of a class
933     SCvirtual,        // virtual function
934     SClocstat,        // static, but local to a function
935     SCtemplate,       // class template
936     SCfunctempl,      // function template
937     SCftexpspec,      // function template explicit specialization
938     SClinkage,        // function linkage symbol
939     SCpublic,         // generate a pubdef for this
940     SCcomdef,         // uninitialized common block
941     SCbprel,          // variable at fixed offset from frame pointer
942     SCnamespace,      // namespace
943     SCalias,          // alias to another symbol
944     SCfuncalias,      // alias to another function symbol
945     SCmemalias,       // alias to base class member
946     SCstack,          // offset from stack pointer (not frame pointer)
947     SCadl,            // list of ADL symbols for overloading
948     SCMAX
949 }
950 
951 int ClassInline(int c) { return c == SCinline || c == SCsinline || c == SCeinline; }
952 int SymInline(Symbol* s) { return ClassInline(s.Sclass); }
953