Branch data Line data Source code
1 : : // Copyright (C) 2020-2025 Free Software Foundation, Inc.
2 : :
3 : : // This file is part of GCC.
4 : :
5 : : // GCC is free software; you can redistribute it and/or modify it under
6 : : // the terms of the GNU General Public License as published by the Free
7 : : // Software Foundation; either version 3, or (at your option) any later
8 : : // version.
9 : :
10 : : // GCC is distributed in the hope that it will be useful, but WITHOUT ANY
11 : : // WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 : : // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 : : // for more details.
14 : :
15 : : // You should have received a copy of the GNU General Public License
16 : : // along with GCC; see the file COPYING3. If not see
17 : : // <http://www.gnu.org/licenses/>.
18 : :
19 : : #include "rust-compile-item.h"
20 : : #include "rust-compile-implitem.h"
21 : : #include "rust-compile-extern.h"
22 : : #include "rust-substitution-mapper.h"
23 : : #include "rust-type-util.h"
24 : : #include "rust-immutable-name-resolution-context.h"
25 : :
26 : : namespace Rust {
27 : : namespace Compile {
28 : :
29 : : void
30 : 63 : CompileItem::visit (HIR::StaticItem &var)
31 : : {
32 : : // have we already compiled this?
33 : 63 : Bvariable *static_decl_ref = nullptr;
34 : 63 : if (ctx->lookup_var_decl (var.get_mappings ().get_hirid (), &static_decl_ref))
35 : : {
36 : 8 : reference = Backend::var_expression (static_decl_ref, ref_locus);
37 : 8 : return;
38 : : }
39 : :
40 : 55 : HIR::Expr &const_value_expr = var.get_expr ();
41 : :
42 : 55 : TyTy::BaseType *resolved_type = nullptr;
43 : 55 : TyTy::BaseType *expr_type = nullptr;
44 : 55 : bool ok = ctx->get_tyctx ()->lookup_type (var.get_mappings ().get_hirid (),
45 : : &resolved_type);
46 : 55 : rust_assert (ok);
47 : 55 : ok = ctx->get_tyctx ()->lookup_type (
48 : 55 : const_value_expr.get_mappings ().get_hirid (), &expr_type);
49 : 55 : rust_assert (ok);
50 : :
51 : 55 : tree type = TyTyResolveCompile::compile (ctx, resolved_type);
52 : :
53 : 55 : tl::optional<Resolver::CanonicalPath> canonical_path;
54 : :
55 : 55 : if (flag_name_resolution_2_0)
56 : : {
57 : 11 : auto &nr_ctx
58 : 11 : = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
59 : :
60 : 11 : canonical_path
61 : 22 : = nr_ctx.values.to_canonical_path (var.get_mappings ().get_nodeid ());
62 : : }
63 : : else
64 : : {
65 : 88 : canonical_path = ctx->get_mappings ().lookup_canonical_path (
66 : 44 : var.get_mappings ().get_nodeid ());
67 : : }
68 : :
69 : 55 : rust_assert (canonical_path.has_value ());
70 : :
71 : 55 : ctx->push_const_context ();
72 : 55 : tree value
73 : 55 : = compile_constant_item (var.get_mappings ().get_hirid (), expr_type,
74 : 55 : resolved_type, *canonical_path, const_value_expr,
75 : 55 : var.get_locus (), const_value_expr.get_locus ());
76 : 55 : ctx->pop_const_context ();
77 : :
78 : 55 : std::string name = canonical_path->get ();
79 : 55 : std::string asm_name = ctx->mangle_item (resolved_type, *canonical_path);
80 : :
81 : 55 : bool is_external = false;
82 : 55 : bool is_hidden = false;
83 : 55 : bool in_unique_section = true;
84 : :
85 : 55 : Bvariable *static_global
86 : 55 : = Backend::global_variable (name, asm_name, type, is_external, is_hidden,
87 : : in_unique_section, var.get_locus ());
88 : :
89 : 55 : tree init = value == error_mark_node ? error_mark_node : DECL_INITIAL (value);
90 : 55 : Backend::global_variable_set_init (static_global, init);
91 : :
92 : 55 : ctx->insert_var_decl (var.get_mappings ().get_hirid (), static_global);
93 : 55 : ctx->push_var (static_global);
94 : :
95 : 55 : reference = Backend::var_expression (static_global, ref_locus);
96 : 110 : }
97 : :
98 : : void
99 : 551 : CompileItem::visit (HIR::ConstantItem &constant)
100 : : {
101 : 551 : HIR::Expr &const_value_expr = constant.get_expr ();
102 : 551 : auto &mappings = constant.get_mappings ();
103 : :
104 : 551 : if (ctx->lookup_const_decl (mappings.get_hirid (), &reference))
105 : 8 : return;
106 : :
107 : : // resolve the type
108 : 543 : TyTy::BaseType *constant_type = nullptr;
109 : 543 : TyTy::BaseType *expr_type = nullptr;
110 : :
111 : 543 : bool ok
112 : 543 : = ctx->get_tyctx ()->lookup_type (mappings.get_hirid (), &constant_type);
113 : 543 : rust_assert (ok);
114 : 543 : ok = ctx->get_tyctx ()->lookup_type (
115 : 543 : const_value_expr.get_mappings ().get_hirid (), &expr_type);
116 : 543 : rust_assert (ok);
117 : :
118 : : // canonical path
119 : 543 : Resolver::CanonicalPath canonical_path
120 : 543 : = Resolver::CanonicalPath::create_empty ();
121 : :
122 : 543 : if (flag_name_resolution_2_0)
123 : : {
124 : 90 : auto &nr_ctx
125 : 90 : = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
126 : :
127 : 90 : canonical_path
128 : 180 : = nr_ctx.values.to_canonical_path (mappings.get_nodeid ()).value ();
129 : : }
130 : : else
131 : : {
132 : 453 : canonical_path = ctx->get_mappings ()
133 : 453 : .lookup_canonical_path (mappings.get_nodeid ())
134 : 453 : .value ();
135 : : }
136 : :
137 : 543 : ctx->push_const_context ();
138 : 543 : tree const_expr
139 : 543 : = compile_constant_item (mappings.get_hirid (), expr_type, constant_type,
140 : : canonical_path, const_value_expr,
141 : : constant.get_locus (),
142 : 543 : const_value_expr.get_locus ());
143 : 543 : ctx->pop_const_context ();
144 : :
145 : 543 : ctx->push_const (const_expr);
146 : 543 : ctx->insert_const_decl (mappings.get_hirid (), const_expr);
147 : 543 : reference = const_expr;
148 : 543 : }
149 : :
150 : : void
151 : 15091 : CompileItem::visit (HIR::Function &function)
152 : : {
153 : 15091 : TyTy::BaseType *fntype_tyty;
154 : 15091 : if (!ctx->get_tyctx ()->lookup_type (function.get_mappings ().get_hirid (),
155 : : &fntype_tyty))
156 : : {
157 : 0 : rust_fatal_error (function.get_locus (),
158 : : "failed to lookup function type");
159 : 3596 : return;
160 : : }
161 : :
162 : 15091 : rust_assert (fntype_tyty->get_kind () == TyTy::TypeKind::FNDEF);
163 : 15091 : TyTy::FnType *fntype = static_cast<TyTy::FnType *> (fntype_tyty);
164 : 15091 : if (fntype->has_substitutions_defined ())
165 : : {
166 : : // we cant do anything for this only when it is used and a concrete type
167 : : // is given
168 : 3439 : if (concrete == nullptr)
169 : : return;
170 : :
171 : 1670 : rust_assert (concrete->get_kind () == TyTy::TypeKind::FNDEF);
172 : 1670 : TyTy::FnType *concrete_fnty = static_cast<TyTy::FnType *> (concrete);
173 : 1670 : bool is_trait_item_concrete
174 : 1670 : = ctx->get_mappings ()
175 : 1670 : .lookup_trait_item_defid (concrete_fnty->get_id ())
176 : 1670 : .has_value ();
177 : 1670 : if (!is_trait_item_concrete)
178 : : {
179 : 1627 : rust_assert (concrete->get_kind () == TyTy::TypeKind::FNDEF);
180 : 1627 : fntype = static_cast<TyTy::FnType *> (concrete);
181 : : }
182 : : else
183 : : {
184 : 43 : TyTy::BaseType *infer
185 : 43 : = Resolver::SubstMapper::InferSubst (fntype, function.get_locus ());
186 : 43 : TyTy::BaseType *resolved
187 : 43 : = Resolver::unify_site (function.get_mappings ().get_hirid (),
188 : 43 : TyTy::TyWithLocation (infer),
189 : 43 : TyTy::TyWithLocation (concrete),
190 : : function.get_locus ());
191 : :
192 : 43 : rust_assert (resolved->is<TyTy::FnType> ());
193 : 43 : fntype = resolved->as<TyTy::FnType> ();
194 : : }
195 : :
196 : 1670 : fntype->monomorphize ();
197 : : }
198 : : else
199 : : {
200 : : // if this is part of a trait impl block which is not generic we need to
201 : : // ensure associated types are setup
202 : 11652 : HirId id = function.get_mappings ().get_hirid ();
203 : 11652 : if (auto impl_item = ctx->get_mappings ().lookup_hir_implitem (id))
204 : : {
205 : 6026 : Resolver::AssociatedImplTrait *impl = nullptr;
206 : 6026 : bool found = ctx->get_tyctx ()->lookup_associated_trait_impl (
207 : 6026 : impl_item->second, &impl);
208 : 6026 : if (found)
209 : 3139 : impl->setup_raw_associated_types ();
210 : : }
211 : : }
212 : :
213 : 13322 : Resolver::CanonicalPath canonical_path
214 : 13322 : = Resolver::CanonicalPath::create_empty ();
215 : :
216 : 13322 : if (flag_name_resolution_2_0)
217 : : {
218 : 1695 : auto &nr_ctx
219 : 1695 : = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
220 : :
221 : 1695 : auto path = nr_ctx.values.to_canonical_path (
222 : 1695 : function.get_mappings ().get_nodeid ());
223 : :
224 : 1695 : canonical_path = path.value ();
225 : 1695 : }
226 : : else
227 : : {
228 : 11627 : auto path = ctx->get_mappings ().lookup_canonical_path (
229 : 11627 : function.get_mappings ().get_nodeid ());
230 : :
231 : 11627 : canonical_path = *path;
232 : : }
233 : :
234 : 13322 : const std::string asm_name = ctx->mangle_item (fntype, canonical_path);
235 : :
236 : : // items can be forward compiled which means we may not need to invoke this
237 : : // code. We might also have already compiled this generic function as well.
238 : 13322 : tree lookup = NULL_TREE;
239 : 13322 : if (ctx->lookup_function_decl (fntype->get_ty_ref (), &lookup,
240 : : fntype->get_id (), fntype, asm_name))
241 : : {
242 : 1827 : reference = address_expression (lookup, ref_locus);
243 : 1827 : return;
244 : : }
245 : :
246 : 11495 : if (fntype->has_substitutions_defined ())
247 : : {
248 : : // override the Hir Lookups for the substituions in this context
249 : 1469 : fntype->override_context ();
250 : : }
251 : :
252 : 11495 : if (function.get_qualifiers ().is_const ())
253 : 711 : ctx->push_const_context ();
254 : :
255 : 11495 : auto lookup_root_item = ctx->get_mappings ().lookup_hir_item (
256 : 11495 : function.get_mappings ().get_hirid ());
257 : 11495 : bool is_root_item = lookup_root_item.has_value ();
258 : 11495 : tree fndecl
259 : 11495 : = compile_function (is_root_item,
260 : 11495 : function.get_function_name ().as_string (),
261 : : function.get_self_param (),
262 : : function.get_function_params (),
263 : : function.get_qualifiers (), function.get_visibility (),
264 : : function.get_outer_attrs (), function.get_locus (),
265 : 11495 : &function.get_definition (), canonical_path, fntype);
266 : 11494 : reference = address_expression (fndecl, ref_locus);
267 : :
268 : 11494 : if (function.get_qualifiers ().is_const ())
269 : 12205 : ctx->pop_const_context ();
270 : 13321 : }
271 : :
272 : : void
273 : 4806 : CompileItem::visit (HIR::ImplBlock &impl_block)
274 : : {
275 : 4806 : TyTy::BaseType *self_lookup = nullptr;
276 : 9612 : if (!ctx->get_tyctx ()->lookup_type (
277 : 4806 : impl_block.get_type ().get_mappings ().get_hirid (), &self_lookup))
278 : : {
279 : 0 : rust_error_at (impl_block.get_locus (), "failed to resolve type of impl");
280 : 0 : return;
281 : : }
282 : :
283 : 11718 : for (auto &impl_item : impl_block.get_impl_items ())
284 : 6912 : CompileInherentImplItem::Compile (impl_item.get (), ctx);
285 : : }
286 : :
287 : : void
288 : 1225 : CompileItem::visit (HIR::ExternBlock &extern_block)
289 : : {
290 : 3275 : for (auto &item : extern_block.get_extern_items ())
291 : : {
292 : 2050 : CompileExternItem::compile (item.get (), ctx, concrete);
293 : : }
294 : 1225 : }
295 : :
296 : : void
297 : 863 : CompileItem::visit (HIR::Module &module)
298 : : {
299 : 3855 : for (auto &item : module.get_items ())
300 : 2992 : CompileItem::compile (item.get (), ctx);
301 : 863 : }
302 : :
303 : : } // namespace Compile
304 : : } // namespace Rust
|