Home | History | Annotate | Line # | Download | only in d
imports.cc revision 1.1.1.3
      1 /* imports.cc -- Build imported modules/declarations.
      2    Copyright (C) 2014-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/declaration.h"
     24 #include "dmd/enum.h"
     25 #include "dmd/identifier.h"
     26 #include "dmd/import.h"
     27 #include "dmd/module.h"
     28 
     29 #include "tree.h"
     30 #include "stringpool.h"
     31 
     32 #include "d-tree.h"
     33 
     34 
     35 /* Implements the visitor interface to build debug trees for all
     36    module and import declarations, where ISYM holds the cached
     37    back-end representation to be returned.  */
     38 class ImportVisitor : public Visitor
     39 {
     40   using Visitor::visit;
     41 
     42   /* Build the declaration DECL as an imported symbol.  */
     43   tree make_import (tree decl)
     44   {
     45     gcc_assert (decl != NULL_TREE);
     46 
     47     tree import = build_decl (input_location, IMPORTED_DECL,
     48 			      DECL_NAME (decl), void_type_node);
     49     IMPORTED_DECL_ASSOCIATED_DECL (import) = decl;
     50     d_keep (import);
     51 
     52     return import;
     53   }
     54 
     55 public:
     56   ImportVisitor (void)
     57   {
     58   }
     59 
     60   /* This should be overridden by each symbol class.  */
     61   void visit (Dsymbol *)
     62   {
     63     gcc_unreachable ();
     64   }
     65 
     66   /* Build the module decl for M, this is considered toplevel, regardless
     67      of whether there are any parent packages in the module system.  */
     68   void visit (Module *m)
     69   {
     70     Loc loc = (m->md != NULL) ? m->md->loc
     71       : Loc (m->srcfile->toChars (), 1, 0);
     72 
     73     m->isym = build_decl (make_location_t (loc), NAMESPACE_DECL,
     74 			  get_identifier (m->toPrettyChars ()),
     75 			  void_type_node);
     76     d_keep (m->isym);
     77 
     78     if (!m->isRoot ())
     79       DECL_EXTERNAL (m->isym) = 1;
     80 
     81     TREE_PUBLIC (m->isym) = 1;
     82     DECL_CONTEXT (m->isym) = NULL_TREE;
     83   }
     84 
     85   /* Build an import of another module symbol.  */
     86 
     87   void visit (Import *m)
     88   {
     89     tree module = build_import_decl (m->mod);
     90     m->isym = this->make_import (module);
     91   }
     92 
     93   /* Build an import for any kind of user defined type.
     94      Use the TYPE_DECL associated with the type symbol.  */
     95   void visit (EnumDeclaration *d)
     96   {
     97     tree type = build_ctype (d->type);
     98     /* Not all kinds of D enums create a TYPE_DECL.  */
     99     if (TREE_CODE (type) == ENUMERAL_TYPE)
    100       {
    101 	type = TYPE_MAIN_VARIANT (type);
    102 	d->isym = this->make_import (TYPE_STUB_DECL (type));
    103       }
    104 
    105   }
    106 
    107   void visit (AggregateDeclaration *d)
    108   {
    109     tree type = build_ctype (d->type);
    110     type = TYPE_MAIN_VARIANT (type);
    111     d->isym = this->make_import (TYPE_STUB_DECL (type));
    112   }
    113 
    114   void visit (ClassDeclaration *d)
    115   {
    116     /* Want the RECORD_TYPE, not POINTER_TYPE.  */
    117     tree type = TREE_TYPE (build_ctype (d->type));
    118     type = TYPE_MAIN_VARIANT (type);
    119     d->isym = this->make_import (TYPE_STUB_DECL (type));
    120   }
    121 
    122   /* For now, ignore importing other kinds of dsymbols.  */
    123   void visit (ScopeDsymbol *)
    124   {
    125   }
    126 
    127   /* Alias symbols aren't imported, but their targets are.  */
    128   void visit (AliasDeclaration *d)
    129   {
    130     Dsymbol *dsym = d->toAlias ();
    131 
    132     if (dsym == d)
    133       {
    134 	Type *type = d->getType ();
    135 
    136 	/* Type imports should really be part of their own visit method.  */
    137 	if (type != NULL)
    138 	  {
    139 	    if (type->ty == Tenum)
    140 	      dsym = ((TypeEnum *) type)->sym;
    141 	    else if (type->ty == Tstruct)
    142 	      dsym = ((TypeStruct *) type)->sym;
    143 	    else if (type->ty == Tclass)
    144 	      dsym = ((TypeClass *) type)->sym;
    145 	  }
    146       }
    147 
    148     /* This symbol is really an alias for another, visit the other.  */
    149     if (dsym != d)
    150       {
    151 	dsym->accept (this);
    152 	d->isym = dsym->isym;
    153       }
    154   }
    155 
    156   /* Visit the underlying alias symbol of overloadable aliases.  */
    157   void visit (OverDeclaration *d)
    158   {
    159     if (d->aliassym != NULL)
    160       {
    161 	d->aliassym->accept (this);
    162 	d->isym = d->aliassym->isym;
    163       }
    164   }
    165 
    166   /* Build IMPORTED_DECLs for all overloads in a set.  */
    167   void visit (OverloadSet *d)
    168   {
    169     vec<tree, va_gc> *tset = NULL;
    170 
    171     vec_alloc (tset, d->a.dim);
    172 
    173     for (size_t i = 0; i < d->a.dim; i++)
    174       vec_safe_push (tset, build_import_decl (d->a[i]));
    175 
    176     d->isym = build_tree_list_vec (tset);
    177     tset->truncate (0);
    178   }
    179 
    180   /* Function aliases are the same as alias symbols.  */
    181   void visit (FuncAliasDeclaration *d)
    182   {
    183     FuncDeclaration *fd = d->toAliasFunc ();
    184 
    185     if (fd != NULL)
    186       {
    187 	fd->accept (this);
    188 	d->isym = fd->isym;
    189       }
    190   }
    191 
    192   /* Skip over importing templates and tuples.  */
    193   void visit (TemplateDeclaration *)
    194   {
    195   }
    196 
    197   void visit (TupleDeclaration *)
    198   {
    199   }
    200 
    201   /* Import any other kind of declaration.  If the class does not implement
    202      symbol generation routines, the compiler will throw an error.  */
    203   void visit (Declaration *d)
    204   {
    205     d->isym = this->make_import (get_symbol_decl (d));
    206   }
    207 };
    208 
    209 
    210 /* Build a declaration for the symbol D that can be used for the
    211    debug_hook imported_module_or_decl.  */
    212 tree
    213 build_import_decl (Dsymbol *d)
    214 {
    215   if (!d->isym)
    216     {
    217       location_t saved_location = input_location;
    218       ImportVisitor v;
    219 
    220       input_location = make_location_t (d->loc);
    221       d->accept (&v);
    222       input_location = saved_location;
    223     }
    224 
    225   /* Not all visitors set 'isym'.  */
    226   return d->isym ? d->isym : NULL_TREE;
    227 }
    228 
    229