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