]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/rust/backend/rust-compile-extern.h
b42878eb64faf5c6eec1bcb3f9a25de380d2945c
[thirdparty/gcc.git] / gcc / rust / backend / rust-compile-extern.h
1 // Copyright (C) 2020-2023 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 #ifndef RUST_COMPILE_EXTERN_ITEM
20 #define RUST_COMPILE_EXTERN_ITEM
21
22 #include "rust-compile-base.h"
23 #include "rust-compile-intrinsic.h"
24
25 namespace Rust {
26 namespace Compile {
27
28 class CompileExternItem : public HIRCompileBase,
29 public HIR::HIRExternalItemVisitor
30 {
31 public:
32 static tree compile (HIR::ExternalItem *item, Context *ctx,
33 TyTy::BaseType *concrete = nullptr,
34 bool is_query_mode = false,
35 Location ref_locus = Location ())
36 {
37 CompileExternItem compiler (ctx, concrete, ref_locus);
38 item->accept_vis (compiler);
39
40 if (is_query_mode && compiler.reference == error_mark_node)
41 rust_internal_error_at (ref_locus, "failed to compile extern item: %s",
42 item->as_string ().c_str ());
43
44 return compiler.reference;
45 }
46
47 void visit (HIR::ExternalStaticItem &item) override
48 {
49 // check if its already been compiled
50 Bvariable *lookup = ctx->get_backend ()->error_variable ();
51 if (ctx->lookup_var_decl (item.get_mappings ().get_hirid (), &lookup))
52 {
53 reference = ctx->get_backend ()->var_expression (lookup, ref_locus);
54 return;
55 }
56
57 TyTy::BaseType *resolved_type = nullptr;
58 bool ok = ctx->get_tyctx ()->lookup_type (item.get_mappings ().get_hirid (),
59 &resolved_type);
60 rust_assert (ok);
61
62 std::string name = item.get_item_name ();
63 // FIXME this is assuming C ABI
64 std::string asm_name = name;
65
66 tree type = TyTyResolveCompile::compile (ctx, resolved_type);
67 bool is_external = true;
68 bool is_hidden = false;
69 bool in_unique_section = false;
70
71 Bvariable *static_global
72 = ctx->get_backend ()->global_variable (name, asm_name, type, is_external,
73 is_hidden, in_unique_section,
74 item.get_locus ());
75 ctx->insert_var_decl (item.get_mappings ().get_hirid (), static_global);
76 ctx->push_var (static_global);
77
78 reference = ctx->get_backend ()->var_expression (static_global, ref_locus);
79 }
80
81 void visit (HIR::ExternalFunctionItem &function) override
82 {
83 TyTy::BaseType *fntype_tyty;
84 if (!ctx->get_tyctx ()->lookup_type (function.get_mappings ().get_hirid (),
85 &fntype_tyty))
86 {
87 rust_fatal_error (function.get_locus (),
88 "failed to lookup function type");
89 return;
90 }
91
92 rust_assert (fntype_tyty->get_kind () == TyTy::TypeKind::FNDEF);
93 TyTy::FnType *fntype = static_cast<TyTy::FnType *> (fntype_tyty);
94 if (fntype->has_subsititions_defined ())
95 {
96 // we cant do anything for this only when it is used and a concrete type
97 // is given
98 if (concrete == nullptr)
99 return;
100 else
101 {
102 rust_assert (concrete->get_kind () == TyTy::TypeKind::FNDEF);
103 fntype = static_cast<TyTy::FnType *> (concrete);
104 }
105 }
106
107 // items can be forward compiled which means we may not need to invoke this
108 // code. We might also have already compiled this generic function as well.
109 tree lookup = NULL_TREE;
110 if (ctx->lookup_function_decl (fntype->get_ty_ref (), &lookup,
111 fntype->get_id (), fntype))
112 {
113 reference = address_expression (lookup, ref_locus);
114 return;
115 }
116
117 if (fntype->has_subsititions_defined ())
118 {
119 // override the Hir Lookups for the substituions in this context
120 fntype->override_context ();
121 }
122
123 if (fntype->get_abi () == ABI::INTRINSIC)
124 {
125 Intrinsics compile (ctx);
126 tree fndecl = compile.compile (fntype);
127 ctx->insert_function_decl (fntype, fndecl);
128 return;
129 }
130
131 tree compiled_fn_type = TyTyResolveCompile::compile (ctx, fntype);
132 std::string ir_symbol_name = function.get_item_name ();
133 std::string asm_name = function.get_item_name ();
134 if (fntype->get_abi () == ABI::RUST)
135 {
136 // then we need to get the canonical path of it and mangle it
137 const Resolver::CanonicalPath *canonical_path = nullptr;
138 bool ok = ctx->get_mappings ()->lookup_canonical_path (
139 function.get_mappings ().get_nodeid (), &canonical_path);
140 rust_assert (ok);
141
142 ir_symbol_name = canonical_path->get () + fntype->subst_as_string ();
143 asm_name = ctx->mangle_item (fntype, *canonical_path);
144 }
145
146 const unsigned int flags = Backend::function_is_declaration;
147 tree fndecl
148 = ctx->get_backend ()->function (compiled_fn_type, ir_symbol_name,
149 asm_name, flags, function.get_locus ());
150 TREE_PUBLIC (fndecl) = 1;
151 setup_abi_options (fndecl, fntype->get_abi ());
152
153 ctx->insert_function_decl (fntype, fndecl);
154
155 reference = address_expression (fndecl, ref_locus);
156 }
157
158 private:
159 CompileExternItem (Context *ctx, TyTy::BaseType *concrete, Location ref_locus)
160 : HIRCompileBase (ctx), concrete (concrete), reference (error_mark_node),
161 ref_locus (ref_locus)
162 {}
163
164 TyTy::BaseType *concrete;
165 tree reference;
166 Location ref_locus;
167 };
168
169 } // namespace Compile
170 } // namespace Rust
171
172 #endif // RUST_COMPILE_EXTERN_ITEM