Allow returning something of type void in a function that returns void
[delight/core.git] / d-lang.cc
blob4fa66a8b7f95bb9832142817ec0824c2edb018ee
1 /* GDC -- D front-end for GCC
2 Copyright (C) 2004 David Friedman
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 dc-lang.cc: implementation of back-end callbacks and data structures
23 #include "root.h"
24 #include "mtype.h"
25 #include "id.h"
26 #include "module.h"
27 #include "cond.h"
28 #include "mars.h"
30 #include <assert.h>
31 #include "d-gcc-includes.h"
32 #include "options.h"
33 #include "d-lang.h"
34 #include "d-codegen.h"
35 #include "d-gcc-real.h"
36 #include "d-confdefs.h"
38 static char lang_name[6] = "GNU D";
40 #undef LANG_HOOKS_NAME
41 #define LANG_HOOKS_NAME lang_name
43 #undef LANG_HOOKS_INIT
44 #define LANG_HOOKS_INIT d_init
46 #undef LANG_HOOKS_INIT_OPTIONS
47 #define LANG_HOOKS_INIT_OPTIONS d_init_options
49 #undef LANG_HOOKS_HANDLE_OPTION
50 #define LANG_HOOKS_HANDLE_OPTION d_handle_option
51 #undef LANG_HOOKS_POST_OPTIONS
52 #define LANG_HOOKS_POST_OPTIONS d_post_options
54 #undef LANG_HOOKS_PARSE_FILE
55 #define LANG_HOOKS_PARSE_FILE d_parse_file
57 #if D_GCC_VER < 41
58 #undef LANG_HOOKS_TRUTHVALUE_CONVERSION
59 #define LANG_HOOKS_TRUTHVALUE_CONVERSION d_truthvalue_conversion
60 #endif
62 #undef LANG_HOOKS_MARK_ADDRESSABLE
63 #define LANG_HOOKS_MARK_ADDRESSABLE d_mark_addressable
65 #undef LANG_HOOKS_TYPE_FOR_MODE
66 #define LANG_HOOKS_TYPE_FOR_MODE d_type_for_mode
68 #undef LANG_HOOKS_TYPE_FOR_SIZE
69 #define LANG_HOOKS_TYPE_FOR_SIZE d_type_for_size
71 #if D_GCC_VER < 40
72 #undef LANG_HOOKS_EXPAND_EXPR
73 #define LANG_HOOKS_EXPAND_EXPR d_expand_expr
74 #endif
76 #define LANG_HOOKS_UNSIGNED_TYPE d_unsigned_type
77 #define LANG_HOOKS_SIGNED_TYPE d_signed_type
78 #define LANG_HOOKS_SIGNED_OR_UNSIGNED_TYPE d_signed_or_unsigned_type
79 #define LANG_HOOKS_TYPE_FOR_SIZE d_type_for_size
80 #define LANG_HOOKS_TYPE_FOR_MODE d_type_for_mode
82 #undef LANG_HOOKS_TYPE_PROMOTES_TO
83 #define LANG_HOOKS_TYPE_PROMOTES_TO d_type_promotes_to
85 #undef LANG_HOOKS_WRITE_GLOBALS
86 #define LANG_HOOKS_WRITE_GLOBALS d_write_global_declarations
88 // Some phobos code (isnormal, etc.) breaks with strict aliasing...
89 // so I guess D doesn't have aliasing rules. Would be nice to enable
90 // strict aliasing, but hooking or defaulting flag_strict_aliasing is
91 // not trivial
92 #undef LANG_HOOKS_GET_ALIAS_SET
93 #define LANG_HOOKS_GET_ALIAS_SET hook_get_alias_set_0
95 // Needed for try/finally -- statements cannont be re-evaluated
96 #if D_GCC_VER < 40
97 #undef LANG_HOOKS_UNSAFE_FOR_REEVAL
98 #define LANG_HOOKS_UNSAFE_FOR_REEVAL d_unsafe_for_reeval
99 #endif
101 #undef LANG_HOOKS_COMMON_ATTRIBUTE_TABLE
102 #define LANG_HOOKS_COMMON_ATTRIBUTE_TABLE d_common_attribute_table
103 #undef LANG_HOOKS_FORMAT_ATTRIBUTE_TABLE
104 #define LANG_HOOKS_FORMAT_ATTRIBUTE_TABLE d_common_format_attribute_table
106 #if D_GCC_VER >= 40
107 #undef LANG_HOOKS_CALLGRAPH_EXPAND_FUNCTION
108 #define LANG_HOOKS_CALLGRAPH_EXPAND_FUNCTION d_expand_function
109 #endif
111 #if D_GCC_VER >= 40
112 #define LANG_HOOKS_TYPES_COMPATIBLE_P d_types_compatible_p
114 #if V2
115 #undef LANG_HOOKS_TREE_INLINING_CONVERT_PARM_FOR_INLINING
116 #define LANG_HOOKS_TREE_INLINING_CONVERT_PARM_FOR_INLINING d_convert_parm_for_inlining
117 #endif
119 #endif
122 ////static tree d_type_for_size PARAMS ((unsigned, int));
123 static tree d_signed_or_unsigned_type(int, tree);
124 ////tree d_unsigned_type(tree);
125 ////tree d_signed_type(tree);
128 class DGCCMain {
129 bool stdInc;
131 initOptions() { }
135 static const char * iprefix;
136 static bool std_inc; // %%FIX: find a place for this
137 static const char * fonly_arg;
138 static const char * multilib_dir;
140 static unsigned int
141 d_init_options (unsigned int, const char **)
143 // Set default values
144 global.params.argv0 = (char *) progname;
145 global.params.link = 1;
146 global.params.useAssert = 1;
147 global.params.useInvariants = 1;
148 global.params.useIn = 1;
149 global.params.useOut = 1;
150 global.params.useArrayBounds = 1;
151 flag_bounds_check = global.params.useArrayBounds; // keep in synch with existing -fbounds-check flag
152 global.params.useSwitchError = 1;
153 global.params.useInline = 0;
154 global.params.warnings = 0;
155 global.params.obj = 1;
156 global.params.Dversion = 2;
157 global.params.quiet = 1;
159 global.params.linkswitches = new Array();
160 global.params.libfiles = new Array();
161 global.params.objfiles = new Array();
162 global.params.ddocfiles = new Array();
164 global.params.imppath = new Array();
165 global.params.fileImppath = new Array();
167 // GCC options
168 flag_exceptions = 1;
170 // extra D-specific options
171 gen.splitDynArrayVarArgs = true;
172 gen.emitTemplates = TEauto;
173 gen.useBuiltins = true;
174 std_inc = true;
176 return CL_D;
179 // support for the -mno-cygwin switch
180 // copied from cygwin.h, cygwin2.c
181 #ifndef CYGWIN_MINGW_SUBDIR
182 #define CYGWIN_MINGW_SUBDIR "/mingw"
183 #endif
184 #define CYGWIN_MINGW_SUBDIR_LEN (sizeof (CYGWIN_MINGW_SUBDIR) - 1)
186 char cygwin_d_phobos_dir[sizeof(D_PHOBOS_DIR) + 1
187 + (CYGWIN_MINGW_SUBDIR_LEN)] = D_PHOBOS_DIR;
188 #undef D_PHOBOS_DIR
189 #define D_PHOBOS_DIR (cygwin_d_phobos_dir)
190 char cygwin_d_target_dir[sizeof(D_PHOBOS_TARGET_DIR) + 1
191 + (CYGWIN_MINGW_SUBDIR_LEN)] = D_PHOBOS_TARGET_DIR;
192 #undef D_PHOBOS_TARGET_DIR
193 #define D_PHOBOS_TARGET_DIR (cygwin_d_target_dir)
195 #ifdef D_OS_VERSYM
196 const char * cygwin_d_os_versym = D_OS_VERSYM;
197 #undef D_OS_VERSYM
198 #define D_OS_VERSYM cygwin_d_os_versym
199 #endif
201 void
202 maybe_fixup_cygwin()
204 #ifdef D_OS_VERSYM
205 char * env = getenv("GCC_CYGWIN_MINGW");
206 char * p;
207 char ** av;
209 static char *d_cvt_to_mingw[] = {
210 cygwin_d_phobos_dir,
211 cygwin_d_target_dir,
212 NULL };
213 if (!strcmp(cygwin_d_os_versym,"cygwin") && env && *env == '1') {
214 cygwin_d_os_versym = "Win32";
216 for (av = d_cvt_to_mingw; *av; av++)
218 int sawcygwin = 0;
219 while ((p = strstr (*av, "-cygwin")))
221 char *over = p + sizeof ("-cygwin") - 1;
222 memmove (over + 1, over, strlen (over));
223 memcpy (p, "-mingw32", sizeof("-mingw32") - 1);
224 p = ++over;
225 while (ISALNUM (*p))
226 p++;
227 strcpy (over, p);
228 sawcygwin = 1;
230 if (!sawcygwin && !strstr (*av, "mingw"))
231 strcat (*av, CYGWIN_MINGW_SUBDIR);
234 #endif
237 static bool is_target_win32 = false;
239 bool
240 d_gcc_is_target_win32()
242 return is_target_win32;
245 static char *
246 prefixed_path(const char * path)
248 // based on c-incpath.c
249 size_t len = cpp_GCC_INCLUDE_DIR_len;
250 if (iprefix && len != 0 && ! strncmp(path, cpp_GCC_INCLUDE_DIR, len))
251 return concat(iprefix, path + len, NULL);
252 else
253 return xstrdup(path);
256 static int
257 d_cpp_forall_callback(cpp_reader *, cpp_hashnode * hn, void *)
259 const char * str = (const char *) hn->ident.str;
260 unsigned int len = hn->ident.len;
261 char * d_ident = new char[4 + len + 1];
262 if (len > 4 && str[0] == '_' && str[1] == '_' &&
263 str[len - 1] == '_' && str[len - 2] == '_')
265 str += 2;
266 len -= 4;
268 strcpy(d_ident, "GNU_");
269 strncpy(d_ident + 4, str, len);
270 d_ident[len + 4] = '\0';
271 VersionCondition::addPredefinedGlobalIdent(d_ident);
272 return 1;
275 /* Supports CPP builtins. */
276 cpp_reader * parse_in;
277 void
278 builtin_define_std (const char *macro)
280 // Do nothing. No need for these (yet).
283 static bool
284 d_init ()
286 const char * cpu_versym = NULL;
288 /* Currently, isX86_64 indicates a 64-bit target in general and is not
289 Intel-specific. */
290 #ifdef TARGET_64BIT
291 global.params.isX86_64 = TARGET_64BIT ? 1 : 0;
292 #else
293 /* TARGET_64BIT is only defined on biarched archs defaulted to 64-bit
294 * (as amd64 or s390x) so for full 64-bit archs (as ia64 or alpha) we
295 * need to test it more. */
296 # ifdef D_CPU_VERSYM64
297 /* We are "defaulting" to 32-bit, which mean that if both D_CPU_VERSYM
298 * and D_CPU_VERSYM64 are defined, and not TARGET_64BIT, we will use
299 * 32 bits. This will be overidden for full 64-bit archs */
300 global.params.isX86_64 = 0;
301 # ifndef D_CPU_VERSYM
302 /* So this is typically for alpha and ia64 */
303 global.params.isX86_64 = 1;
304 # endif
305 # else
306 # ifdef D_CPU_VERSYM /* D_CPU_VERSYM is defined and D_CPU_VERSYM64 is not. */
307 global.params.isX86_64 = 0;
308 # else
309 /* If none of D_CPU_VERSYM and D_CPU_VERSYM64 defined check size_t
310 * length instead. */
311 switch (sizeof(size_t)) {
312 case 4:
313 global.params.isX86_64 = 0;
314 break;
315 case 8:
316 global.params.isX86_64 = 1;
317 break;
319 # endif
320 # endif
321 #endif
323 Type::init();
324 Id::initialize();
325 Module::init();
326 initPrecedence();
327 gcc_d_backend_init();
328 real_t::init();
330 maybe_fixup_cygwin();
332 VersionCondition::addPredefinedGlobalIdent("GNU");
333 #ifdef D_CPU_VERSYM64
334 if (global.params.isX86_64 == 1)
335 cpu_versym = D_CPU_VERSYM64;
336 # ifdef D_CPU_VERSYM
337 else
338 cpu_versym = D_CPU_VERSYM;
339 # endif
340 #else
341 # ifdef D_CPU_VERSYM
342 cpu_versym = D_CPU_VERSYM;
343 # endif
344 #endif
345 if (cpu_versym)
346 VersionCondition::addPredefinedGlobalIdent((char*) cpu_versym);
347 #ifdef D_OS_VERSYM
348 VersionCondition::addPredefinedGlobalIdent((char*) D_OS_VERSYM);
349 if (strcmp(D_OS_VERSYM, "Win32") == 0)
350 is_target_win32 = true;
351 #endif
352 #ifdef D_OS_VERSYM2
353 VersionCondition::addPredefinedGlobalIdent((char*) D_OS_VERSYM2);
354 if (strcmp(D_OS_VERSYM2, "Win32") == 0)
355 is_target_win32 = true;
356 #endif
358 #ifdef TARGET_THUMB
359 if (TARGET_THUMB)
360 VersionCondition::addPredefinedGlobalIdent("Thumb");
361 else
362 VersionCondition::addPredefinedGlobalIdent("Arm");
363 #endif
365 if (BYTES_BIG_ENDIAN)
366 VersionCondition::addPredefinedGlobalIdent("BigEndian");
367 else
368 VersionCondition::addPredefinedGlobalIdent("LittleEndian");
370 if (d_using_sjlj_exceptions()) {
371 VersionCondition::addPredefinedGlobalIdent("GNU_SjLj_Exceptions");
373 #ifdef TARGET_LONG_DOUBLE_128
374 if (TARGET_LONG_DOUBLE_128)
375 VersionCondition::addPredefinedGlobalIdent("GNU_LongDouble128");
376 #endif
378 if (d_have_inline_asm() && cpu_versym && strcmp(cpu_versym, "X86") == 0)
380 VersionCondition::addPredefinedGlobalIdent("D_InlineAsm");
381 VersionCondition::addPredefinedGlobalIdent("D_InlineAsm_X86");
384 /* Setting global.params.cov forces module info generation which is
385 not needed for thee GCC coverage implementation. Instead, just
386 test flag_test_coverage while leaving global.params.cov unset. */
387 //if (global.params.cov)
388 if (flag_test_coverage)
389 VersionCondition::addPredefinedGlobalIdent("D_Coverage");
390 if (global.params.useUnitTests)
391 VersionCondition::addPredefinedGlobalIdent("unittest");
394 line_maps lm;
395 cpp_reader * pfile; // Target macros below expect this identifier.
396 int flag_iso = 0; // ditto
398 linemap_init(& lm);
399 parse_in = pfile = cpp_create_reader(CLK_STDC89, NULL
400 #if D_GCC_VER >= 40
401 , & lm
402 #endif
404 cpp_change_file(pfile, LC_ENTER, "<built-in>");
406 // from c-cppbuiltin.c
407 #ifndef TARGET_OS_CPP_BUILTINS
408 # define TARGET_OS_CPP_BUILTINS()
409 #endif
410 #ifndef TARGET_OBJFMT_CPP_BUILTINS
411 # define TARGET_OBJFMT_CPP_BUILTINS()
412 #endif
414 # define preprocessing_asm_p() (cpp_get_options (pfile)->lang == CLK_ASM)
415 # define preprocessing_trad_p() (cpp_get_options (pfile)->traditional)
416 # define preprocessing_asm_p() (0)
417 # define preprocessing_trad_p() (0)
418 # define c_dialect_cxx() (0)
419 # define c_dialect_objc() (0)
420 # define builtin_define(TXT) (cpp_define (pfile, TXT))
421 # define builtin_define_with_value(m,e,s)
422 # define builtin_define_with_int_value(m,i)
423 # define builtin_define_std(TXT) (cpp_define (pfile, TXT))
424 # define builtin_assert(TXT) (cpp_assert (pfile, TXT))
425 TARGET_CPU_CPP_BUILTINS ();
426 TARGET_OS_CPP_BUILTINS ();
427 TARGET_OBJFMT_CPP_BUILTINS ();
429 cpp_forall_identifiers(pfile, & d_cpp_forall_callback, NULL);
431 cpp_destroy(pfile);
432 linemap_free(& lm);
435 VersionCondition::addPredefinedGlobalIdent("all");
438 // %%TODO: front or back?
439 if (std_inc)
441 char * target_dir = prefixed_path(D_PHOBOS_TARGET_DIR);
442 if (multilib_dir)
443 target_dir = concat(target_dir, "/", multilib_dir, NULL);
445 global.params.imppath->insert(0, prefixed_path(D_PHOBOS_DIR));
446 global.params.imppath->insert(0, target_dir);
449 if (global.params.imppath)
451 for (unsigned i = 0; i < global.params.imppath->dim; i++)
453 char *path = (char *)global.params.imppath->data[i];
454 // We would do this for D_INCLUDE_PATH env var, but not for '-I'
455 // command line args.
456 //Array *a = FileName::splitPath(path);
458 if (path)
460 if (!global.path)
461 global.path = new Array();
462 //global.path->append(a);
463 global.path->push(path);
468 if (global.params.fileImppath)
470 for (unsigned i = 0; i < global.params.fileImppath->dim; i++)
472 char *path = (char *)global.params.fileImppath->data[i];
473 if (path)
475 if (!global.filePath)
476 global.filePath = new Array();
477 global.filePath->push(path);
483 char * path = FileName::searchPath(global.path, "phobos-ver-syms", 1);
484 if (path) {
485 FILE * f = fopen(path, "r");
486 char buf[256];
487 char *p, *q;
488 if (f) {
489 while ( ! feof(f) && fgets(buf, 256, f) ) {
490 p = buf;
491 while (*p && ISSPACE(*p))
492 p++;
493 q = p;
494 while (*q && ! ISSPACE(*q))
495 q++;
496 *q = 0;
497 if (p != q) {
498 /* Needs to be predefined because we define
499 Unix/Windows this way. */
500 VersionCondition::addPredefinedGlobalIdent(xstrdup(p));
503 fclose(f);
504 } else {
505 //printf("failed\n");
507 } else {
508 //printf("no p-v-s found\n");
512 return 1;
515 static bool
516 parse_int (const char * arg, int * value_ret)
518 long v;
519 char * err;
520 errno = 0;
521 v = strtol(arg, & err, 10);
522 if (*err || errno || v > INT_MAX)
523 return false;
524 * value_ret = v;
525 return true;
528 static int
529 d_handle_option (size_t scode, const char *arg, int value)
531 enum opt_code code = (enum opt_code) scode;
532 int level;
534 switch (code)
536 case OPT_I:
537 global.params.imppath->push(xstrdup(arg)); // %% not sure if we can keep the arg or not
538 break;
539 case OPT_J:
540 global.params.fileImppath->push(xstrdup(arg));
541 break;
542 case OPT_fdeprecated:
543 global.params.useDeprecated = value;
544 break;
545 case OPT_fassert:
546 global.params.useAssert = value;
547 break;
548 case OPT_frelease:
549 global.params.useInvariants = ! value;
550 global.params.useIn = ! value;
551 global.params.useOut = ! value;
552 global.params.useAssert = ! value;
553 flag_bounds_check = global.params.useArrayBounds = ! value;
554 global.params.useSwitchError = ! value;
555 break;
556 case OPT_funittest:
557 global.params.useUnitTests = value;
558 break;
559 case OPT_fversion_:
560 if (ISDIGIT(arg[0])) {
561 if (! parse_int(arg, & level))
562 goto Lerror_v;
563 VersionCondition::setGlobalLevel(level);
564 } else if (Lexer::isValidIdentifier((char*) arg))
565 VersionCondition::addGlobalIdent(xstrdup(arg));
566 else {
567 Lerror_v:
568 error("bad argument for -fversion");
570 break;
571 case OPT_fdebug:
572 global.params.debuglevel = value ? 1 : 0;
573 break;
574 case OPT_fdebug_:
575 if (ISDIGIT(arg[0])) {
576 if (! parse_int(arg, & level))
577 goto Lerror_d;
578 DebugCondition::setGlobalLevel(level);
579 } else if (Lexer::isValidIdentifier((char*) arg))
580 DebugCondition::addGlobalIdent(xstrdup(arg));
581 else {
582 Lerror_d:
583 error("bad argument for -fdebug");
585 break;
586 case OPT_fdebug_c:
587 strcpy(lang_name, value ? "GNU C" : "GNU D");
588 break;
589 case OPT_fignore_unknown_pragmas:
590 global.params.ignoreUnsupportedPragmas = value;
591 break;
592 #ifdef _DH
593 case OPT_fintfc:
594 global.params.doHdrGeneration = value;
595 break;
596 case OPT_fintfc_dir_:
597 global.params.doHdrGeneration = 1;
598 global.params.hdrdir = xstrdup(arg);
599 break;
600 case OPT_fintfc_file_:
601 global.params.doHdrGeneration = 1;
602 global.params.hdrname = xstrdup(arg);
603 break;
604 #endif
605 case OPT_fdoc:
606 global.params.doDocComments = value;
607 break;
608 case OPT_fdoc_dir_:
609 global.params.doDocComments = 1;
610 global.params.docdir = xstrdup(arg);
611 break;
612 case OPT_fdoc_file_:
613 global.params.doDocComments = 1;
614 global.params.docname = xstrdup(arg);
615 break;
616 case OPT_fdoc_inc_:
617 global.params.ddocfiles->push(xstrdup(arg));
618 break;
619 case OPT_fd_verbose:
620 global.params.verbose = 1;
621 break;
622 case OPT_fd_version_1:
623 global.params.Dversion = 1;
624 break;
625 case OPT_femit_templates:
626 gen.emitTemplates = value ? TEauto : TEnone;
627 break;
628 case OPT_femit_templates_:
629 if (! arg || ! *arg) {
630 gen.emitTemplates = value ? TEauto : TEnone;
631 } else if (! strcmp(arg, "normal")) {
632 gen.emitTemplates = TEnormal;
633 } else if (! strcmp(arg, "all")) {
634 gen.emitTemplates = TEall;
635 } else if (! strcmp(arg, "private")) {
636 gen.emitTemplates = TEprivate;
637 } else if (! strcmp(arg, "none")) {
638 gen.emitTemplates = TEnone;
639 } else if (! strcmp(arg, "auto")) {
640 gen.emitTemplates = TEauto;
641 } else {
642 error("bad argument for -femit-templates");
644 break;
645 case OPT_fonly_:
646 fonly_arg = xstrdup(arg);
647 break;
648 case OPT_iprefix:
649 iprefix = xstrdup(arg);
650 break;
651 case OPT_fmultilib_dir_:
652 multilib_dir = xstrdup(arg);
653 break;
654 case OPT_nostdinc:
655 std_inc = false;
656 break;
657 case OPT_fdump_source:
658 global.params.dump_source = value;
659 break;
660 case OPT_fbuiltin:
661 gen.useBuiltins = value;
662 break;
663 case OPT_fsigned_char:
664 case OPT_funsigned_char:
665 // ignored
666 break;
667 case OPT_Wall:
668 global.params.warnings = value;
669 gen.warnSignCompare = value;
670 break;
671 case OPT_Wsign_compare:
672 gen.warnSignCompare = value;
673 break;
674 default:
675 break;
677 return 1;
680 bool d_post_options(const char ** fn)
682 // The front end considers the first input file to be the main one.
683 if (num_in_fnames)
684 *fn = in_fnames[0];
685 #if D_GCC_VER >= 40
687 // Inline option code copied from c-opts.c
688 flag_inline_trees = 1;
690 /* Use tree inlining. */
691 if (!flag_no_inline)
692 flag_no_inline = 1;
693 if (flag_inline_functions)
694 flag_inline_trees = 2;
696 /* If we are given more than one input file, we must use
697 unit-at-a-time mode. */
698 if (num_in_fnames > 1)
699 flag_unit_at_a_time = 1;
700 #endif
701 return false;
704 /* wrapup_global_declaration needs to be called or functions will not
705 be emitted. */
706 Array globalFunctions; // Array of tree (for easy passing to wrapup_global_declarations)
708 void
709 d_add_global_function(tree decl)
711 globalFunctions.push(decl);
714 static void
715 d_write_global_declarations()
717 tree * vec = (tree *) globalFunctions.data;
718 wrapup_global_declarations(vec, globalFunctions.dim);
719 check_global_declarations(vec, globalFunctions.dim);
720 #if D_GCC_VER >= 40
722 #if D_GCC_VER >= 41
723 cgraph_optimize();
724 #endif
727 for (int i = 0; i < globalFunctions.dim; i++)
728 debug_hooks->global_decl(vec[i]);
730 #if D_GCC_VER == 40
731 /* For 4.0.x, if cgraph_optimize is called before the loop over
732 globalFunctions, dwarf2out can generate a DIE tree that has a
733 nested class as the parent of an outer class (this causes an
734 ICE.) Not sure if this is due to a bug in the D front end, but calling
735 debug_hooks->global_decl ensures the outer elements are
736 processed first.
738 For later versions, calling cgraph_optimize later causes more
739 problems.
741 cgraph_optimize();
742 #endif
744 #endif
747 #if D_GCC_VER < 40
748 // taken from c_common_unsafe_for_reeval
750 d_unsafe_for_reeval (tree exp)
752 /* Statement expressions may not be reevaluated. */
753 if (TREE_CODE (exp) == (enum tree_code) D_STMT_EXPR)
754 return 2;
756 /* Walk all other expressions. */
757 return -1;
759 #endif
761 static Module * an_output_module = 0;
763 Module *
764 d_gcc_get_output_module()
766 return an_output_module;
769 static void
770 nametype(tree type, const char * name)
772 tree ident = get_identifier(name);
773 tree decl = build_decl(TYPE_DECL, ident, type);
774 TYPE_NAME(type) = decl;
775 ObjectFile::rodc(decl, 1);
778 static void
779 nametype(Type * t)
781 nametype(t->toCtype(), t->toChars());
784 #if V2
785 Symbol* rtlsym[N_RTLSYM];
786 #endif
788 void
789 d_parse_file (int /*set_yydebug*/)
791 Identifier * id;
792 //Module * m;
793 char * p, * e;
794 char * name;
795 unsigned i;
797 if (global.params.verbose && asm_out_file == stdout)
799 // Really, driver should see the option and turn off -pipe
800 error("Cannot use -fd-verbose with -pipe");
801 return;
804 if (global.params.useUnitTests)
805 global.params.useAssert = 1;
806 global.params.useArrayBounds = flag_bounds_check;
807 if (gen.emitTemplates == TEauto) {
808 gen.emitTemplates = (supports_one_only()) ? TEnormal : TEprivate;
810 global.params.symdebug = write_symbols != NO_DEBUG;
811 //global.params.useInline = flag_inline_functions;
812 global.params.obj = ! flag_syntax_only;
813 global.params.pic = flag_pic != 0; // Has no effect yet.
814 gen.originalOmitFramePointer = flag_omit_frame_pointer;
816 // better to use input_location.xxx ?
817 (*debug_hooks->start_source_file) (input_line, input_filename);
820 printf("input_filename = '%s'\n", input_filename);
821 printf("main_input_filename = '%s'\n", main_input_filename);
824 /* hack...
826 #if ! V2
827 Type::tbit->toCtype();
828 #endif
829 Type::tbool->toCtype();
830 Type::tchar->toCtype();
831 Type::twchar->toCtype();
832 Type::tdchar->toCtype();
834 for (TY ty = (TY) 0; ty < TMAX; ty = (TY)(ty + 1)) {
835 if (Type::basic[ty])
836 nametype(Type::basic[ty]);
840 p = FileName::name(input_filename);
841 e = FileName::ext(p);
842 if (e) {
843 e--;
844 assert( *e == '.' );
845 name = (char *) xmalloc((e - p) + 1);
846 memcpy(name, p, e - p);
847 name[e - p] = 0;
848 } else
849 name = p;
851 an_output_module = NULL;
852 Array modules; // vs. outmodules... = [an_output_module] or modules
853 modules.reserve(num_in_fnames);
855 // %% FIX
856 if ( ! input_filename ) {
857 ::error("input file name required; cannot use stdin");
858 goto had_errors;
861 if (fonly_arg) {
862 /* In this mode, the first file name is supposed to be
863 a duplicate of one of the input file. */
864 if (strcmp(fonly_arg, input_filename))
865 ::error("-fonly= argument is different from main input file name");
866 if (strcmp(fonly_arg, in_fnames[0]))
867 ::error("-fonly= argument is different from first input file name");
870 //fprintf (stderr, "***** %d files main=%s\n", num_in_fnames, input_filename);
872 for (i = 0; i < num_in_fnames; i++) {
873 if (fonly_arg) {
874 if (i == 0)
875 continue;
876 /* %% Do the other modules really need to be processed?
877 else if (an_output_module)
878 break;
882 //fprintf(stderr, "fn %d = %s\n", i, in_fnames[i]);
884 char * the_fname = (char*) in_fnames[i];
885 bool isDltFile = 0;
887 p = FileName::name(the_fname);
888 e = FileName::ext(p);
889 if (e) {
890 isDltFile = (stricmp(e, "dlt") == 0);
891 e--;
892 assert( *e == '.' );
893 name = (char *) xmalloc((e - p) + 1);
894 memcpy(name, p, e - p);
895 name[e - p] = 0;
897 if (name[0] == 0 ||
898 strcmp(name, "..") == 0 ||
899 strcmp(name, ".") == 0)
901 Linvalid:
902 ::error("invalid file name '%s'", the_fname);
903 goto had_errors;
906 else
907 { name = p;
908 if (!*name)
909 goto Linvalid;
912 id = new Identifier(name, 0);
913 Module * m = new Module(the_fname, id, global.params.doDocComments, global.params.doHdrGeneration, isDltFile);
914 if (! strcmp(in_fnames[i], input_filename))
915 an_output_module = m;
916 modules.push(m);
919 #if V2
920 // There is only one of these so far...
921 rtlsym[RTLSYM_DHIDDENFUNC] =
922 gen.getLibCallDecl(LIBCALL_HIDDEN_FUNC)->toSymbol();
923 #endif
925 // current_module shouldn't have any implications before genobjfile..
926 // ... but it does. We need to know what module in which to insert
927 // TemplateInstanceS during the semantic pass. In order for
928 // -femit-templates=private to work, template instances must be emitted
929 // in every translation unit. To do this, the TemplateInstaceS have to
930 // have toObjFile called in the module being compiled.
931 // TemplateInstance puts itself somwhere during ::semantic, thus it has
932 // to know the current module...
934 assert(an_output_module);
936 Module * m;
938 //global.params.verbose = 1;
940 // Read files, parse them
941 for (i = 0; i < modules.dim; i++)
943 m = (Module *)modules.data[i];
944 if (global.params.verbose)
945 printf("parse %s\n", m->toChars());
946 if (!Module::rootModule)
947 Module::rootModule = m;
948 m->importedFrom = m;
949 //m->deleteObjFile(); // %% driver does this
950 m->read(0);
951 m->parse(global.params.dump_source);
952 d_gcc_magic_module(m);
953 if (m->isDocFile)
955 m->gendocfile();
957 // Remove m from list of modules
958 modules.remove(i);
959 i--;
962 if (global.errors)
963 goto had_errors;
965 #ifdef _DH
966 if (global.params.doHdrGeneration)
968 /* Generate 'header' import files.
969 * Since 'header' import files must be independent of command
970 * line switches and what else is imported, they are generated
971 * before any semantic analysis.
973 for (i = 0; i < modules.dim; i++)
975 m = (Module *)modules.data[i];
976 if (fonly_arg && m != an_output_module)
977 continue;
978 if (global.params.verbose)
979 printf("import %s\n", m->toChars());
980 m->genhdrfile();
983 if (global.errors)
984 fatal();
985 #endif
987 // Do semantic analysis
988 for (i = 0; i < modules.dim; i++)
990 m = (Module *)modules.data[i];
991 if (global.params.verbose)
992 printf("semantic %s\n", m->toChars());
993 m->semantic();
995 if (global.errors)
996 goto had_errors;
998 // Do pass 2 semantic analysis
999 for (i = 0; i < modules.dim; i++)
1001 m = (Module *)modules.data[i];
1002 if (global.params.verbose)
1003 printf("semantic2 %s\n", m->toChars());
1004 m->semantic2();
1006 if (global.errors)
1007 goto had_errors;
1009 // Do pass 3 semantic analysis
1010 for (i = 0; i < modules.dim; i++)
1012 m = (Module *)modules.data[i];
1013 if (global.params.verbose)
1014 printf("semantic3 %s\n", m->toChars());
1015 m->semantic3();
1017 if (global.errors)
1018 goto had_errors;
1020 // Scan for functions to inline
1021 if (global.params.useInline)
1023 for (i = 0; i < modules.dim; i++)
1025 m = (Module *)modules.data[i];
1026 if (global.params.verbose)
1027 printf("inline scan %s\n", m->toChars());
1028 m->inlineScan();
1031 if (global.errors)
1032 fatal();
1034 g.ofile = new ObjectFile();
1035 if (fonly_arg)
1036 g.ofile->modules.push(an_output_module);
1037 else
1038 g.ofile->modules.append(& modules);
1039 g.irs = & gen; // needed for FuncDeclaration::toObjFile shouldDefer check
1041 // Generate output files
1042 for (i = 0; i < modules.dim; i++)
1044 m = (Module *)modules.data[i];
1045 if (fonly_arg && m != an_output_module)
1046 continue;
1047 if (global.params.verbose)
1048 printf("code %s\n", m->toChars());
1049 if (! flag_syntax_only)
1050 m->genobjfile(false);
1051 if (! global.errors && ! errorcount)
1053 if (global.params.doDocComments)
1054 m->gendocfile();
1058 // better to use input_location.xxx ?
1059 (*debug_hooks->end_source_file) (input_line);
1060 had_errors:
1061 // Add DMD error count to GCC error count to to exit with error status
1062 errorcount += global.errors;
1064 g.ofile->finish();
1066 #if D_GCC_VER >= 40
1067 cgraph_finalize_compilation_unit();
1068 #endif
1070 an_output_module = 0;
1072 gcc_d_backend_term();
1075 void
1076 d_gcc_dump_source(const char * srcname, const char * ext, unsigned char * data, unsigned len)
1078 // Note: There is a dump_base_name variable, but as long as the all-sources hack is in
1079 // around, the base name has to be determined here.
1081 /* construct output name */
1082 char* base = (char*) alloca(strlen(srcname)+1);
1083 base = strcpy(base, srcname);
1084 base = basename(base);
1086 char* name = (char*) alloca(strlen(base)+strlen(ext)+2);
1087 name = strcpy(name, base);
1088 if(strlen(ext)>0){
1089 name = strcat(name, ".");
1090 name = strcat(name, ext);
1093 /* output
1094 * ignores if the output file exists
1095 * ignores if the output fails
1097 FILE* output = fopen(name, "w");
1098 if(output){
1099 fwrite(data, 1, len, output);
1100 fclose(output);
1103 /* cleanup */
1104 errno=0;
1108 bool
1109 d_mark_addressable (tree t)
1111 tree x = t;
1112 while (1)
1113 switch (TREE_CODE (x))
1115 case ADDR_EXPR:
1116 case COMPONENT_REF:
1117 /* If D had bit fields, we would need to handle that here */
1118 case ARRAY_REF:
1119 case REALPART_EXPR:
1120 case IMAGPART_EXPR:
1121 x = TREE_OPERAND (x, 0);
1122 break;
1123 /* %% C++ prevents {& this} .... */
1124 /* %% TARGET_EXPR ... */
1125 case TRUTH_ANDIF_EXPR:
1126 case TRUTH_ORIF_EXPR:
1127 case COMPOUND_EXPR:
1128 x = TREE_OPERAND (x, 1);
1129 break;
1131 case COND_EXPR:
1132 return d_mark_addressable (TREE_OPERAND (x, 1))
1133 && d_mark_addressable (TREE_OPERAND (x, 2));
1135 case CONSTRUCTOR:
1136 TREE_ADDRESSABLE (x) = 1;
1137 return true;
1139 case INDIRECT_REF:
1140 /* %% this was in Java, not sure for D */
1141 /* We sometimes add a cast *(TYPE*)&FOO to handle type and mode
1142 incompatibility problems. Handle this case by marking FOO. */
1143 if (TREE_CODE (TREE_OPERAND (x, 0)) == NOP_EXPR
1144 && TREE_CODE (TREE_OPERAND (TREE_OPERAND (x, 0), 0)) == ADDR_EXPR)
1146 x = TREE_OPERAND (TREE_OPERAND (x, 0), 0);
1147 break;
1149 if (TREE_CODE (TREE_OPERAND (x, 0)) == ADDR_EXPR)
1151 x = TREE_OPERAND (x, 0);
1152 break;
1154 return true;
1156 case VAR_DECL:
1157 case CONST_DECL:
1158 case PARM_DECL:
1159 case RESULT_DECL:
1160 #if D_GCC_VER < 40
1161 if ( ! TREE_STATIC(x) ) // %% C doesn't do this check
1162 put_var_into_stack(x, 1);
1163 #endif
1164 // drop through
1165 case FUNCTION_DECL:
1166 TREE_ADDRESSABLE (x) = 1;
1167 /* drops through */
1168 default:
1169 return true;
1172 return 1;
1177 tree
1178 d_type_for_mode (enum machine_mode mode, int unsignedp)
1180 // taken from c-common.c
1181 if (mode == TYPE_MODE (integer_type_node))
1182 return unsignedp ? unsigned_type_node : integer_type_node;
1184 if (mode == TYPE_MODE (signed_char_type_node))
1185 return unsignedp ? unsigned_char_type_node : signed_char_type_node;
1187 if (mode == TYPE_MODE (short_integer_type_node))
1188 return unsignedp ? short_unsigned_type_node : short_integer_type_node;
1190 if (mode == TYPE_MODE (long_integer_type_node))
1191 return unsignedp ? long_unsigned_type_node : long_integer_type_node;
1193 if (mode == TYPE_MODE (long_long_integer_type_node))
1194 return unsignedp ? long_long_unsigned_type_node : long_long_integer_type_node;
1196 /*%% ?
1197 if (mode == TYPE_MODE (widest_integer_literal_type_node))
1198 return unsignedp ? widest_unsigned_literal_type_node
1199 : widest_integer_literal_type_node;
1201 if (mode == QImode)
1202 return unsignedp ? unsigned_intQI_type_node : intQI_type_node;
1204 if (mode == HImode)
1205 return unsignedp ? unsigned_intHI_type_node : intHI_type_node;
1207 if (mode == SImode)
1208 return unsignedp ? unsigned_intSI_type_node : intSI_type_node;
1210 if (mode == DImode)
1211 return unsignedp ? unsigned_intDI_type_node : intDI_type_node;
1213 #if HOST_BITS_PER_WIDE_INT >= 64
1214 if (mode == TYPE_MODE (intTI_type_node))
1215 return unsignedp ? unsigned_intTI_type_node : intTI_type_node;
1216 #endif
1218 if (mode == TYPE_MODE (float_type_node))
1219 return float_type_node;
1221 if (mode == TYPE_MODE (double_type_node))
1222 return double_type_node;
1224 if (mode == TYPE_MODE (long_double_type_node))
1225 return long_double_type_node;
1227 if (mode == TYPE_MODE (build_pointer_type (char_type_node)))
1228 return build_pointer_type (char_type_node);
1230 if (mode == TYPE_MODE (build_pointer_type (integer_type_node)))
1231 return build_pointer_type (integer_type_node);
1233 #if D_GCC_VER < 40
1234 switch (mode)
1236 case V16QImode:
1237 return unsignedp ? unsigned_V16QI_type_node : V16QI_type_node;
1238 case V8HImode:
1239 return unsignedp ? unsigned_V8HI_type_node : V8HI_type_node;
1240 case V4SImode:
1241 return unsignedp ? unsigned_V4SI_type_node : V4SI_type_node;
1242 case V2DImode:
1243 return unsignedp ? unsigned_V2DI_type_node : V2DI_type_node;
1244 case V2SImode:
1245 return unsignedp ? unsigned_V2SI_type_node : V2SI_type_node;
1246 case V2HImode:
1247 return unsignedp ? unsigned_V2HI_type_node : V2HI_type_node;
1248 case V4HImode:
1249 return unsignedp ? unsigned_V4HI_type_node : V4HI_type_node;
1250 case V8QImode:
1251 return unsignedp ? unsigned_V8QI_type_node : V8QI_type_node;
1252 case V1DImode:
1253 return unsignedp ? unsigned_V1DI_type_node : V1DI_type_node;
1254 case V16SFmode:
1255 return V16SF_type_node;
1256 case V4SFmode:
1257 return V4SF_type_node;
1258 case V2SFmode:
1259 return V2SF_type_node;
1260 case V2DFmode:
1261 return V2DF_type_node;
1262 default:
1263 break;
1265 #else
1266 if (COMPLEX_MODE_P (mode))
1268 enum machine_mode inner_mode;
1269 tree inner_type;
1271 if (mode == TYPE_MODE (complex_float_type_node))
1272 return complex_float_type_node;
1273 if (mode == TYPE_MODE (complex_double_type_node))
1274 return complex_double_type_node;
1275 if (mode == TYPE_MODE (complex_long_double_type_node))
1276 return complex_long_double_type_node;
1278 if (mode == TYPE_MODE (complex_integer_type_node) && !unsignedp)
1279 return complex_integer_type_node;
1281 inner_mode = (machine_mode) GET_MODE_INNER (mode);
1282 inner_type = d_type_for_mode (inner_mode, unsignedp);
1283 if (inner_type != NULL_TREE)
1284 return build_complex_type (inner_type);
1286 else if (VECTOR_MODE_P (mode))
1288 enum machine_mode inner_mode = (machine_mode) GET_MODE_INNER (mode);
1289 tree inner_type = d_type_for_mode (inner_mode, unsignedp);
1290 if (inner_type != NULL_TREE)
1291 return build_vector_type_for_mode (inner_type, mode);
1293 #endif
1295 return 0;
1298 tree
1299 d_type_for_size (unsigned bits, int unsignedp)
1301 if (bits == TYPE_PRECISION (integer_type_node))
1302 return unsignedp ? unsigned_type_node : integer_type_node;
1304 if (bits == TYPE_PRECISION (signed_char_type_node))
1305 return unsignedp ? unsigned_char_type_node : signed_char_type_node;
1307 if (bits == TYPE_PRECISION (short_integer_type_node))
1308 return unsignedp ? short_unsigned_type_node : short_integer_type_node;
1310 if (bits == TYPE_PRECISION (long_integer_type_node))
1311 return unsignedp ? long_unsigned_type_node : long_integer_type_node;
1313 if (bits == TYPE_PRECISION (long_long_integer_type_node))
1314 return (unsignedp ? long_long_unsigned_type_node
1315 : long_long_integer_type_node);
1316 /* %%?
1317 if (bits == TYPE_PRECISION (widest_integer_literal_type_node))
1318 return (unsignedp ? widest_unsigned_literal_type_node
1319 : widest_integer_literal_type_node);
1321 if (bits <= TYPE_PRECISION (intQI_type_node))
1322 return unsignedp ? unsigned_intQI_type_node : intQI_type_node;
1324 if (bits <= TYPE_PRECISION (intHI_type_node))
1325 return unsignedp ? unsigned_intHI_type_node : intHI_type_node;
1327 if (bits <= TYPE_PRECISION (intSI_type_node))
1328 return unsignedp ? unsigned_intSI_type_node : intSI_type_node;
1330 if (bits <= TYPE_PRECISION (intDI_type_node))
1331 return unsignedp ? unsigned_intDI_type_node : intDI_type_node;
1333 return 0;
1336 tree
1337 d_unsigned_type (tree type)
1339 tree type1 = TYPE_MAIN_VARIANT (type);
1340 if (type1 == signed_char_type_node || type1 == char_type_node)
1341 return unsigned_char_type_node;
1342 if (type1 == integer_type_node)
1343 return unsigned_type_node;
1344 if (type1 == short_integer_type_node)
1345 return short_unsigned_type_node;
1346 if (type1 == long_integer_type_node)
1347 return long_unsigned_type_node;
1348 if (type1 == long_long_integer_type_node)
1349 return long_long_unsigned_type_node;
1350 /* %%?
1351 if (type1 == widest_integer_literal_type_node)
1352 return widest_unsigned_literal_type_node;
1354 #if HOST_BITS_PER_WIDE_INT >= 64
1355 if (type1 == intTI_type_node)
1356 return unsigned_intTI_type_node;
1357 #endif
1358 if (type1 == intDI_type_node)
1359 return unsigned_intDI_type_node;
1360 if (type1 == intSI_type_node)
1361 return unsigned_intSI_type_node;
1362 if (type1 == intHI_type_node)
1363 return unsigned_intHI_type_node;
1364 if (type1 == intQI_type_node)
1365 return unsigned_intQI_type_node;
1367 return d_signed_or_unsigned_type (1, type);
1370 tree
1371 d_signed_type (tree type)
1373 tree type1 = TYPE_MAIN_VARIANT (type);
1374 if (type1 == unsigned_char_type_node || type1 == char_type_node)
1375 return signed_char_type_node;
1376 if (type1 == unsigned_type_node)
1377 return integer_type_node;
1378 if (type1 == short_unsigned_type_node)
1379 return short_integer_type_node;
1380 if (type1 == long_unsigned_type_node)
1381 return long_integer_type_node;
1382 if (type1 == long_long_unsigned_type_node)
1383 return long_long_integer_type_node;
1385 if (type1 == widest_unsigned_literal_type_node)
1386 return widest_integer_literal_type_node;
1388 #if HOST_BITS_PER_WIDE_INT >= 64
1389 if (type1 == unsigned_intTI_type_node)
1390 return intTI_type_node;
1391 #endif
1392 if (type1 == unsigned_intDI_type_node)
1393 return intDI_type_node;
1394 if (type1 == unsigned_intSI_type_node)
1395 return intSI_type_node;
1396 if (type1 == unsigned_intHI_type_node)
1397 return intHI_type_node;
1398 if (type1 == unsigned_intQI_type_node)
1399 return intQI_type_node;
1401 return d_signed_or_unsigned_type (0, type);
1404 tree
1405 d_signed_or_unsigned_type (int unsignedp, tree type)
1407 if (! INTEGRAL_TYPE_P (type)
1408 || TREE_UNSIGNED (type) == (unsigned) unsignedp)
1409 return type;
1411 if (TYPE_PRECISION (type) == TYPE_PRECISION (signed_char_type_node))
1412 return unsignedp ? unsigned_char_type_node : signed_char_type_node;
1413 if (TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node))
1414 return unsignedp ? unsigned_type_node : integer_type_node;
1415 if (TYPE_PRECISION (type) == TYPE_PRECISION (short_integer_type_node))
1416 return unsignedp ? short_unsigned_type_node : short_integer_type_node;
1417 if (TYPE_PRECISION (type) == TYPE_PRECISION (long_integer_type_node))
1418 return unsignedp ? long_unsigned_type_node : long_integer_type_node;
1419 if (TYPE_PRECISION (type) == TYPE_PRECISION (long_long_integer_type_node))
1420 return (unsignedp ? long_long_unsigned_type_node
1421 : long_long_integer_type_node);
1422 /* %%?
1423 if (TYPE_PRECISION (type) == TYPE_PRECISION (widest_integer_literal_type_node))
1424 return (unsignedp ? widest_unsigned_literal_type_node
1425 : widest_integer_literal_type_node);
1427 #if HOST_BITS_PER_WIDE_INT >= 64
1428 if (TYPE_PRECISION (type) == TYPE_PRECISION (intTI_type_node))
1429 return unsignedp ? unsigned_intTI_type_node : intTI_type_node;
1430 #endif
1431 if (TYPE_PRECISION (type) == TYPE_PRECISION (intDI_type_node))
1432 return unsignedp ? unsigned_intDI_type_node : intDI_type_node;
1433 if (TYPE_PRECISION (type) == TYPE_PRECISION (intSI_type_node))
1434 return unsignedp ? unsigned_intSI_type_node : intSI_type_node;
1435 if (TYPE_PRECISION (type) == TYPE_PRECISION (intHI_type_node))
1436 return unsignedp ? unsigned_intHI_type_node : intHI_type_node;
1437 if (TYPE_PRECISION (type) == TYPE_PRECISION (intQI_type_node))
1438 return unsignedp ? unsigned_intQI_type_node : intQI_type_node;
1440 return type;
1443 #if D_GCC_VER < 40
1444 #define TYPE_UNSIGNED TREE_UNSIGNED
1445 #endif
1447 /* Type promotion for variable arguments. */
1448 tree
1449 d_type_promotes_to (tree type)
1451 /* Almost the same as c_type_promotes_to. This is needed varargs to work on
1452 certain targets. */
1453 if (TYPE_MAIN_VARIANT (type) == float_type_node)
1454 return double_type_node;
1456 // not quite the same as... if (c_promoting_integer_type_p (type))
1457 if (INTEGRAL_TYPE_P (type) &&
1458 (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)) )
1460 /* Preserve unsignedness if not really getting any wider. */
1461 if (TYPE_UNSIGNED (type)
1462 && (TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node)))
1463 return unsigned_type_node;
1464 return integer_type_node;
1467 return type;
1471 extern "C" void pushlevel PARAMS ((int));
1472 extern "C" tree poplevel PARAMS ((int, int, int));
1473 extern "C" int global_bindings_p PARAMS ((void));
1474 extern "C" void insert_block PARAMS ((tree));
1475 extern "C" void set_block PARAMS ((tree));
1476 extern "C" tree getdecls PARAMS ((void));
1479 struct binding_level * current_binding_level;
1480 struct binding_level * global_binding_level;
1483 static binding_level *
1484 alloc_binding_level()
1486 return (struct binding_level *) ggc_alloc_cleared (sizeof (struct binding_level));
1489 /* The D front-end does not use the 'binding level' system for a symbol table,
1490 It is only needed to get debugging information for local variables and
1491 otherwise support the backend. */
1493 void
1494 pushlevel (int /*arg*/)
1496 binding_level * new_level = alloc_binding_level();
1497 new_level->level_chain = current_binding_level;
1498 current_binding_level = new_level;
1501 tree
1502 poplevel (int keep, int reverse, int routinebody)
1504 binding_level * level = current_binding_level;
1505 tree block, decls;
1507 current_binding_level = level->level_chain;
1508 decls = level->names;
1509 if (reverse)
1510 decls = nreverse(decls);
1512 if ( level->this_block )
1513 block = level->this_block;
1514 else if (keep || routinebody)
1515 block = make_node(BLOCK);
1516 else
1517 block = NULL_TREE;
1519 if (block) {
1520 BLOCK_VARS( block ) = routinebody ? NULL_TREE : decls;
1521 BLOCK_SUBBLOCKS( block ) = level->blocks;
1522 // %% need this for when insert_block is called by backend... or make
1523 // insert_block do it's work elsewere
1524 // BLOCK_SUBBLOCKS( block ) = level->blocks;
1525 // %% pascal does: in each subblock, record that this is the superiod..
1527 /* In each subblock, record that this is its superior. */
1528 for (tree t = level->blocks; t; t = TREE_CHAIN (t))
1529 BLOCK_SUPERCONTEXT (t) = block;
1530 /* Dispose of the block that we just made inside some higher level. */
1531 if (routinebody)
1532 DECL_INITIAL (current_function_decl) = block;
1533 else if (block)
1535 // Original logic was: If this block was created by this poplevel
1536 // call and not and earlier set_block, insert it into the parent's
1537 // list of blocks. Blocks created with set_block have to be
1538 // inserted with insert_block.
1540 // For D, currently always using set_block/insert_block
1541 if (!level->this_block)
1542 current_binding_level->blocks = chainon (current_binding_level->blocks, block);
1544 /* If we did not make a block for the level just exited, any blocks made for inner
1545 levels (since they cannot be recorded as subblocks in that level) must be
1546 carried forward so they will later become subblocks of something else. */
1547 else if (level->blocks)
1548 current_binding_level->blocks = chainon (current_binding_level->blocks, level->blocks);
1549 if (block)
1550 TREE_USED (block) = 1;
1551 return block;
1555 global_bindings_p (void)
1557 // This is called by the backend before parsing. Need to make this do
1558 // something or lang_hooks.clear_binding_stack (lhd_clear_binding_stack)
1559 // loops forever.
1560 return current_binding_level == global_binding_level || ! global_binding_level;
1563 void
1564 init_global_binding_level()
1566 current_binding_level = global_binding_level = alloc_binding_level();
1570 void
1571 insert_block (tree block)
1573 TREE_USED (block) = 1;
1574 current_binding_level->blocks = chainon (current_binding_level->blocks, block);
1577 void
1578 set_block (tree block)
1580 current_binding_level->this_block = block;
1583 tree
1584 pushdecl (tree decl)
1586 // %% Pascal: if not a local external routine decl doesn't consitite nesting
1588 // %% probably should be cur_irs->getDeclContext()
1589 // %% should only be for variables OR, should also use TRANSLATION_UNIT for toplevel..
1590 if ( DECL_CONTEXT( decl ) == NULL_TREE )
1591 DECL_CONTEXT( decl ) = current_function_decl; // could be NULL_TREE (top level) .. hmm. // hm.m.
1593 /* Put decls on list in reverse order. We will reverse them later if necessary. */
1594 TREE_CHAIN (decl) = current_binding_level->names;
1595 current_binding_level->names = decl;
1596 if (!TREE_CHAIN (decl))
1597 current_binding_level->names_end = decl;
1598 return decl;
1601 /* pushdecl_top_level is only for building with Apple GCC. */
1602 extern "C" tree
1603 pushdecl_top_level (tree x)
1605 tree t;
1606 struct binding_level *b = current_binding_level;
1608 current_binding_level = global_binding_level;
1609 t = pushdecl (x);
1610 current_binding_level = b;
1611 return t;
1615 void
1616 set_decl_binding_chain(tree decl_chain)
1618 assert(current_binding_level);
1619 current_binding_level->names = decl_chain;
1623 // Supports dbx and stabs
1624 tree
1625 getdecls ()
1627 if (current_binding_level)
1628 return current_binding_level->names;
1629 else
1630 return NULL_TREE;
1634 /* Tree code classes. */
1636 #undef DEFTREECODE
1637 #define DEFTREECODE(SYM, NAME, TYPE, LENGTH) TYPE,
1639 #if D_GCC_VER < 40
1640 const char
1641 tree_code_type[] = {
1642 #include "tree.def"
1643 'x',
1644 #include "dlt/d-tree.def"
1647 #else
1649 const enum tree_code_class
1650 tree_code_type[] = {
1651 #include "tree.def"
1652 tcc_exceptional,
1653 #include "dlt/d-tree.def"
1655 #endif
1657 #undef DEFTREECODE
1659 /* Table indexed by tree code giving number of expression
1660 operands beyond the fixed part of the node structure.
1661 Not used for types or decls. */
1663 #define DEFTREECODE(SYM, NAME, TYPE, LENGTH) LENGTH,
1665 const unsigned char tree_code_length[] = {
1666 #include "tree.def"
1668 #include "dlt/d-tree.def"
1670 #undef DEFTREECODE
1672 /* Names of tree components.
1673 Used for printing out the tree and error messages. */
1674 #define DEFTREECODE(SYM, NAME, TYPE, LEN) NAME,
1676 const char *const tree_code_name[] = {
1677 #include "tree.def"
1678 "@@dummy",
1679 #include "dlt/d-tree.def"
1681 #undef DEFTREECODE
1683 #if D_GCC_VER >= 40
1685 static void
1686 d_expand_function(tree fndecl)
1688 if (!DECL_INITIAL (fndecl)
1689 || DECL_INITIAL (fndecl) == error_mark_node)
1690 return;
1692 bool save_flag = flag_omit_frame_pointer;
1693 flag_omit_frame_pointer = gen.originalOmitFramePointer ||
1694 D_DECL_NO_FRAME_POINTER( fndecl );
1696 tree_rest_of_compilation (fndecl);
1698 flag_omit_frame_pointer = save_flag;
1700 if (DECL_STATIC_CONSTRUCTOR (fndecl)
1701 && targetm.have_ctors_dtors)
1702 targetm.asm_out.constructor (XEXP (DECL_RTL (fndecl), 0),
1703 DEFAULT_INIT_PRIORITY);
1704 if (DECL_STATIC_DESTRUCTOR (fndecl)
1705 && targetm.have_ctors_dtors)
1706 targetm.asm_out.destructor (XEXP (DECL_RTL (fndecl), 0),
1707 DEFAULT_INIT_PRIORITY);
1710 #endif
1712 #if D_GCC_VER >= 40
1713 static int
1714 d_types_compatible_p (tree x, tree y)
1716 if (lhd_types_compatible_p(x, y))
1717 return 1;
1718 else if (d_gcc_builtin_va_list_d_type &&
1720 ( x == d_gcc_builtin_va_list_d_type->ctype &&
1721 y == va_list_type_node ) ||
1722 ( y == d_gcc_builtin_va_list_d_type->ctype &&
1723 x == va_list_type_node ) ))
1724 return 1;
1725 else
1726 return 0;
1728 return TYPE_MAIN_VARIANT (x) == TYPE_MAIN_VARIANT (y);
1731 #if V2
1733 /* DMD 2 makes a parameter delclaration's type 'const(T)' if the
1734 parameter is a simple STCin or STCconst. The TypeFunction's
1735 Argument's type stays unqualified, however.
1737 This mismatch causes a problem with optimization and inlining. For
1738 RECORD_TYPE arguments, failure will occur in (setup_one_parameter
1739 -> fold_convert). d_types_compatible_p hacks lead to failures in
1740 the sra pass.
1742 Fortunately, the middle end provides a simple workaround by using
1743 this hook.
1746 tree
1747 d_convert_parm_for_inlining (tree parm, tree value, tree fndecl, int argnum)
1749 if (TREE_TYPE(parm) != TREE_TYPE(value))
1750 return build1(NOP_EXPR, TREE_TYPE(parm), value);
1751 else
1752 return value;
1754 #endif
1756 #endif
1759 struct lang_type *
1760 build_d_type_lang_specific(Type * t)
1762 struct lang_type * l = (struct lang_type *) ggc_alloc_cleared( sizeof(struct lang_type) );
1763 l->d_type = t;
1764 return l;
1767 tree d_keep_list = NULL_TREE;
1769 void
1770 dkeep(tree t)
1772 d_keep_list = tree_cons(NULL_TREE, t, d_keep_list);
1776 const struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;