xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/d/d-lang.cc (revision 4c3eb207d36f67d31994830c0a694161fc1ca39b)
1 /* d-lang.cc -- Language-dependent hooks for D.
2    Copyright (C) 2006-2020 Free Software Foundation, Inc.
3 
4 GCC 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 3, or (at your option)
7 any later version.
8 
9 GCC 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.
13 
14 You should have received a copy of the GNU General Public License
15 along 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.  */
60 tree d_global_trees[DTI_MAX];
61 
62 /* True if compilation is currently inside the D frontend semantic passes.  */
63 bool doing_semantic_analysis_p = false;
64 
65 /* Options handled by the compiler that are separate from the frontend.  */
66 struct 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 }
81 d_option;
82 
83 /* List of modules being compiled.  */
84 static Modules builtin_modules;
85 
86 /* Module where `C main' is defined, compiled in if needed.  */
87 static Module *entrypoint_module = NULL;
88 static Module *entrypoint_root_module = NULL;
89 
90 /* The current and global binding level in effect.  */
91 struct binding_level *current_binding_level;
92 struct binding_level *global_binding_level;
93 
94 /* The context to be used for global declarations.  */
95 static GTY(()) tree global_context;
96 
97 /* Array of all global declarations to pass back to the middle-end.  */
98 static 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 
104 static void
deps_add_target(const char * target,bool quoted)105 deps_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 
151 static void
deps_write(Module * module,OutBuffer * buffer,unsigned colmax=72)152 deps_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 
273 static void
d_init_options(unsigned int,cl_decoded_option * decoded_options)274 d_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 
329 static void
d_init_options_struct(gcc_options * opts)330 d_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 
352 static unsigned int
d_option_lang_mask(void)353 d_option_lang_mask (void)
354 {
355   return CL_D;
356 }
357 
358 /* Implements the lang_hooks.init routine for language D.  */
359 
360 static bool
d_init(void)361 d_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 
401 static void
d_init_ts(void)402 d_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 
411 static bool
d_handle_option(size_t scode,const char * arg,HOST_WIDE_INT value,int kind ATTRIBUTE_UNUSED,location_t loc ATTRIBUTE_UNUSED,const cl_option_handlers * handlers ATTRIBUTE_UNUSED)412 d_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 
718 static bool
d_post_options(const char ** fn)719 d_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 
811 static bool
empty_modify_p(tree type,tree op)812 empty_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 
845 int
d_gimplify_expr(tree * expr_p,gimple_seq * pre_p,gimple_seq * post_p ATTRIBUTE_UNUSED)846 d_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 
970 void
d_add_builtin_module(Module * m)971 d_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 
979 void
d_add_entrypoint_module(Module * entry,Module * root)980 d_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 
989 void
d_parse_file(void)990 d_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 
1350 static tree
d_type_for_mode(machine_mode mode,int unsignedp)1351 d_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 
1424 static tree
d_type_for_size(unsigned bits,int unsignedp)1425 d_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 
1459 static tree
d_signed_or_unsigned_type(int unsignedp,tree type)1460 d_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 
1485 tree
d_unsigned_type(tree type)1486 d_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 
1493 tree
d_signed_type(tree type)1494 d_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 
1502 static tree
d_type_promotes_to(tree type)1503 d_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 
1511 static bool
d_global_bindings_p(void)1512 d_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 
1519 static tree
get_global_context(void)1520 get_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 
1534 tree
d_pushdecl(tree decl)1535 d_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 
1562 static tree
d_getdecls(void)1563 d_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 
1576 static alias_set_type
d_get_alias_set(tree)1577 d_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 
1593 static int
d_types_compatible_p(tree x,tree y)1594 d_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 
1630 static void
d_finish_incomplete_decl(tree decl)1631 d_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 
1650 static classify_record
d_classify_record(tree type)1651 d_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 
1673 static size_t
d_tree_size(tree_code code)1674 d_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 
1688 static void
d_print_xnode(FILE * file,tree node,int indent)1689 d_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 
1705 d_tree_node_structure_enum
d_tree_node_structure(lang_tree_node * t)1706 d_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 
1723 struct lang_type *
build_lang_type(Type * t)1724 build_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 
1733 struct lang_decl *
build_lang_decl(Declaration * d)1734 build_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 
1755 static void
d_dup_lang_specific_decl(tree node)1756 d_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 
1768 static GTY(()) tree d_keep_list = NULL_TREE;
1769 
1770 void
d_keep(tree t)1771 d_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 
1779 static GTY(()) tree d_eh_personality_decl;
1780 
1781 static tree
d_eh_personality(void)1782 d_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 
1792 static tree
d_build_eh_runtime_type(tree type)1793 d_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 
1876 struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
1877 
1878 #include "gt-d-d-lang.h"
1879 #include "gtype-d.h"
1880