Line data Source code
1 : // Copyright (C) 2020-2026 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 57 : CompileItem::visit (HIR::StaticItem &var)
31 : {
32 : // have we already compiled this?
33 57 : Bvariable *static_decl_ref = nullptr;
34 57 : if (ctx->lookup_var_decl (var.get_mappings ().get_hirid (), &static_decl_ref))
35 : {
36 7 : reference = Backend::var_expression (static_decl_ref, ref_locus);
37 7 : return;
38 : }
39 :
40 50 : HIR::Expr &const_value_expr = var.get_expr ();
41 :
42 50 : TyTy::BaseType *resolved_type = nullptr;
43 50 : TyTy::BaseType *expr_type = nullptr;
44 50 : bool ok = ctx->get_tyctx ()->lookup_type (var.get_mappings ().get_hirid (),
45 : &resolved_type);
46 50 : rust_assert (ok);
47 50 : ok = ctx->get_tyctx ()->lookup_type (
48 50 : const_value_expr.get_mappings ().get_hirid (), &expr_type);
49 50 : rust_assert (ok);
50 :
51 50 : tree type = TyTyResolveCompile::compile (ctx, resolved_type);
52 :
53 50 : auto &nr_ctx
54 50 : = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
55 :
56 50 : Resolver::CanonicalPath canonical_path
57 50 : = nr_ctx.to_canonical_path (var.get_mappings ().get_nodeid ());
58 :
59 50 : ctx->push_const_context ();
60 50 : tree value
61 50 : = compile_constant_item (var.get_mappings ().get_hirid (), expr_type,
62 : resolved_type, canonical_path, const_value_expr,
63 50 : var.get_locus (), const_value_expr.get_locus ());
64 50 : ctx->pop_const_context ();
65 :
66 50 : std::string name = canonical_path.get ();
67 50 : std::string asm_name = ctx->mangle_item (resolved_type, canonical_path);
68 :
69 50 : bool is_external = false;
70 50 : bool is_hidden = false;
71 50 : bool in_unique_section = true;
72 :
73 50 : Bvariable *static_global
74 50 : = Backend::global_variable (name, asm_name, type, is_external, is_hidden,
75 : in_unique_section, var.get_locus ());
76 :
77 50 : tree init = value == error_mark_node ? error_mark_node : DECL_INITIAL (value);
78 50 : Backend::global_variable_set_init (static_global, init);
79 :
80 50 : ctx->insert_var_decl (var.get_mappings ().get_hirid (), static_global);
81 50 : ctx->push_var (static_global);
82 :
83 50 : reference = Backend::var_expression (static_global, ref_locus);
84 50 : }
85 :
86 : void
87 587 : CompileItem::visit (HIR::ConstantItem &constant)
88 : {
89 587 : HIR::Expr &const_value_expr = constant.get_expr ();
90 587 : auto &mappings = constant.get_mappings ();
91 :
92 587 : if (ctx->lookup_const_decl (mappings.get_hirid (), &reference))
93 81 : return;
94 :
95 : // resolve the type
96 534 : TyTy::BaseType *constant_type = nullptr;
97 534 : TyTy::BaseType *expr_type = nullptr;
98 :
99 534 : bool ok
100 534 : = ctx->get_tyctx ()->lookup_type (mappings.get_hirid (), &constant_type);
101 534 : rust_assert (ok);
102 534 : ok = ctx->get_tyctx ()->lookup_type (
103 534 : const_value_expr.get_mappings ().get_hirid (), &expr_type);
104 534 : rust_assert (ok);
105 :
106 534 : auto &nr_ctx
107 534 : = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
108 :
109 : // canonical path
110 534 : Resolver::CanonicalPath canonical_path
111 534 : = nr_ctx.to_canonical_path (mappings.get_nodeid ());
112 534 : if (constant_type->is<const TyTy::FnType> ())
113 : {
114 56 : if (concrete == nullptr)
115 28 : return;
116 :
117 28 : rust_assert (concrete->get_kind () == TyTy::TypeKind::FNDEF);
118 28 : TyTy::FnType *concrete_fnty = static_cast<TyTy::FnType *> (concrete);
119 :
120 28 : concrete_fnty->override_context ();
121 28 : constant_type = expr_type = concrete_fnty->get_return_type ();
122 : }
123 :
124 506 : ctx->push_const_context ();
125 506 : tree const_expr
126 506 : = compile_constant_item (mappings.get_hirid (), expr_type, constant_type,
127 : canonical_path, const_value_expr,
128 : constant.get_locus (),
129 506 : const_value_expr.get_locus ());
130 506 : ctx->pop_const_context ();
131 :
132 506 : ctx->push_const (const_expr);
133 506 : ctx->insert_const_decl (mappings.get_hirid (), const_expr);
134 506 : reference = const_expr;
135 534 : }
136 :
137 : void
138 18079 : CompileItem::visit (HIR::Function &function)
139 : {
140 18079 : TyTy::BaseType *fntype_tyty;
141 18079 : if (!ctx->get_tyctx ()->lookup_type (function.get_mappings ().get_hirid (),
142 : &fntype_tyty))
143 : {
144 0 : rust_fatal_error (function.get_locus (),
145 : "failed to lookup function type");
146 5604 : return;
147 : }
148 :
149 18079 : rust_assert (fntype_tyty->get_kind () == TyTy::TypeKind::FNDEF);
150 18079 : TyTy::FnType *fntype = static_cast<TyTy::FnType *> (fntype_tyty);
151 18079 : if (fntype->has_substitutions_defined ())
152 : {
153 : // we cant do anything for this only when it is used and a concrete type
154 : // is given
155 3535 : if (concrete == nullptr)
156 : return;
157 :
158 1762 : rust_assert (concrete->get_kind () == TyTy::TypeKind::FNDEF);
159 1762 : TyTy::FnType *concrete_fnty = static_cast<TyTy::FnType *> (concrete);
160 1762 : bool is_trait_item_concrete
161 1762 : = ctx->get_mappings ()
162 1762 : .lookup_trait_item_defid (concrete_fnty->get_id ())
163 1762 : .has_value ();
164 1762 : if (!is_trait_item_concrete)
165 : {
166 1722 : rust_assert (concrete->get_kind () == TyTy::TypeKind::FNDEF);
167 1722 : fntype = static_cast<TyTy::FnType *> (concrete);
168 : }
169 : else
170 : {
171 40 : TyTy::BaseType *infer
172 40 : = Resolver::SubstMapper::InferSubst (fntype, function.get_locus ());
173 40 : TyTy::BaseType *resolved
174 40 : = Resolver::unify_site (function.get_mappings ().get_hirid (),
175 40 : TyTy::TyWithLocation (infer),
176 40 : TyTy::TyWithLocation (concrete),
177 : function.get_locus ());
178 :
179 40 : rust_assert (resolved->is<TyTy::FnType> ());
180 40 : fntype = resolved->as<TyTy::FnType> ();
181 : }
182 :
183 1762 : fntype->monomorphize ();
184 : }
185 : else
186 : {
187 : // if this is part of a trait impl block which is not generic we need to
188 : // ensure associated types are setup
189 14544 : HirId id = function.get_mappings ().get_hirid ();
190 14544 : if (auto impl_item = ctx->get_mappings ().lookup_hir_implitem (id))
191 : {
192 9040 : Resolver::AssociatedImplTrait *impl = nullptr;
193 9040 : bool found = ctx->get_tyctx ()->lookup_associated_trait_impl (
194 9040 : impl_item->second, &impl);
195 9040 : if (found)
196 5534 : impl->setup_raw_associated_types ();
197 : }
198 : }
199 :
200 16306 : auto &nr_ctx
201 16306 : = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
202 :
203 16306 : Resolver::CanonicalPath canonical_path
204 16306 : = nr_ctx.to_canonical_path (function.get_mappings ().get_nodeid ());
205 :
206 16306 : const std::string asm_name = ctx->mangle_item (fntype, canonical_path);
207 :
208 : // items can be forward compiled which means we may not need to invoke this
209 : // code. We might also have already compiled this generic function as well.
210 16306 : tree lookup = NULL_TREE;
211 16306 : if (ctx->lookup_function_decl (fntype->get_ty_ref (), &lookup,
212 : fntype->get_id (), fntype, asm_name))
213 : {
214 3831 : reference = address_expression (lookup, ref_locus);
215 3831 : return;
216 : }
217 :
218 12475 : if (fntype->has_substitutions_defined ())
219 : {
220 : // override the Hir Lookups for the substituions in this context
221 1502 : fntype->override_context ();
222 : }
223 :
224 12475 : if (function.get_qualifiers ().is_const ())
225 664 : ctx->push_const_context ();
226 :
227 12475 : auto lookup_root_item = ctx->get_mappings ().lookup_hir_item (
228 12475 : function.get_mappings ().get_hirid ());
229 12475 : bool is_root_item = lookup_root_item.has_value ();
230 12475 : tree fndecl
231 12475 : = compile_function (is_root_item,
232 12475 : function.get_function_name ().as_string (),
233 : function.get_self_param (),
234 : function.get_function_params (),
235 : function.get_qualifiers (), function.get_visibility (),
236 : function.get_outer_attrs (), function.get_locus (),
237 12475 : &function.get_definition (), canonical_path, fntype);
238 12475 : reference = address_expression (fndecl, ref_locus);
239 :
240 12475 : if (function.get_qualifiers ().is_const ())
241 13139 : ctx->pop_const_context ();
242 16306 : }
243 :
244 : void
245 5525 : CompileItem::visit (HIR::ImplBlock &impl_block)
246 : {
247 5525 : TyTy::BaseType *self_lookup = nullptr;
248 11050 : if (!ctx->get_tyctx ()->lookup_type (
249 5525 : impl_block.get_type ().get_mappings ().get_hirid (), &self_lookup))
250 : {
251 0 : rust_error_at (impl_block.get_locus (), "failed to resolve type of impl");
252 0 : return;
253 : }
254 :
255 13510 : for (auto &impl_item : impl_block.get_impl_items ())
256 7985 : CompileInherentImplItem::Compile (impl_item.get (), ctx);
257 : }
258 :
259 : void
260 1438 : CompileItem::visit (HIR::ExternBlock &extern_block)
261 : {
262 3617 : for (auto &item : extern_block.get_extern_items ())
263 : {
264 2179 : CompileExternItem::compile (item.get (), ctx, concrete);
265 : }
266 1438 : }
267 :
268 : void
269 1173 : CompileItem::visit (HIR::Module &module)
270 : {
271 5054 : for (auto &item : module.get_items ())
272 3881 : CompileItem::compile (item.get (), ctx);
273 1173 : }
274 :
275 : void
276 792 : CompileItem::visit (HIR::TupleStruct &tuple_struct_decl)
277 : {
278 792 : TyTy::BaseType *lookup = nullptr;
279 792 : if (!ctx->get_tyctx ()->lookup_type (
280 792 : tuple_struct_decl.get_mappings ().get_hirid (), &lookup))
281 : {
282 0 : rust_error_at (tuple_struct_decl.get_locus (), "failed to resolve type");
283 0 : return;
284 : }
285 :
286 792 : if (lookup->is_concrete ())
287 512 : TyTyResolveCompile::compile (ctx, lookup);
288 : }
289 :
290 : void
291 477 : CompileItem::visit (HIR::Enum &enum_decl)
292 : {
293 477 : TyTy::BaseType *lookup = nullptr;
294 477 : if (!ctx->get_tyctx ()->lookup_type (enum_decl.get_mappings ().get_hirid (),
295 : &lookup))
296 : {
297 0 : rust_error_at (enum_decl.get_locus (), "failed to resolve type");
298 0 : return;
299 : }
300 :
301 477 : if (lookup->is_concrete ())
302 254 : TyTyResolveCompile::compile (ctx, lookup);
303 : }
304 :
305 : void
306 96 : CompileItem::visit (HIR::Union &union_decl)
307 : {
308 96 : TyTy::BaseType *lookup = nullptr;
309 96 : if (!ctx->get_tyctx ()->lookup_type (union_decl.get_mappings ().get_hirid (),
310 : &lookup))
311 : {
312 0 : rust_error_at (union_decl.get_locus (), "failed to resolve type");
313 0 : return;
314 : }
315 :
316 96 : if (lookup->is_concrete ())
317 23 : TyTyResolveCompile::compile (ctx, lookup);
318 : }
319 :
320 : void
321 1308 : CompileItem::visit (HIR::StructStruct &struct_decl)
322 : {
323 1308 : TyTy::BaseType *lookup = nullptr;
324 1308 : if (!ctx->get_tyctx ()->lookup_type (struct_decl.get_mappings ().get_hirid (),
325 : &lookup))
326 : {
327 0 : rust_error_at (struct_decl.get_locus (), "failed to resolve type");
328 0 : return;
329 : }
330 :
331 1308 : if (lookup->is_concrete ())
332 904 : TyTyResolveCompile::compile (ctx, lookup);
333 : }
334 :
335 : } // namespace Compile
336 : } // namespace Rust
|