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