1/* d-lang.cc -- Language-dependent hooks for D.
2   Copyright (C) 2006-2020 Free Software Foundation, Inc.
3
4GCC is free software; you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
6the Free Software Foundation; either version 3, or (at your option)
7any later version.
8
9GCC is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with GCC; see the file COPYING3.  If not see
16<http://www.gnu.org/licenses/>.  */
17
18#include "config.h"
19#include "system.h"
20#include "coretypes.h"
21
22#include "dmd/aggregate.h"
23#include "dmd/cond.h"
24#include "dmd/declaration.h"
25#include "dmd/doc.h"
26#include "dmd/errors.h"
27#include "dmd/expression.h"
28#include "dmd/hdrgen.h"
29#include "dmd/identifier.h"
30#include "dmd/json.h"
31#include "dmd/mangle.h"
32#include "dmd/mars.h"
33#include "dmd/module.h"
34#include "dmd/mtype.h"
35#include "dmd/target.h"
36
37#include "opts.h"
38#include "alias.h"
39#include "tree.h"
40#include "diagnostic.h"
41#include "fold-const.h"
42#include "toplev.h"
43#include "langhooks.h"
44#include "langhooks-def.h"
45#include "target.h"
46#include "stringpool.h"
47#include "stor-layout.h"
48#include "varasm.h"
49#include "output.h"
50#include "print-tree.h"
51#include "gimple-expr.h"
52#include "gimplify.h"
53#include "debug.h"
54
55#include "d-tree.h"
56#include "id.h"
57
58
59/* Array of D frontend type/decl nodes.  */
60tree d_global_trees[DTI_MAX];
61
62/* True if compilation is currently inside the D frontend semantic passes.  */
63bool doing_semantic_analysis_p = false;
64
65/* Options handled by the compiler that are separate from the frontend.  */
66struct d_option_data
67{
68  const char *fonly;		    /* -fonly=<arg>  */
69  const char *multilib;		    /* -imultilib <dir>  */
70  const char *prefix;		    /* -iprefix <dir>  */
71
72  bool deps;			    /* -M  */
73  bool deps_skip_system;	    /* -MM  */
74  const char *deps_filename;	    /* -M[M]D  */
75  const char *deps_filename_user;   /* -MF <arg>  */
76  OutBuffer *deps_target;	    /* -M[QT] <arg> */
77  bool deps_phony;		    /* -MP  */
78
79  bool stdinc;			    /* -nostdinc  */
80}
81d_option;
82
83/* List of modules being compiled.  */
84static Modules builtin_modules;
85
86/* Module where `C main' is defined, compiled in if needed.  */
87static Module *entrypoint_module = NULL;
88static Module *entrypoint_root_module = NULL;
89
90/* The current and global binding level in effect.  */
91struct binding_level *current_binding_level;
92struct binding_level *global_binding_level;
93
94/* The context to be used for global declarations.  */
95static GTY(()) tree global_context;
96
97/* Array of all global declarations to pass back to the middle-end.  */
98static GTY(()) vec<tree, va_gc> *global_declarations;
99
100/* Support for GCC-style command-line make dependency generation.
101   Adds TARGET to the make dependencies target buffer.
102   QUOTED is true if the string should be quoted.  */
103
104static void
105deps_add_target (const char *target, bool quoted)
106{
107  if (!d_option.deps_target)
108    d_option.deps_target = new OutBuffer ();
109  else
110    d_option.deps_target->writeByte (' ');
111
112  d_option.deps_target->reserve (strlen (target));
113
114  if (!quoted)
115    {
116      d_option.deps_target->writestring (target);
117      return;
118    }
119
120  /* Quote characters in target which are significant to Make.  */
121  for (const char *p = target; *p != '\0'; p++)
122    {
123      switch (*p)
124	{
125	case ' ':
126	case '\t':
127	  for (const char *q = p - 1; target <= q && *q == '\\';  q--)
128	    d_option.deps_target->writeByte ('\\');
129	  d_option.deps_target->writeByte ('\\');
130	  break;
131
132	case '$':
133	  d_option.deps_target->writeByte ('$');
134	  break;
135
136	case '#':
137	  d_option.deps_target->writeByte ('\\');
138	  break;
139
140	default:
141	  break;
142	}
143
144      d_option.deps_target->writeByte (*p);
145    }
146}
147
148/* Write out all dependencies of a given MODULE to the specified BUFFER.
149   COLMAX is the number of columns to word-wrap at (0 means don't wrap).  */
150
151static void
152deps_write (Module *module, OutBuffer *buffer, unsigned colmax = 72)
153{
154  hash_set <const char *> seen_modules;
155  vec <const char *> dependencies = vNULL;
156
157  Modules modlist;
158  modlist.push (module);
159
160  vec <const char *> phonylist = vNULL;
161  unsigned column = 0;
162
163  /* Write out make target module name.  */
164  if (d_option.deps_target)
165    {
166      buffer->writestring (d_option.deps_target->extractString ());
167      column = d_option.deps_target->offset;
168    }
169  else
170    {
171      buffer->writestring (module->objfile->name->str);
172      column = buffer->offset;
173    }
174
175  buffer->writestring (":");
176  column++;
177
178  /* Search all modules for file dependencies.  */
179  while (modlist.dim > 0)
180    {
181      Module *depmod = modlist.pop ();
182
183      const char *modstr = depmod->srcfile->name->str;
184
185      /* Skip modules that have already been looked at.  */
186      if (seen_modules.add (modstr))
187	continue;
188
189      dependencies.safe_push (modstr);
190
191      /* Add to list of phony targets if is not being compile.  */
192      if (d_option.deps_phony && !depmod->isRoot ())
193	phonylist.safe_push (modstr);
194
195      /* Add imported files to dependency list.  */
196      for (size_t i = 0; i < depmod->contentImportedFiles.dim; i++)
197	{
198	  const char *impstr = depmod->contentImportedFiles[i];
199	  dependencies.safe_push (impstr);
200	  phonylist.safe_push (impstr);
201	}
202
203      /* Search all imports of the module.  */
204      for (size_t i = 0; i < depmod->aimports.dim; i++)
205	{
206	  Module *m = depmod->aimports[i];
207
208	  /* Ignore compiler-generated modules.  */
209	  if ((m->ident == Identifier::idPool ("__entrypoint")
210	       || m->ident == Identifier::idPool ("__main"))
211	      && m->parent == NULL)
212	    continue;
213
214	  /* Don't search system installed modules, this includes
215	     object, core.*, std.*, and gcc.* packages.  */
216	  if (d_option.deps_skip_system)
217	    {
218	      if (m->ident == Identifier::idPool ("object")
219		  && m->parent == NULL)
220		continue;
221
222	      if (m->md && m->md->packages)
223		{
224		  Identifier *package = (*m->md->packages)[0];
225
226		  if (package == Identifier::idPool ("core")
227		      || package == Identifier::idPool ("std")
228		      || package == Identifier::idPool ("gcc"))
229		    continue;
230		}
231	    }
232
233	  modlist.push (m);
234	}
235    }
236
237  /* Write out all make dependencies.  */
238  for (size_t i = 0; i < dependencies.length (); i++)
239    {
240      const char *str = dependencies[i];
241      unsigned size = strlen (str);
242      column += size;
243
244      if (colmax && column > colmax)
245	{
246	  buffer->writestring (" \\\n ");
247	  column = size + 1;
248	}
249      else
250	{
251	  buffer->writestring (" ");
252	  column++;
253	}
254
255      buffer->writestring (str);
256    }
257
258  buffer->writenl ();
259
260  /* Write out all phony targets.  */
261  for (size_t i = 0; i < phonylist.length (); i++)
262    {
263      buffer->writenl ();
264      buffer->writestring (phonylist[i]);
265      buffer->writestring (":\n");
266    }
267}
268
269/* Implements the lang_hooks.init_options routine for language D.
270   This initializes the global state for the D frontend before calling
271   the option handlers.  */
272
273static void
274d_init_options (unsigned int, cl_decoded_option *decoded_options)
275{
276  /* Set default values.  */
277  global._init ();
278
279  global.vendor = lang_hooks.name;
280  global.params.argv0 = xstrdup (decoded_options[0].arg);
281  global.params.link = true;
282  global.params.useAssert = true;
283  global.params.useInvariants = true;
284  global.params.useIn = true;
285  global.params.useOut = true;
286  global.params.useArrayBounds = BOUNDSCHECKdefault;
287  global.params.useSwitchError = true;
288  global.params.useModuleInfo = true;
289  global.params.useTypeInfo = true;
290  global.params.useExceptions = true;
291  global.params.useInline = false;
292  global.params.obj = true;
293  global.params.hdrStripPlainFunctions = true;
294  global.params.betterC = false;
295  global.params.allInst = false;
296
297  /* Default extern(C++) mangling to C++14.  */
298  global.params.cplusplus = CppStdRevisionCpp14;
299
300  global.params.linkswitches = new Strings ();
301  global.params.libfiles = new Strings ();
302  global.params.objfiles = new Strings ();
303  global.params.ddocfiles = new Strings ();
304
305  /* Warnings and deprecations are disabled by default.  */
306  global.params.useDeprecated = DIAGNOSTICoff;
307  global.params.warnings = DIAGNOSTICoff;
308
309  global.params.imppath = new Strings ();
310  global.params.fileImppath = new Strings ();
311  global.params.modFileAliasStrings = new Strings ();
312
313  /* Extra GDC-specific options.  */
314  d_option.fonly = NULL;
315  d_option.multilib = NULL;
316  d_option.prefix = NULL;
317  d_option.deps = false;
318  d_option.deps_skip_system = false;
319  d_option.deps_filename = NULL;
320  d_option.deps_filename_user = NULL;
321  d_option.deps_target = NULL;
322  d_option.deps_phony = false;
323  d_option.stdinc = true;
324}
325
326/* Implements the lang_hooks.init_options_struct routine for language D.
327   Initializes the options structure OPTS.  */
328
329static void
330d_init_options_struct (gcc_options *opts)
331{
332  /* GCC options.  */
333  opts->x_flag_exceptions = 1;
334
335  /* Avoid range issues for complex multiply and divide.  */
336  opts->x_flag_complex_method = 2;
337
338  /* Unlike C, there is no global 'errno' variable.  */
339  opts->x_flag_errno_math = 0;
340  opts->frontend_set_flag_errno_math = true;
341
342  /* Keep in sync with existing -fbounds-check flag.  */
343  opts->x_flag_bounds_check = global.params.useArrayBounds;
344
345  /* D says that signed overflow is precisely defined.  */
346  opts->x_flag_wrapv = 1;
347}
348
349/* Implements the lang_hooks.lang_mask routine for language D.
350   Returns language mask for option parsing.  */
351
352static unsigned int
353d_option_lang_mask (void)
354{
355  return CL_D;
356}
357
358/* Implements the lang_hooks.init routine for language D.  */
359
360static bool
361d_init (void)
362{
363  Type::_init ();
364  Id::initialize ();
365  Module::_init ();
366  Expression::_init ();
367  Objc::_init ();
368
369  /* Back-end init.  */
370  global_binding_level = ggc_cleared_alloc<binding_level> ();
371  current_binding_level = global_binding_level;
372
373  /* This allows the code in d-builtins.cc to not have to worry about
374     converting (C signed char *) to (D char *) for string arguments of
375     built-in functions.  The parameter (signed_char = false) specifies
376     whether char is signed.  */
377  build_common_tree_nodes (false);
378
379  d_init_builtins ();
380
381  if (flag_exceptions)
382    using_eh_for_cleanups ();
383
384  if (!supports_one_only ())
385    flag_weak = 0;
386
387  /* This is the C main, not the D main.  */
388  main_identifier_node = get_identifier ("main");
389
390  Target::_init ();
391  d_init_versions ();
392
393  /* Insert all library-configured identifiers and import paths.  */
394  add_import_paths (d_option.prefix, d_option.multilib, d_option.stdinc);
395
396  return 1;
397}
398
399/* Implements the lang_hooks.init_ts routine for language D.  */
400
401static void
402d_init_ts (void)
403{
404  MARK_TS_TYPED (FLOAT_MOD_EXPR);
405  MARK_TS_TYPED (UNSIGNED_RSHIFT_EXPR);
406}
407
408/* Implements the lang_hooks.handle_option routine for language D.
409   Handles D specific options.  Return false if we didn't do anything.  */
410
411static bool
412d_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value,
413		 int kind ATTRIBUTE_UNUSED,
414		 location_t loc ATTRIBUTE_UNUSED,
415		 const cl_option_handlers *handlers ATTRIBUTE_UNUSED)
416{
417  opt_code code = (opt_code) scode;
418  bool result = true;
419
420  switch (code)
421    {
422    case OPT_fall_instantiations:
423      global.params.allInst = value;
424      break;
425
426    case OPT_fassert:
427      global.params.useAssert = value;
428      break;
429
430    case OPT_fbounds_check:
431      global.params.useArrayBounds = value
432	? BOUNDSCHECKon : BOUNDSCHECKoff;
433      break;
434
435    case OPT_fbounds_check_:
436      global.params.useArrayBounds = (value == 2) ? BOUNDSCHECKon
437	: (value == 1) ? BOUNDSCHECKsafeonly : BOUNDSCHECKoff;
438      break;
439
440    case OPT_fdebug:
441      global.params.debuglevel = value ? 1 : 0;
442      break;
443
444    case OPT_fdebug_:
445      if (ISDIGIT (arg[0]))
446	{
447	  int level = integral_argument (arg);
448	  if (level != -1)
449	    {
450	      DebugCondition::setGlobalLevel (level);
451	      break;
452	    }
453	}
454
455      if (Identifier::isValidIdentifier (CONST_CAST (char *, arg)))
456	{
457	  DebugCondition::addGlobalIdent (arg);
458	  break;
459	}
460
461      error ("bad argument for %<-fdebug%>: %qs", arg);
462      break;
463
464    case OPT_fdoc:
465      global.params.doDocComments = value;
466      break;
467
468    case OPT_fdoc_dir_:
469      global.params.doDocComments = true;
470      global.params.docdir = arg;
471      break;
472
473    case OPT_fdoc_file_:
474      global.params.doDocComments = true;
475      global.params.docname = arg;
476      break;
477
478    case OPT_fdoc_inc_:
479      global.params.ddocfiles->push (arg);
480      break;
481
482    case OPT_fdruntime:
483      global.params.betterC = !value;
484      break;
485
486    case OPT_fdump_d_original:
487      global.params.vcg_ast = value;
488      break;
489
490    case OPT_fexceptions:
491      global.params.useExceptions = value;
492      break;
493
494    case OPT_fignore_unknown_pragmas:
495      global.params.ignoreUnsupportedPragmas = value;
496      break;
497
498    case OPT_finvariants:
499      global.params.useInvariants = value;
500      break;
501
502    case OPT_fmain:
503      global.params.addMain = value;
504      break;
505
506    case OPT_fmodule_file_:
507      global.params.modFileAliasStrings->push (arg);
508      if (!strchr (arg, '='))
509	error ("bad argument for %<-fmodule-file%>: %qs", arg);
510      break;
511
512    case OPT_fmoduleinfo:
513      global.params.useModuleInfo = value;
514      break;
515
516    case OPT_fonly_:
517      d_option.fonly = arg;
518      break;
519
520    case OPT_fpostconditions:
521      global.params.useOut = value;
522      break;
523
524    case OPT_fpreconditions:
525      global.params.useIn = value;
526      break;
527
528    case OPT_frelease:
529      global.params.release = value;
530      break;
531
532    case OPT_frtti:
533      global.params.useTypeInfo = value;
534      break;
535
536    case OPT_fswitch_errors:
537      global.params.useSwitchError = value;
538      break;
539
540    case OPT_ftransition_all:
541      global.params.vtls = value;
542      global.params.vfield = value;
543      global.params.vcomplex = value;
544      break;
545
546    case OPT_ftransition_checkimports:
547      global.params.check10378 = value;
548      break;
549
550    case OPT_ftransition_complex:
551      global.params.vcomplex = value;
552      break;
553
554    case OPT_ftransition_dip1000:
555      global.params.vsafe = value;
556      global.params.useDIP25 = value;
557      break;
558
559    case OPT_ftransition_dip25:
560      global.params.useDIP25 = value;
561      break;
562
563    case OPT_ftransition_field:
564      global.params.vfield = value;
565      break;
566
567    case OPT_ftransition_import:
568      global.params.bug10378 = value;
569      break;
570
571    case OPT_ftransition_nogc:
572      global.params.vgc = value;
573      break;
574
575    case OPT_ftransition_tls:
576      global.params.vtls = value;
577      break;
578
579    case OPT_funittest:
580      global.params.useUnitTests = value;
581      break;
582
583    case OPT_fversion_:
584      if (ISDIGIT (arg[0]))
585	{
586	  int level = integral_argument (arg);
587	  if (level != -1)
588	    {
589	      VersionCondition::setGlobalLevel (level);
590	      break;
591	    }
592	}
593
594      if (Identifier::isValidIdentifier (CONST_CAST (char *, arg)))
595	{
596	  VersionCondition::addGlobalIdent (arg);
597	  break;
598	}
599
600      error ("bad argument for %<-fversion%>: %qs", arg);
601      break;
602
603    case OPT_H:
604      global.params.doHdrGeneration = true;
605      break;
606
607    case OPT_Hd:
608      global.params.doHdrGeneration = true;
609      global.params.hdrdir = arg;
610      break;
611
612    case OPT_Hf:
613      global.params.doHdrGeneration = true;
614      global.params.hdrname = arg;
615      break;
616
617    case OPT_imultilib:
618      d_option.multilib = arg;
619      break;
620
621    case OPT_iprefix:
622      d_option.prefix = arg;
623      break;
624
625    case OPT_I:
626      global.params.imppath->push (arg);
627      break;
628
629    case OPT_J:
630      global.params.fileImppath->push (arg);
631      break;
632
633    case OPT_MM:
634      d_option.deps_skip_system = true;
635      /* Fall through.  */
636
637    case OPT_M:
638      d_option.deps = true;
639      break;
640
641    case OPT_MMD:
642      d_option.deps_skip_system = true;
643      /* Fall through.  */
644
645    case OPT_MD:
646      d_option.deps = true;
647      d_option.deps_filename = arg;
648      break;
649
650    case OPT_MF:
651      /* If specified multiple times, last one wins.  */
652      d_option.deps_filename_user = arg;
653      break;
654
655    case OPT_MP:
656      d_option.deps_phony = true;
657      break;
658
659    case OPT_MQ:
660      deps_add_target (arg, true);
661      break;
662
663    case OPT_MT:
664      deps_add_target (arg, false);
665      break;
666
667    case OPT_nostdinc:
668      d_option.stdinc = false;
669      break;
670
671    case OPT_v:
672      global.params.verbose = value;
673      break;
674
675    case OPT_Wall:
676      if (value)
677	global.params.warnings = DIAGNOSTICinform;
678      break;
679
680    case OPT_Wdeprecated:
681      global.params.useDeprecated = value ? DIAGNOSTICinform : DIAGNOSTICoff;
682      break;
683
684    case OPT_Werror:
685      if (value)
686	global.params.warnings = DIAGNOSTICerror;
687      break;
688
689    case OPT_Wspeculative:
690      if (value)
691	global.params.showGaggedErrors = 1;
692      break;
693
694    case OPT_Xf:
695      global.params.jsonfilename = arg;
696      /* Fall through.  */
697
698    case OPT_X:
699      global.params.doJsonGeneration = true;
700      break;
701
702    default:
703      break;
704    }
705
706  D_handle_option_auto (&global_options, &global_options_set,
707			scode, arg, value,
708			d_option_lang_mask (), kind,
709			loc, handlers, global_dc);
710
711  return result;
712}
713
714/* Implements the lang_hooks.post_options routine for language D.
715   Deal with any options that imply the turning on/off of features.
716   FN is the main input filename passed on the command line.  */
717
718static bool
719d_post_options (const char ** fn)
720{
721  /* Verify the input file name.  */
722  const char *filename = *fn;
723  if (!filename || strcmp (filename, "-") == 0)
724    filename = "";
725
726  /* The front end considers the first input file to be the main one.  */
727  *fn = filename;
728
729  /* Release mode doesn't turn off bounds checking for safe functions.  */
730  if (global.params.useArrayBounds == BOUNDSCHECKdefault)
731    {
732      global.params.useArrayBounds = global.params.release
733	? BOUNDSCHECKsafeonly : BOUNDSCHECKon;
734      flag_bounds_check = !global.params.release;
735    }
736
737  if (global.params.release)
738    {
739      if (!global_options_set.x_flag_invariants)
740	global.params.useInvariants = false;
741
742      if (!global_options_set.x_flag_preconditions)
743	global.params.useIn = false;
744
745      if (!global_options_set.x_flag_postconditions)
746	global.params.useOut = false;
747
748      if (!global_options_set.x_flag_assert)
749	global.params.useAssert = false;
750
751      if (!global_options_set.x_flag_switch_errors)
752	global.params.useSwitchError = false;
753    }
754
755  if (global.params.betterC)
756    {
757      if (!global_options_set.x_flag_moduleinfo)
758	global.params.useModuleInfo = false;
759
760      if (!global_options_set.x_flag_rtti)
761	global.params.useTypeInfo = false;
762
763      if (!global_options_set.x_flag_exceptions)
764	global.params.useExceptions = false;
765
766      global.params.checkAction = CHECKACTION_halt;
767    }
768
769  /* Turn off partitioning unless it was explicitly requested, as it doesn't
770     work with D exception chaining, where EH handler uses LSDA to determine
771     whether two thrown exception are in the same context.  */
772  if (!global_options_set.x_flag_reorder_blocks_and_partition)
773    global_options.x_flag_reorder_blocks_and_partition = 0;
774
775  /* Error about use of deprecated features.  */
776  if (global.params.useDeprecated == DIAGNOSTICinform
777      && global.params.warnings == DIAGNOSTICerror)
778    global.params.useDeprecated = DIAGNOSTICerror;
779
780  /* Make -fmax-errors visible to frontend's diagnostic machinery.  */
781  if (global_options_set.x_flag_max_errors)
782    global.errorLimit = flag_max_errors;
783
784  if (flag_excess_precision == EXCESS_PRECISION_DEFAULT)
785    flag_excess_precision = EXCESS_PRECISION_STANDARD;
786
787  if (global.params.useUnitTests)
788    global.params.useAssert = true;
789
790  global.params.symdebug = write_symbols != NO_DEBUG;
791  global.params.useInline = flag_inline_functions;
792  global.params.showColumns = flag_show_column;
793
794  if (global.params.useInline)
795    global.params.hdrStripPlainFunctions = false;
796
797  global.params.obj = !flag_syntax_only;
798
799  /* Has no effect yet.  */
800  global.params.pic = flag_pic != 0;
801
802  if (warn_return_type == -1)
803    warn_return_type = 0;
804
805  return false;
806}
807
808/* Return TRUE if an operand OP of a given TYPE being copied has no data.
809   The middle-end does a similar check with zero sized types.  */
810
811static bool
812empty_modify_p (tree type, tree op)
813{
814  tree_code code = TREE_CODE (op);
815  switch (code)
816    {
817    case COMPOUND_EXPR:
818      return empty_modify_p (type, TREE_OPERAND (op, 1));
819
820    case CONSTRUCTOR:
821      /* Non-empty construcors are valid.  */
822      if (CONSTRUCTOR_NELTS (op) != 0 || TREE_CLOBBER_P (op))
823	return false;
824      break;
825
826    case CALL_EXPR:
827      /* Leave nrvo alone because it isn't a copy.  */
828      if (CALL_EXPR_RETURN_SLOT_OPT (op))
829	return false;
830      break;
831
832    default:
833      /* If the operand doesn't have a simple form.  */
834      if (!is_gimple_lvalue (op) && !INDIRECT_REF_P (op))
835	return false;
836      break;
837    }
838
839  return empty_aggregate_p (type);
840}
841
842/* Implements the lang_hooks.gimplify_expr routine for language D.
843   Do gimplification of D specific expression trees in EXPR_P.  */
844
845int
846d_gimplify_expr (tree *expr_p, gimple_seq *pre_p,
847		 gimple_seq *post_p ATTRIBUTE_UNUSED)
848{
849  tree_code code = TREE_CODE (*expr_p);
850  enum gimplify_status ret = GS_UNHANDLED;
851  tree op0, op1;
852  tree type;
853
854  switch (code)
855    {
856    case INIT_EXPR:
857    case MODIFY_EXPR:
858      op0 = TREE_OPERAND (*expr_p, 0);
859      op1 = TREE_OPERAND (*expr_p, 1);
860
861      if (!error_operand_p (op0) && !error_operand_p (op1)
862	  && (AGGREGATE_TYPE_P (TREE_TYPE (op0))
863	      || AGGREGATE_TYPE_P (TREE_TYPE (op1)))
864	  && !useless_type_conversion_p (TREE_TYPE (op1), TREE_TYPE (op0)))
865	{
866	  /* If the back end isn't clever enough to know that the lhs and rhs
867	     types are the same, add an explicit conversion.  */
868	  TREE_OPERAND (*expr_p, 1) = build1 (VIEW_CONVERT_EXPR,
869					      TREE_TYPE (op0), op1);
870	  ret = GS_OK;
871	}
872      else if (empty_modify_p (TREE_TYPE (op0), op1))
873	{
874	  /* Remove any copies of empty aggregates.  */
875	  gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
876			 is_gimple_lvalue, fb_lvalue);
877
878	  if (TREE_SIDE_EFFECTS (op1))
879	    gimplify_and_add (op1, pre_p);
880
881	  *expr_p = TREE_OPERAND (*expr_p, 0);
882	  ret = GS_OK;
883	}
884      break;
885
886    case ADDR_EXPR:
887      op0 = TREE_OPERAND (*expr_p, 0);
888      /* Constructors are not lvalues, so make them one.  */
889      if (TREE_CODE (op0) == CONSTRUCTOR)
890	{
891	  TREE_OPERAND (*expr_p, 0) = force_target_expr (op0);
892	  ret = GS_OK;
893	}
894      break;
895
896    case CALL_EXPR:
897      if (CALL_EXPR_ARGS_ORDERED (*expr_p))
898	{
899	  /* Strictly evaluate all arguments from left to right.  */
900	  int nargs = call_expr_nargs (*expr_p);
901	  location_t loc = EXPR_LOC_OR_LOC (*expr_p, input_location);
902
903	  /* No need to enforce evaluation order if only one argument.  */
904	  if (nargs < 2)
905	    break;
906
907	  /* Or if all arguments are already free of side-effects.  */
908	  bool has_side_effects = false;
909	  for (int i = 0; i < nargs; i++)
910	    {
911	      if (TREE_SIDE_EFFECTS (CALL_EXPR_ARG (*expr_p, i)))
912		{
913		  has_side_effects = true;
914		  break;
915		}
916	    }
917
918	  if (!has_side_effects)
919	    break;
920
921	  /* Leave the last argument for gimplify_call_expr.  */
922	  for (int i = 0; i < nargs - 1; i++)
923	    {
924	      tree new_arg = CALL_EXPR_ARG (*expr_p, i);
925
926	      /* If argument has a side-effect, gimplify_arg will handle it.  */
927	      if (gimplify_arg (&new_arg, pre_p, loc) == GS_ERROR)
928		ret = GS_ERROR;
929
930	      /* Even if an argument itself doesn't have any side-effects, it
931		 might be altered by another argument in the list.  */
932	      if (new_arg == CALL_EXPR_ARG (*expr_p, i)
933		  && !really_constant_p (new_arg))
934		new_arg = get_formal_tmp_var (new_arg, pre_p);
935
936	      CALL_EXPR_ARG (*expr_p, i) = new_arg;
937	    }
938
939	  if (ret != GS_ERROR)
940	    ret = GS_OK;
941	}
942      break;
943
944    case UNSIGNED_RSHIFT_EXPR:
945      /* Convert op0 to an unsigned type.  */
946      op0 = TREE_OPERAND (*expr_p, 0);
947      op1 = TREE_OPERAND (*expr_p, 1);
948
949      type = d_unsigned_type (TREE_TYPE (op0));
950
951      *expr_p = convert (TREE_TYPE (*expr_p),
952			 build2 (RSHIFT_EXPR, type, convert (type, op0), op1));
953      ret = GS_OK;
954      break;
955
956    case FLOAT_MOD_EXPR:
957      gcc_unreachable ();
958
959    default:
960      break;
961    }
962
963  return ret;
964}
965
966/* Add the module M to the list of modules that may declare GCC builtins.
967   These are scanned after first semantic and before codegen passes.
968   See d_maybe_set_builtin() for the implementation.  */
969
970void
971d_add_builtin_module (Module *m)
972{
973  builtin_modules.push (m);
974}
975
976/* Record the entrypoint module ENTRY which will be compiled in the current
977   compilation.  ROOT is the module scope where this was requested from.  */
978
979void
980d_add_entrypoint_module (Module *entry, Module *root)
981{
982  /* We are emitting this straight to object file.  */
983  entrypoint_module = entry;
984  entrypoint_root_module = root;
985}
986
987/* Implements the lang_hooks.parse_file routine for language D.  */
988
989void
990d_parse_file (void)
991{
992  if (global.params.verbose)
993    {
994      message ("binary    %s", global.params.argv0);
995      message ("version   %s", global.version);
996
997      if (global.params.versionids)
998	{
999	  OutBuffer buf;
1000	  buf.writestring ("predefs  ");
1001	  for (size_t i = 0; i < global.params.versionids->dim; i++)
1002	    {
1003	      const char *s = (*global.params.versionids)[i];
1004	      buf.writestring (" ");
1005	      buf.writestring (s);
1006	    }
1007
1008	  message ("%.*s", (int) buf.offset, (char *) buf.data);
1009	}
1010    }
1011
1012  /* Start the main input file, if the debug writer wants it.  */
1013  if (debug_hooks->start_end_main_source_file)
1014    debug_hooks->start_source_file (0, main_input_filename);
1015
1016  /* Create Module's for all sources we will load.  */
1017  Modules modules;
1018  modules.reserve (num_in_fnames);
1019
1020  /* In this mode, the first file name is supposed to be a duplicate
1021     of one of the input files.  */
1022  if (d_option.fonly && strcmp (d_option.fonly, main_input_filename) != 0)
1023    error ("%<-fonly=%> argument is different from first input file name");
1024
1025  for (size_t i = 0; i < num_in_fnames; i++)
1026    {
1027      if (strcmp (in_fnames[i], "-") == 0)
1028	{
1029	  /* Load the entire contents of stdin into memory.  8 kilobytes should
1030	     be a good enough initial size, but double on each iteration.
1031	     16 bytes are added for the final '\n' and 15 bytes of padding.  */
1032	  ssize_t size = 8 * 1024;
1033	  uchar *buffer = XNEWVEC (uchar, size + 16);
1034	  ssize_t len = 0;
1035	  ssize_t count;
1036
1037	  while ((count = read (STDIN_FILENO, buffer + len, size - len)) > 0)
1038	    {
1039	      len += count;
1040	      if (len == size)
1041		{
1042		  size *= 2;
1043		  buffer = XRESIZEVEC (uchar, buffer, size + 16);
1044		}
1045	    }
1046
1047	  if (count < 0)
1048	    {
1049	      error (Loc ("stdin", 0, 0), "%s", xstrerror (errno));
1050	      free (buffer);
1051	      continue;
1052	    }
1053
1054	  /* Handling stdin, generate a unique name for the module.  */
1055	  Module *m = Module::create (in_fnames[i],
1056				      Identifier::generateId ("__stdin"),
1057				      global.params.doDocComments,
1058				      global.params.doHdrGeneration);
1059	  modules.push (m);
1060
1061	  /* Overwrite the source file for the module, the one created by
1062	     Module::create would have a forced a `.d' suffix.  */
1063	  m->srcfile = File::create ("<stdin>");
1064	  m->srcfile->len = len;
1065	  m->srcfile->buffer = buffer;
1066	}
1067      else
1068	{
1069	  /* Handling a D source file, strip off the path and extension.  */
1070	  const char *basename = FileName::name (in_fnames[i]);
1071	  const char *name = FileName::removeExt (basename);
1072
1073	  Module *m = Module::create (in_fnames[i], Identifier::idPool (name),
1074				      global.params.doDocComments,
1075				      global.params.doHdrGeneration);
1076	  modules.push (m);
1077	  FileName::free (name);
1078	}
1079    }
1080
1081  /* Read all D source files.  */
1082  for (size_t i = 0; i < modules.dim; i++)
1083    {
1084      Module *m = modules[i];
1085      m->read (Loc ());
1086    }
1087
1088  /* Parse all D source files.  */
1089  for (size_t i = 0; i < modules.dim; i++)
1090    {
1091      Module *m = modules[i];
1092
1093      if (global.params.verbose)
1094	message ("parse     %s", m->toChars ());
1095
1096      if (!Module::rootModule)
1097	Module::rootModule = m;
1098
1099      m->importedFrom = m;
1100      m->parse ();
1101      Compiler::loadModule (m);
1102
1103      if (m->isDocFile)
1104	{
1105	  gendocfile (m);
1106	  /* Remove M from list of modules.  */
1107	  modules.remove (i);
1108	  i--;
1109	}
1110    }
1111
1112  /* Load the module containing D main.  */
1113  if (global.params.addMain)
1114    {
1115      unsigned errors = global.startGagging ();
1116      Module *m = Module::load (Loc (), NULL, Identifier::idPool ("__main"));
1117
1118      if (! global.endGagging (errors))
1119	{
1120	  m->importedFrom = m;
1121	  modules.push (m);
1122	}
1123    }
1124
1125  if (global.errors)
1126    goto had_errors;
1127
1128  if (global.params.doHdrGeneration)
1129    {
1130      /* Generate 'header' import files.  Since 'header' import files must be
1131	 independent of command line switches and what else is imported, they
1132	 are generated before any semantic analysis.  */
1133      for (size_t i = 0; i < modules.dim; i++)
1134	{
1135	  Module *m = modules[i];
1136	  if (d_option.fonly && m != Module::rootModule)
1137	    continue;
1138
1139	  if (global.params.verbose)
1140	    message ("import    %s", m->toChars ());
1141
1142	  genhdrfile (m);
1143	}
1144    }
1145
1146  if (global.errors)
1147    goto had_errors;
1148
1149  /* Load all unconditional imports for better symbol resolving.  */
1150  for (size_t i = 0; i < modules.dim; i++)
1151    {
1152      Module *m = modules[i];
1153
1154      if (global.params.verbose)
1155	message ("importall %s", m->toChars ());
1156
1157      m->importAll (NULL);
1158    }
1159
1160  if (global.errors)
1161    goto had_errors;
1162
1163  /* Do semantic analysis.  */
1164  doing_semantic_analysis_p = true;
1165
1166  for (size_t i = 0; i < modules.dim; i++)
1167    {
1168      Module *m = modules[i];
1169
1170      if (global.params.verbose)
1171	message ("semantic  %s", m->toChars ());
1172
1173      m->semantic (NULL);
1174    }
1175
1176  /* Do deferred semantic analysis.  */
1177  Module::dprogress = 1;
1178  Module::runDeferredSemantic ();
1179
1180  if (Module::deferred.dim)
1181    {
1182      for (size_t i = 0; i < Module::deferred.dim; i++)
1183	{
1184	  Dsymbol *sd = Module::deferred[i];
1185	  error_at (make_location_t (sd->loc),
1186		    "unable to resolve forward reference in definition");
1187	}
1188    }
1189
1190  /* Process all built-in modules or functions now for CTFE.  */
1191  while (builtin_modules.dim != 0)
1192    {
1193      Module *m = builtin_modules.pop ();
1194      d_maybe_set_builtin (m);
1195    }
1196
1197  /* Do pass 2 semantic analysis.  */
1198  for (size_t i = 0; i < modules.dim; i++)
1199    {
1200      Module *m = modules[i];
1201
1202      if (global.params.verbose)
1203	message ("semantic2 %s", m->toChars ());
1204
1205      m->semantic2 (NULL);
1206    }
1207
1208  Module::runDeferredSemantic2 ();
1209
1210  if (global.errors)
1211    goto had_errors;
1212
1213  /* Do pass 3 semantic analysis.  */
1214  for (size_t i = 0; i < modules.dim; i++)
1215    {
1216      Module *m = modules[i];
1217
1218      if (global.params.verbose)
1219	message ("semantic3 %s", m->toChars ());
1220
1221      m->semantic3 (NULL);
1222    }
1223
1224  Module::runDeferredSemantic3 ();
1225
1226  /* Check again, incase semantic3 pass loaded any more modules.  */
1227  while (builtin_modules.dim != 0)
1228    {
1229      Module *m = builtin_modules.pop ();
1230      d_maybe_set_builtin (m);
1231    }
1232
1233  /* Do not attempt to generate output files if errors or warnings occurred.  */
1234  if (global.errors || global.warnings)
1235    goto had_errors;
1236
1237  /* Generate output files.  */
1238  doing_semantic_analysis_p = false;
1239
1240  if (Module::rootModule)
1241    {
1242      /* Declare the name of the root module as the first global name in order
1243	 to make the middle-end fully deterministic.  */
1244      OutBuffer buf;
1245      mangleToBuffer (Module::rootModule, &buf);
1246      first_global_object_name = buf.extractString ();
1247    }
1248
1249  /* Make dependencies.  */
1250  if (d_option.deps)
1251    {
1252      OutBuffer buf;
1253
1254      for (size_t i = 0; i < modules.dim; i++)
1255	deps_write (modules[i], &buf);
1256
1257      /* -MF <arg> overrides -M[M]D.  */
1258      if (d_option.deps_filename_user)
1259	d_option.deps_filename = d_option.deps_filename_user;
1260
1261      if (d_option.deps_filename)
1262	{
1263	  File *fdeps = File::create (d_option.deps_filename);
1264	  fdeps->setbuffer ((void *) buf.data, buf.offset);
1265	  fdeps->ref = 1;
1266	  writeFile (Loc (), fdeps);
1267	}
1268      else
1269	message ("%.*s", (int) buf.offset, (char *) buf.data);
1270    }
1271
1272  /* Generate JSON files.  */
1273  if (global.params.doJsonGeneration)
1274    {
1275      OutBuffer buf;
1276      json_generate (&buf, &modules);
1277
1278      const char *name = global.params.jsonfilename;
1279
1280      if (name && (name[0] != '-' || name[1] != '\0'))
1281	{
1282	  const char *nameext = FileName::defaultExt (name, global.json_ext);
1283	  File *fjson = File::create (nameext);
1284	  fjson->setbuffer ((void *) buf.data, buf.offset);
1285	  fjson->ref = 1;
1286	  writeFile (Loc (), fjson);
1287	}
1288      else
1289	message ("%.*s", (int) buf.offset, (char *) buf.data);
1290    }
1291
1292  /* Generate Ddoc files.  */
1293  if (global.params.doDocComments && !global.errors && !errorcount)
1294    {
1295      for (size_t i = 0; i < modules.dim; i++)
1296	{
1297	  Module *m = modules[i];
1298	  gendocfile (m);
1299	}
1300    }
1301
1302  /* Handle -fdump-d-original.  */
1303  if (global.params.vcg_ast)
1304    {
1305      for (size_t i = 0; i < modules.dim; i++)
1306	{
1307	  Module *m = modules[i];
1308	  OutBuffer buf;
1309	  buf.doindent = 1;
1310
1311	  moduleToBuffer (&buf, m);
1312	  message ("%.*s", (int) buf.offset, (char *) buf.data);
1313	}
1314    }
1315
1316  for (size_t i = 0; i < modules.dim; i++)
1317    {
1318      Module *m = modules[i];
1319      if (d_option.fonly && m != Module::rootModule)
1320	continue;
1321
1322      if (global.params.verbose)
1323	message ("code      %s", m->toChars ());
1324
1325      if (!flag_syntax_only)
1326	{
1327	  if ((entrypoint_module != NULL) && (m == entrypoint_root_module))
1328	    build_decl_tree (entrypoint_module);
1329
1330	  build_decl_tree (m);
1331	}
1332    }
1333
1334  /* And end the main input file, if the debug writer wants it.  */
1335  if (debug_hooks->start_end_main_source_file)
1336    debug_hooks->end_source_file (0);
1337
1338 had_errors:
1339  /* Add the D frontend error count to the GCC error count to correctly
1340     exit with an error status.  */
1341  errorcount += (global.errors + global.warnings);
1342
1343  /* Write out globals.  */
1344  d_finish_compilation (vec_safe_address (global_declarations),
1345			vec_safe_length (global_declarations));
1346}
1347
1348/* Implements the lang_hooks.types.type_for_mode routine for language D.  */
1349
1350static tree
1351d_type_for_mode (machine_mode mode, int unsignedp)
1352{
1353  if (mode == QImode)
1354    return unsignedp ? d_ubyte_type : d_byte_type;
1355
1356  if (mode == HImode)
1357    return unsignedp ? d_ushort_type : d_short_type;
1358
1359  if (mode == SImode)
1360    return unsignedp ? d_uint_type : d_int_type;
1361
1362  if (mode == DImode)
1363    return unsignedp ? d_ulong_type : d_long_type;
1364
1365  if (mode == TYPE_MODE (d_cent_type))
1366    return unsignedp ? d_ucent_type : d_cent_type;
1367
1368  if (mode == TYPE_MODE (float_type_node))
1369    return float_type_node;
1370
1371  if (mode == TYPE_MODE (double_type_node))
1372    return double_type_node;
1373
1374  if (mode == TYPE_MODE (long_double_type_node))
1375    return long_double_type_node;
1376
1377  if (mode == TYPE_MODE (build_pointer_type (char8_type_node)))
1378    return build_pointer_type (char8_type_node);
1379
1380  if (mode == TYPE_MODE (build_pointer_type (d_int_type)))
1381    return build_pointer_type (d_int_type);
1382
1383  for (int i = 0; i < NUM_INT_N_ENTS; i ++)
1384    {
1385      if (int_n_enabled_p[i] && mode == int_n_data[i].m)
1386	{
1387	  if (unsignedp)
1388	    return int_n_trees[i].unsigned_type;
1389	  else
1390	    return int_n_trees[i].signed_type;
1391	}
1392    }
1393
1394  if (COMPLEX_MODE_P (mode))
1395    {
1396      machine_mode inner_mode;
1397      tree inner_type;
1398
1399      if (mode == TYPE_MODE (complex_float_type_node))
1400	return complex_float_type_node;
1401      if (mode == TYPE_MODE (complex_double_type_node))
1402	return complex_double_type_node;
1403      if (mode == TYPE_MODE (complex_long_double_type_node))
1404	return complex_long_double_type_node;
1405
1406      inner_mode = (machine_mode) GET_MODE_INNER (mode);
1407      inner_type = d_type_for_mode (inner_mode, unsignedp);
1408      if (inner_type != NULL_TREE)
1409	return build_complex_type (inner_type);
1410    }
1411  else if (VECTOR_MODE_P (mode))
1412    {
1413      machine_mode inner_mode = (machine_mode) GET_MODE_INNER (mode);
1414      tree inner_type = d_type_for_mode (inner_mode, unsignedp);
1415      if (inner_type != NULL_TREE)
1416	return build_vector_type_for_mode (inner_type, mode);
1417    }
1418
1419  return 0;
1420}
1421
1422/* Implements the lang_hooks.types.type_for_size routine for language D.  */
1423
1424static tree
1425d_type_for_size (unsigned bits, int unsignedp)
1426{
1427  if (bits <= TYPE_PRECISION (d_byte_type))
1428    return unsignedp ? d_ubyte_type : d_byte_type;
1429
1430  if (bits <= TYPE_PRECISION (d_short_type))
1431    return unsignedp ? d_ushort_type : d_short_type;
1432
1433  if (bits <= TYPE_PRECISION (d_int_type))
1434    return unsignedp ? d_uint_type : d_int_type;
1435
1436  if (bits <= TYPE_PRECISION (d_long_type))
1437    return unsignedp ? d_ulong_type : d_long_type;
1438
1439  if (bits <= TYPE_PRECISION (d_cent_type))
1440    return unsignedp ? d_ucent_type : d_cent_type;
1441
1442  for (int i = 0; i < NUM_INT_N_ENTS; i ++)
1443    {
1444      if (int_n_enabled_p[i] && bits == int_n_data[i].bitsize)
1445	{
1446	  if (unsignedp)
1447	    return int_n_trees[i].unsigned_type;
1448	  else
1449	    return int_n_trees[i].signed_type;
1450	}
1451    }
1452
1453  return 0;
1454}
1455
1456/* Return the signed or unsigned version of TYPE, an integral type, the
1457   signedness being specified by UNSIGNEDP.  */
1458
1459static tree
1460d_signed_or_unsigned_type (int unsignedp, tree type)
1461{
1462  if (TYPE_UNSIGNED (type) == (unsigned) unsignedp)
1463    return type;
1464
1465  if (TYPE_PRECISION (type) == TYPE_PRECISION (d_cent_type))
1466    return unsignedp ? d_ucent_type : d_cent_type;
1467
1468  if (TYPE_PRECISION (type) == TYPE_PRECISION (d_long_type))
1469    return unsignedp ? d_ulong_type : d_long_type;
1470
1471  if (TYPE_PRECISION (type) == TYPE_PRECISION (d_int_type))
1472    return unsignedp ? d_uint_type : d_int_type;
1473
1474  if (TYPE_PRECISION (type) == TYPE_PRECISION (d_short_type))
1475    return unsignedp ? d_ushort_type : d_short_type;
1476
1477  if (TYPE_PRECISION (type) == TYPE_PRECISION (d_byte_type))
1478    return unsignedp ? d_ubyte_type : d_byte_type;
1479
1480  return signed_or_unsigned_type_for (unsignedp, type);
1481}
1482
1483/* Return the unsigned version of TYPE, an integral type.  */
1484
1485tree
1486d_unsigned_type (tree type)
1487{
1488  return d_signed_or_unsigned_type (1, type);
1489}
1490
1491/* Return the signed version of TYPE, an integral type.  */
1492
1493tree
1494d_signed_type (tree type)
1495{
1496  return d_signed_or_unsigned_type (0, type);
1497}
1498
1499/* Implements the lang_hooks.types.type_promotes_to routine for language D.
1500   All promotions for variable arguments are handled by the D frontend.  */
1501
1502static tree
1503d_type_promotes_to (tree type)
1504{
1505  return type;
1506}
1507
1508/* Implements the lang_hooks.decls.global_bindings_p routine for language D.
1509   Return true if we are in the global binding level.  */
1510
1511static bool
1512d_global_bindings_p (void)
1513{
1514  return (current_binding_level == global_binding_level);
1515}
1516
1517/* Return global_context, but create it first if need be.  */
1518
1519static tree
1520get_global_context (void)
1521{
1522  if (!global_context)
1523    {
1524      global_context = build_translation_unit_decl (NULL_TREE);
1525      debug_hooks->register_main_translation_unit (global_context);
1526    }
1527
1528  return global_context;
1529}
1530
1531/* Implements the lang_hooks.decls.pushdecl routine for language D.
1532   Record DECL as belonging to the current lexical scope.  */
1533
1534tree
1535d_pushdecl (tree decl)
1536{
1537  /* Set the context of the decl.  If current_function_decl did not help in
1538     determining the context, use global scope.  */
1539  if (!DECL_CONTEXT (decl))
1540    {
1541      if (current_function_decl)
1542	DECL_CONTEXT (decl) = current_function_decl;
1543      else
1544	DECL_CONTEXT (decl) = get_global_context ();
1545    }
1546
1547  /* Put decls on list in reverse order.  */
1548  if (TREE_STATIC (decl) || d_global_bindings_p ())
1549    vec_safe_push (global_declarations, decl);
1550  else
1551    {
1552      TREE_CHAIN (decl) = current_binding_level->names;
1553      current_binding_level->names = decl;
1554    }
1555
1556  return decl;
1557}
1558
1559/* Implements the lang_hooks.decls.getdecls routine for language D.
1560   Return the list of declarations of the current level.  */
1561
1562static tree
1563d_getdecls (void)
1564{
1565  if (current_binding_level)
1566    return current_binding_level->names;
1567
1568  return NULL_TREE;
1569}
1570
1571
1572/* Implements the lang_hooks.get_alias_set routine for language D.
1573   Get the alias set corresponding to type or expression T.
1574   Return -1 if we don't do anything special.  */
1575
1576static alias_set_type
1577d_get_alias_set (tree)
1578{
1579  /* For now in D, assume everything aliases everything else, until we define
1580     some solid rules backed by a specification.  There are also some parts
1581     of code generation routines that don't adhere to C alias rules, such as
1582     build_vconvert.  In any case, a lot of user code already assumes there
1583     is no strict aliasing and will break if we were to change that.  */
1584  return 0;
1585}
1586
1587/* Implements the lang_hooks.types_compatible_p routine for language D.
1588   Compares two types for equivalence in the D programming language.
1589   This routine should only return 1 if it is sure, even though the frontend
1590   should have already ensured that all types are compatible before handing
1591   over the parsed ASTs to the code generator.  */
1592
1593static int
1594d_types_compatible_p (tree x, tree y)
1595{
1596  Type *tx = TYPE_LANG_FRONTEND (x);
1597  Type *ty = TYPE_LANG_FRONTEND (y);
1598
1599  /* Try validating the types in the frontend.  */
1600  if (tx != NULL && ty != NULL)
1601    {
1602      /* Types are equivalent.  */
1603      if (same_type_p (tx, ty))
1604	return true;
1605
1606      /* Type system allows implicit conversion between.  */
1607      if (tx->implicitConvTo (ty) || ty->implicitConvTo (tx))
1608	return true;
1609    }
1610
1611  /* Fallback on using type flags for comparison.  E.g: all dynamic arrays
1612     are distinct types in D, but are VIEW_CONVERT compatible.  */
1613  if (TREE_CODE (x) == RECORD_TYPE && TREE_CODE (y) == RECORD_TYPE)
1614    {
1615      if (TYPE_DYNAMIC_ARRAY (x) && TYPE_DYNAMIC_ARRAY (y))
1616	return true;
1617
1618      if (TYPE_DELEGATE (x) && TYPE_DELEGATE (y))
1619	return true;
1620
1621      if (TYPE_ASSOCIATIVE_ARRAY (x) && TYPE_ASSOCIATIVE_ARRAY (y))
1622	return true;
1623    }
1624
1625  return false;
1626}
1627
1628/* Implements the lang_hooks.finish_incomplete_decl routine for language D.  */
1629
1630static void
1631d_finish_incomplete_decl (tree decl)
1632{
1633  if (VAR_P (decl))
1634    {
1635      /* D allows zero-length declarations.  Such a declaration ends up with
1636	 DECL_SIZE (t) == NULL_TREE which is what the back-end function
1637	 assembler_variable checks.  This could change in later versions, or
1638	 maybe all of these variables should be aliased to one symbol.  */
1639      if (DECL_SIZE (decl) == 0)
1640	{
1641	  DECL_SIZE (decl) = bitsize_zero_node;
1642	  DECL_SIZE_UNIT (decl) = size_zero_node;
1643	}
1644    }
1645}
1646
1647/* Implements the lang_hooks.types.classify_record routine for language D.
1648   Return the true debug type for TYPE.  */
1649
1650static classify_record
1651d_classify_record (tree type)
1652{
1653  Type *t = TYPE_LANG_FRONTEND (type);
1654
1655  if (t && t->ty == Tclass)
1656    {
1657      TypeClass *tc = (TypeClass *) t;
1658
1659      /* extern(C++) interfaces get emitted as classes.  */
1660      if (tc->sym->isInterfaceDeclaration ()
1661	  && !tc->sym->isCPPinterface ())
1662	return RECORD_IS_INTERFACE;
1663
1664      return RECORD_IS_CLASS;
1665    }
1666
1667  return RECORD_IS_STRUCT;
1668}
1669
1670/* Implements the lang_hooks.tree_size routine for language D.
1671   Determine the size of our tcc_constant or tcc_exceptional nodes.  */
1672
1673static size_t
1674d_tree_size (tree_code code)
1675{
1676  switch (code)
1677    {
1678    case FUNCFRAME_INFO:
1679      return sizeof (tree_frame_info);
1680
1681    default:
1682      gcc_unreachable ();
1683    }
1684}
1685
1686/* Implements the lang_hooks.print_xnode routine for language D.  */
1687
1688static void
1689d_print_xnode (FILE *file, tree node, int indent)
1690{
1691  switch (TREE_CODE (node))
1692    {
1693    case FUNCFRAME_INFO:
1694      print_node (file, "frame_type", FRAMEINFO_TYPE (node), indent + 4);
1695      break;
1696
1697    default:
1698      break;
1699    }
1700}
1701
1702/* Return which tree structure is used by NODE, or TS_D_GENERIC if NODE
1703   is one of the language-independent trees.  */
1704
1705d_tree_node_structure_enum
1706d_tree_node_structure (lang_tree_node *t)
1707{
1708  switch (TREE_CODE (&t->generic))
1709    {
1710    case IDENTIFIER_NODE:
1711      return TS_D_IDENTIFIER;
1712
1713    case FUNCFRAME_INFO:
1714      return TS_D_FRAMEINFO;
1715
1716    default:
1717      return TS_D_GENERIC;
1718    }
1719}
1720
1721/* Allocate and return a lang specific structure for the frontend type.  */
1722
1723struct lang_type *
1724build_lang_type (Type *t)
1725{
1726  struct lang_type *lt = ggc_cleared_alloc<struct lang_type> ();
1727  lt->type = t;
1728  return lt;
1729}
1730
1731/* Allocate and return a lang specific structure for the frontend decl.  */
1732
1733struct lang_decl *
1734build_lang_decl (Declaration *d)
1735{
1736  /* For compiler generated run-time typeinfo, a lang_decl is allocated even if
1737     there's no associated frontend symbol to refer to (yet).  If the symbol
1738     appears later in the compilation, then the slot will be re-used.  */
1739  if (d == NULL)
1740    return ggc_cleared_alloc<struct lang_decl> ();
1741
1742  struct lang_decl *ld = (d->csym) ? DECL_LANG_SPECIFIC (d->csym) : NULL;
1743  if (ld == NULL)
1744    ld = ggc_cleared_alloc<struct lang_decl> ();
1745
1746  if (ld->decl == NULL)
1747    ld->decl = d;
1748
1749  return ld;
1750}
1751
1752/* Implements the lang_hooks.dup_lang_specific_decl routine for language D.
1753   Replace the DECL_LANG_SPECIFIC field of NODE with a copy.  */
1754
1755static void
1756d_dup_lang_specific_decl (tree node)
1757{
1758  if (! DECL_LANG_SPECIFIC (node))
1759    return;
1760
1761  struct lang_decl *ld = ggc_alloc<struct lang_decl> ();
1762  memcpy (ld, DECL_LANG_SPECIFIC (node), sizeof (struct lang_decl));
1763  DECL_LANG_SPECIFIC (node) = ld;
1764}
1765
1766/* This preserves trees we create from the garbage collector.  */
1767
1768static GTY(()) tree d_keep_list = NULL_TREE;
1769
1770void
1771d_keep (tree t)
1772{
1773  d_keep_list = tree_cons (NULL_TREE, t, d_keep_list);
1774}
1775
1776/* Implements the lang_hooks.eh_personality routine for language D.
1777   Return the GDC personality function decl.  */
1778
1779static GTY(()) tree d_eh_personality_decl;
1780
1781static tree
1782d_eh_personality (void)
1783{
1784  if (!d_eh_personality_decl)
1785    d_eh_personality_decl = build_personality_function ("gdc");
1786
1787  return d_eh_personality_decl;
1788}
1789
1790/* Implements the lang_hooks.eh_runtime_type routine for language D.  */
1791
1792static tree
1793d_build_eh_runtime_type (tree type)
1794{
1795  Type *t = TYPE_LANG_FRONTEND (type);
1796
1797  if (t != NULL)
1798    t = t->toBasetype ();
1799
1800  gcc_assert (t != NULL && t->ty == Tclass);
1801  ClassDeclaration *cd = ((TypeClass *) t)->sym;
1802  tree decl;
1803
1804  if (cd->isCPPclass ())
1805    decl = get_cpp_typeinfo_decl (cd);
1806  else
1807    decl = get_classinfo_decl (cd);
1808
1809  return convert (ptr_type_node, build_address (decl));
1810}
1811
1812/* Definitions for our language-specific hooks.  */
1813
1814#undef LANG_HOOKS_NAME
1815#undef LANG_HOOKS_INIT
1816#undef LANG_HOOKS_INIT_TS
1817#undef LANG_HOOKS_INIT_OPTIONS
1818#undef LANG_HOOKS_INIT_OPTIONS_STRUCT
1819#undef LANG_HOOKS_OPTION_LANG_MASK
1820#undef LANG_HOOKS_HANDLE_OPTION
1821#undef LANG_HOOKS_POST_OPTIONS
1822#undef LANG_HOOKS_PARSE_FILE
1823#undef LANG_HOOKS_COMMON_ATTRIBUTE_TABLE
1824#undef LANG_HOOKS_ATTRIBUTE_TABLE
1825#undef LANG_HOOKS_GET_ALIAS_SET
1826#undef LANG_HOOKS_TYPES_COMPATIBLE_P
1827#undef LANG_HOOKS_BUILTIN_FUNCTION
1828#undef LANG_HOOKS_BUILTIN_FUNCTION_EXT_SCOPE
1829#undef LANG_HOOKS_REGISTER_BUILTIN_TYPE
1830#undef LANG_HOOKS_FINISH_INCOMPLETE_DECL
1831#undef LANG_HOOKS_GIMPLIFY_EXPR
1832#undef LANG_HOOKS_CLASSIFY_RECORD
1833#undef LANG_HOOKS_TREE_SIZE
1834#undef LANG_HOOKS_PRINT_XNODE
1835#undef LANG_HOOKS_DUP_LANG_SPECIFIC_DECL
1836#undef LANG_HOOKS_EH_PERSONALITY
1837#undef LANG_HOOKS_EH_RUNTIME_TYPE
1838#undef LANG_HOOKS_PUSHDECL
1839#undef LANG_HOOKS_GETDECLS
1840#undef LANG_HOOKS_GLOBAL_BINDINGS_P
1841#undef LANG_HOOKS_TYPE_FOR_MODE
1842#undef LANG_HOOKS_TYPE_FOR_SIZE
1843#undef LANG_HOOKS_TYPE_PROMOTES_TO
1844
1845#define LANG_HOOKS_NAME			    "GNU D"
1846#define LANG_HOOKS_INIT			    d_init
1847#define LANG_HOOKS_INIT_TS		    d_init_ts
1848#define LANG_HOOKS_INIT_OPTIONS		    d_init_options
1849#define LANG_HOOKS_INIT_OPTIONS_STRUCT	    d_init_options_struct
1850#define LANG_HOOKS_OPTION_LANG_MASK	    d_option_lang_mask
1851#define LANG_HOOKS_HANDLE_OPTION	    d_handle_option
1852#define LANG_HOOKS_POST_OPTIONS		    d_post_options
1853#define LANG_HOOKS_PARSE_FILE		    d_parse_file
1854#define LANG_HOOKS_COMMON_ATTRIBUTE_TABLE   d_langhook_common_attribute_table
1855#define LANG_HOOKS_ATTRIBUTE_TABLE	    d_langhook_attribute_table
1856#define LANG_HOOKS_GET_ALIAS_SET	    d_get_alias_set
1857#define LANG_HOOKS_TYPES_COMPATIBLE_P	    d_types_compatible_p
1858#define LANG_HOOKS_BUILTIN_FUNCTION	    d_builtin_function
1859#define LANG_HOOKS_BUILTIN_FUNCTION_EXT_SCOPE d_builtin_function_ext_scope
1860#define LANG_HOOKS_REGISTER_BUILTIN_TYPE    d_register_builtin_type
1861#define LANG_HOOKS_FINISH_INCOMPLETE_DECL   d_finish_incomplete_decl
1862#define LANG_HOOKS_GIMPLIFY_EXPR	    d_gimplify_expr
1863#define LANG_HOOKS_CLASSIFY_RECORD	    d_classify_record
1864#define LANG_HOOKS_TREE_SIZE		    d_tree_size
1865#define LANG_HOOKS_PRINT_XNODE		    d_print_xnode
1866#define LANG_HOOKS_DUP_LANG_SPECIFIC_DECL   d_dup_lang_specific_decl
1867#define LANG_HOOKS_EH_PERSONALITY	    d_eh_personality
1868#define LANG_HOOKS_EH_RUNTIME_TYPE	    d_build_eh_runtime_type
1869#define LANG_HOOKS_PUSHDECL		    d_pushdecl
1870#define LANG_HOOKS_GETDECLS		    d_getdecls
1871#define LANG_HOOKS_GLOBAL_BINDINGS_P	    d_global_bindings_p
1872#define LANG_HOOKS_TYPE_FOR_MODE	    d_type_for_mode
1873#define LANG_HOOKS_TYPE_FOR_SIZE	    d_type_for_size
1874#define LANG_HOOKS_TYPE_PROMOTES_TO	    d_type_promotes_to
1875
1876struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
1877
1878#include "gt-d-d-lang.h"
1879#include "gtype-d.h"
1880