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