xref: /netbsd/external/gpl3/gcc/dist/gcc/d/imports.cc (revision f0fbc68b)
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.  */
make_import(tree decl)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:
ImportVisitor(void)59   ImportVisitor (void)
60   {
61     this->result_ = NULL_TREE;
62   }
63 
result(void)64   tree result (void)
65   {
66     return this->result_;
67   }
68 
69   /* This should be overridden by each symbol class.  */
visit(Dsymbol *)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.  */
visit(Module * m)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 
visit(Import * m)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.  */
visit(EnumDeclaration * d)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 
visit(AggregateDeclaration * d)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 
visit(ClassDeclaration * d)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   /* For now, ignore importing other kinds of dsymbols.  */
visit(ScopeDsymbol *)131   void visit (ScopeDsymbol *)
132   {
133   }
134 
135   /* Alias symbols aren't imported, but their targets are.  */
visit(AliasDeclaration * d)136   void visit (AliasDeclaration *d)
137   {
138     Dsymbol *dsym = d->toAlias ();
139 
140     if (dsym == d)
141       {
142 	Type *type = d->getType ();
143 
144 	/* Type imports should really be part of their own visit method.  */
145 	if (type != NULL)
146 	  {
147 	    if (type->ty == TY::Tenum)
148 	      dsym = type->isTypeEnum ()->sym;
149 	    else if (type->ty == TY::Tstruct)
150 	      dsym = type->isTypeStruct ()->sym;
151 	    else if (type->ty == TY::Tclass)
152 	      dsym = type->isTypeClass ()->sym;
153 	  }
154       }
155 
156     /* This symbol is really an alias for another, visit the other.  */
157     if (dsym != d)
158       dsym->accept (this);
159   }
160 
161   /* Visit the underlying alias symbol of overloadable aliases.  */
visit(OverDeclaration * d)162   void visit (OverDeclaration *d)
163   {
164     if (d->aliassym != NULL)
165       d->aliassym->accept (this);
166   }
167 
168   /* Build IMPORTED_DECLs for all overloads in a set.  */
visit(OverloadSet * d)169   void visit (OverloadSet *d)
170   {
171     vec<tree, va_gc> *tset = NULL;
172 
173     vec_alloc (tset, d->a.length);
174 
175     for (size_t i = 0; i < d->a.length; i++)
176       vec_safe_push (tset, build_import_decl (d->a[i]));
177 
178     this->result_ = build_tree_list_vec (tset);
179     tset->truncate (0);
180   }
181 
182   /* Function aliases are the same as alias symbols.  */
visit(FuncAliasDeclaration * d)183   void visit (FuncAliasDeclaration *d)
184   {
185     FuncDeclaration *fd = d->toAliasFunc ();
186 
187     if (fd != NULL)
188       fd->accept (this);
189   }
190 
191   /* Skip over importing templates and tuples.  */
visit(TemplateDeclaration *)192   void visit (TemplateDeclaration *)
193   {
194   }
195 
visit(TupleDeclaration *)196   void visit (TupleDeclaration *)
197   {
198   }
199 
200   /* Import any other kind of declaration.  If the class does not implement
201      symbol generation routines, the compiler will throw an error.  */
visit(Declaration * d)202   void visit (Declaration *d)
203   {
204     this->result_ = this->make_import (get_symbol_decl (d));
205   }
206 };
207 
208 
209 /* Build a declaration for the symbol D that can be used for the
210    debug_hook imported_module_or_decl.  */
211 tree
build_import_decl(Dsymbol * d)212 build_import_decl (Dsymbol *d)
213 {
214   hash_map_maybe_create<hm_ggc> (imported_decls);
215 
216   if (tree *decl = imported_decls->get (d))
217     return *decl;
218 
219   location_t saved_location = input_location;
220   ImportVisitor v = ImportVisitor ();
221 
222   input_location = make_location_t (d->loc);
223   d->accept (&v);
224   input_location = saved_location;
225 
226   /* Not all visitors set `result'.  */
227   tree isym = v.result ();
228   if (isym != NULL_TREE)
229     imported_decls->put (d, isym);
230 
231   return isym;
232 }
233