Branch data Line data Source code
1 : : // Copyright (C) 2020-2024 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-resolve-path.h"
20 : : #include "rust-compile-intrinsic.h"
21 : : #include "rust-compile-item.h"
22 : : #include "rust-compile-implitem.h"
23 : : #include "rust-compile-expr.h"
24 : : #include "rust-hir-trait-resolve.h"
25 : : #include "rust-hir-path-probe.h"
26 : : #include "rust-compile-extern.h"
27 : : #include "rust-constexpr.h"
28 : :
29 : : namespace Rust {
30 : : namespace Compile {
31 : :
32 : : void
33 : 79 : ResolvePathRef::visit (HIR::QualifiedPathInExpression &expr)
34 : : {
35 : 79 : resolved = resolve (expr.get_final_segment ().get_segment (),
36 : : expr.get_mappings (), expr.get_locus (), true);
37 : 79 : }
38 : :
39 : : void
40 : 23436 : ResolvePathRef::visit (HIR::PathInExpression &expr)
41 : : {
42 : 23436 : resolved = resolve (expr.get_final_segment ().get_segment (),
43 : : expr.get_mappings (), expr.get_locus (), false);
44 : 23436 : }
45 : :
46 : : tree
47 : 23515 : ResolvePathRef::resolve (const HIR::PathIdentSegment &final_segment,
48 : : const Analysis::NodeMapping &mappings,
49 : : location_t expr_locus, bool is_qualified_path)
50 : : {
51 : 23515 : TyTy::BaseType *lookup = nullptr;
52 : 23515 : bool ok = ctx->get_tyctx ()->lookup_type (mappings.get_hirid (), &lookup);
53 : 23515 : rust_assert (ok);
54 : :
55 : : // need to look up the reference for this identifier
56 : 23515 : NodeId ref_node_id = UNKNOWN_NODEID;
57 : 23515 : if (!ctx->get_resolver ()->lookup_resolved_name (mappings.get_nodeid (),
58 : : &ref_node_id))
59 : : {
60 : : // this can fail because it might be a Constructor for something
61 : : // in that case the caller should attempt ResolvePathType::Compile
62 : :
63 : : // it might be an enum data-less enum variant
64 : 254 : if (lookup->get_kind () != TyTy::TypeKind::ADT)
65 : 1 : return error_mark_node;
66 : :
67 : 253 : TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (lookup);
68 : 253 : if (adt->is_unit ())
69 : 96 : return unit_expression (ctx, expr_locus);
70 : :
71 : 157 : if (!adt->is_enum ())
72 : 0 : return error_mark_node;
73 : :
74 : 157 : HirId variant_id;
75 : 157 : if (!ctx->get_tyctx ()->lookup_variant_definition (mappings.get_hirid (),
76 : : &variant_id))
77 : 0 : return error_mark_node;
78 : :
79 : 157 : int union_disriminator = -1;
80 : 157 : TyTy::VariantDef *variant = nullptr;
81 : 157 : if (!adt->lookup_variant_by_id (variant_id, &variant,
82 : : &union_disriminator))
83 : 0 : return error_mark_node;
84 : :
85 : : // this can only be for discriminant variants the others are built up
86 : : // using call-expr or struct-init
87 : 157 : rust_assert (variant->get_variant_type ()
88 : : == TyTy::VariantDef::VariantType::NUM);
89 : :
90 : : // we need the actual gcc type
91 : 157 : tree compiled_adt_type = TyTyResolveCompile::compile (ctx, adt);
92 : :
93 : : // make the ctor for the union
94 : 157 : HIR::Expr *discrim_expr = variant->get_discriminant ();
95 : 157 : tree discrim_expr_node = CompileExpr::Compile (discrim_expr, ctx);
96 : 157 : tree folded_discrim_expr = fold_expr (discrim_expr_node);
97 : 157 : tree qualifier = folded_discrim_expr;
98 : :
99 : 157 : return Backend::constructor_expression (compiled_adt_type, true,
100 : : {qualifier}, union_disriminator,
101 : : expr_locus);
102 : : }
103 : :
104 : 23261 : HirId ref;
105 : 23261 : if (!ctx->get_mappings ()->lookup_node_to_hir (ref_node_id, &ref))
106 : : {
107 : 0 : rust_error_at (expr_locus, "reverse call path lookup failure");
108 : 0 : return error_mark_node;
109 : : }
110 : :
111 : : // might be a constant
112 : 23261 : tree constant_expr;
113 : 23261 : if (ctx->lookup_const_decl (ref, &constant_expr))
114 : : {
115 : 757 : TREE_USED (constant_expr) = 1;
116 : 757 : return constant_expr;
117 : : }
118 : :
119 : : // maybe closure binding
120 : 22504 : tree closure_binding = error_mark_node;
121 : 22504 : if (ctx->lookup_closure_binding (ref, &closure_binding))
122 : : {
123 : 7 : TREE_USED (closure_binding) = 1;
124 : 7 : return closure_binding;
125 : : }
126 : :
127 : : // this might be a variable reference or a function reference
128 : 22497 : Bvariable *var = nullptr;
129 : 22497 : if (ctx->lookup_var_decl (ref, &var))
130 : : {
131 : : // TREE_USED is setup in the gcc abstraction here
132 : 16020 : return Backend::var_expression (var, expr_locus);
133 : : }
134 : :
135 : : // might be a match pattern binding
136 : 6477 : tree binding = error_mark_node;
137 : 6477 : if (ctx->lookup_pattern_binding (ref, &binding))
138 : : {
139 : 185 : TREE_USED (binding) = 1;
140 : 185 : return binding;
141 : : }
142 : :
143 : : // it might be a function call
144 : 6292 : if (lookup->get_kind () == TyTy::TypeKind::FNDEF)
145 : : {
146 : 6236 : TyTy::FnType *fntype = static_cast<TyTy::FnType *> (lookup);
147 : 6236 : tree fn = NULL_TREE;
148 : 6236 : if (ctx->lookup_function_decl (fntype->get_ty_ref (), &fn))
149 : : {
150 : 3512 : TREE_USED (fn) = 1;
151 : 5185 : return address_expression (fn, expr_locus);
152 : : }
153 : 2724 : else if (fntype->get_abi () == ABI::INTRINSIC)
154 : : {
155 : 1673 : Intrinsics compile (ctx);
156 : 1673 : fn = compile.compile (fntype);
157 : 1673 : TREE_USED (fn) = 1;
158 : 1673 : return address_expression (fn, expr_locus);
159 : : }
160 : : }
161 : :
162 : : // let the query system figure it out
163 : 1107 : tree resolved_item = query_compile (ref, lookup, final_segment, mappings,
164 : : expr_locus, is_qualified_path);
165 : 1107 : if (resolved_item != error_mark_node)
166 : : {
167 : 1107 : TREE_USED (resolved_item) = 1;
168 : : }
169 : : return resolved_item;
170 : : }
171 : :
172 : : tree
173 : 1107 : HIRCompileBase::query_compile (HirId ref, TyTy::BaseType *lookup,
174 : : const HIR::PathIdentSegment &final_segment,
175 : : const Analysis::NodeMapping &mappings,
176 : : location_t expr_locus, bool is_qualified_path)
177 : : {
178 : 1107 : HIR::Item *resolved_item = ctx->get_mappings ()->lookup_hir_item (ref);
179 : 1107 : HirId parent_block;
180 : 1107 : HIR::ExternalItem *resolved_extern_item
181 : 1107 : = ctx->get_mappings ()->lookup_hir_extern_item (ref, &parent_block);
182 : 1107 : bool is_hir_item = resolved_item != nullptr;
183 : 1107 : bool is_hir_extern_item = resolved_extern_item != nullptr;
184 : 1107 : bool is_fn = lookup->get_kind () == TyTy::TypeKind::FNDEF;
185 : 1107 : if (is_hir_item)
186 : : {
187 : 578 : if (!lookup->has_substitutions_defined ())
188 : 134 : return CompileItem::compile (resolved_item, ctx, nullptr, true,
189 : 134 : expr_locus);
190 : : else
191 : 444 : return CompileItem::compile (resolved_item, ctx, lookup, true,
192 : 444 : expr_locus);
193 : : }
194 : 529 : else if (is_hir_extern_item)
195 : : {
196 : 9 : if (!lookup->has_substitutions_defined ())
197 : 9 : return CompileExternItem::compile (resolved_extern_item, ctx, nullptr,
198 : 9 : true, expr_locus);
199 : : else
200 : 0 : return CompileExternItem::compile (resolved_extern_item, ctx, lookup,
201 : 0 : true, expr_locus);
202 : : }
203 : : else
204 : : {
205 : 520 : if (is_fn)
206 : : {
207 : 520 : TyTy::FnType *fn = static_cast<TyTy::FnType *> (lookup);
208 : 520 : TyTy::BaseType *receiver = nullptr;
209 : :
210 : 520 : if (fn->is_method ())
211 : : {
212 : 91 : receiver = fn->get_self_type ();
213 : 91 : receiver = receiver->destructure ();
214 : :
215 : 91 : return resolve_method_address (fn, receiver, expr_locus);
216 : : }
217 : : }
218 : :
219 : 429 : HirId parent_impl_id = UNKNOWN_HIRID;
220 : 429 : HIR::ImplItem *resolved_item
221 : 429 : = ctx->get_mappings ()->lookup_hir_implitem (ref, &parent_impl_id);
222 : 429 : bool is_impl_item = resolved_item != nullptr;
223 : 429 : if (is_impl_item)
224 : : {
225 : 291 : if (!lookup->has_substitutions_defined ())
226 : 150 : return CompileInherentImplItem::Compile (resolved_item, ctx,
227 : 150 : nullptr, true, expr_locus);
228 : : else
229 : 141 : return CompileInherentImplItem::Compile (resolved_item, ctx, lookup,
230 : 141 : true, expr_locus);
231 : : }
232 : : else
233 : : {
234 : : // it might be resolved to a trait item
235 : 138 : HIR::TraitItem *trait_item
236 : 138 : = ctx->get_mappings ()->lookup_hir_trait_item (ref);
237 : 138 : HIR::Trait *trait = ctx->get_mappings ()->lookup_trait_item_mapping (
238 : 138 : trait_item->get_mappings ().get_hirid ());
239 : :
240 : 138 : Resolver::TraitReference *trait_ref
241 : 138 : = &Resolver::TraitReference::error_node ();
242 : 138 : bool ok = ctx->get_tyctx ()->lookup_trait_reference (
243 : 138 : trait->get_mappings ().get_defid (), &trait_ref);
244 : 138 : rust_assert (ok);
245 : :
246 : 138 : TyTy::BaseType *receiver = nullptr;
247 : 138 : ok = ctx->get_tyctx ()->lookup_receiver (mappings.get_hirid (),
248 : : &receiver);
249 : 138 : rust_assert (ok);
250 : 138 : receiver = receiver->destructure ();
251 : :
252 : : // the type resolver can only resolve type bounds to their trait
253 : : // item so its up to us to figure out if this path should resolve
254 : : // to an trait-impl-block-item or if it can be defaulted to the
255 : : // trait-impl-item's definition
256 : 138 : auto candidates
257 : : = Resolver::PathProbeImplTrait::Probe (receiver, final_segment,
258 : 138 : trait_ref);
259 : 138 : if (candidates.size () == 0)
260 : : {
261 : : // this means we are defaulting back to the trait_item if
262 : : // possible
263 : 107 : Resolver::TraitItemReference *trait_item_ref = nullptr;
264 : 107 : bool ok = trait_ref->lookup_hir_trait_item (*trait_item,
265 : : &trait_item_ref);
266 : 107 : rust_assert (ok); // found
267 : 107 : rust_assert (trait_item_ref->is_optional ()); // has definition
268 : :
269 : 107 : return CompileTraitItem::Compile (
270 : : trait_item_ref->get_hir_trait_item (), ctx, lookup, true,
271 : : expr_locus);
272 : : }
273 : : else
274 : : {
275 : 31 : rust_assert (candidates.size () == 1);
276 : :
277 : 31 : auto candidate = *candidates.begin ();
278 : 31 : rust_assert (candidate.is_impl_candidate ());
279 : :
280 : 31 : HIR::ImplBlock *impl = candidate.item.impl.parent;
281 : 31 : HIR::ImplItem *impl_item = candidate.item.impl.impl_item;
282 : :
283 : 31 : TyTy::BaseType *self = nullptr;
284 : 31 : bool ok = ctx->get_tyctx ()->lookup_type (
285 : 31 : impl->get_type ()->get_mappings ().get_hirid (), &self);
286 : 31 : rust_assert (ok);
287 : :
288 : 31 : if (!lookup->has_substitutions_defined ())
289 : 0 : return CompileInherentImplItem::Compile (impl_item, ctx,
290 : : nullptr, true,
291 : 0 : expr_locus);
292 : : else
293 : 31 : return CompileInherentImplItem::Compile (impl_item, ctx, lookup,
294 : 31 : true, expr_locus);
295 : : }
296 : 138 : }
297 : : }
298 : :
299 : : return error_mark_node;
300 : : }
301 : :
302 : : } // namespace Compile
303 : : } // namespace Rust
|