]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_codegen_gcc/src/callee.rs
New upstream version 1.70.0+dfsg1
[rustc.git] / compiler / rustc_codegen_gcc / src / callee.rs
CommitLineData
353b0b11
FG
1#[cfg(feature="master")]
2use gccjit::{FnAttribute, Visibility};
3use gccjit::{FunctionType, Function};
9ffffee4 4use rustc_middle::ty::{self, Instance, TypeVisitableExt};
c295e0f8
XL
5use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt};
6
353b0b11 7use crate::attributes;
c295e0f8
XL
8use crate::context::CodegenCx;
9
10/// Codegens a reference to a fn/method item, monomorphizing and
11/// inlining as it goes.
12///
13/// # Parameters
14///
15/// - `cx`: the crate context
16/// - `instance`: the instance to be instantiated
353b0b11 17pub fn get_fn<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, instance: Instance<'tcx>) -> Function<'gcc> {
c295e0f8
XL
18 let tcx = cx.tcx();
19
20 assert!(!instance.substs.needs_infer());
21 assert!(!instance.substs.has_escaping_bound_vars());
22
353b0b11
FG
23 let sym = tcx.symbol_name(instance).name;
24
c295e0f8
XL
25 if let Some(&func) = cx.function_instances.borrow().get(&instance) {
26 return func;
27 }
28
c295e0f8
XL
29 let fn_abi = cx.fn_abi_of_instance(instance, ty::List::empty());
30
31 let func =
353b0b11
FG
32 if let Some(_func) = cx.get_declared_value(&sym) {
33 // FIXME(antoyo): we never reach this because get_declared_value only returns global variables
34 // and here we try to get a function.
35 unreachable!();
36 /*
c295e0f8
XL
37 // Create a fn pointer with the new signature.
38 let ptrty = fn_abi.ptr_to_gcc_type(cx);
39
40 // This is subtle and surprising, but sometimes we have to bitcast
41 // the resulting fn pointer. The reason has to do with external
42 // functions. If you have two crates that both bind the same C
43 // library, they may not use precisely the same types: for
44 // example, they will probably each declare their own structs,
45 // which are distinct types from LLVM's point of view (nominal
46 // types).
47 //
48 // Now, if those two crates are linked into an application, and
49 // they contain inlined code, you can wind up with a situation
50 // where both of those functions wind up being loaded into this
51 // application simultaneously. In that case, the same function
52 // (from LLVM's point of view) requires two types. But of course
53 // LLVM won't allow one function to have two types.
54 //
55 // What we currently do, therefore, is declare the function with
56 // one of the two types (whichever happens to come first) and then
57 // bitcast as needed when the function is referenced to make sure
58 // it has the type we expect.
59 //
60 // This can occur on either a crate-local or crate-external
61 // reference. It also occurs when testing libcore and in some
62 // other weird situations. Annoying.
63 if cx.val_ty(func) != ptrty {
64 // TODO(antoyo): cast the pointer.
65 func
66 }
67 else {
68 func
353b0b11 69 }*/
c295e0f8
XL
70 }
71 else {
72 cx.linkage.set(FunctionType::Extern);
73 let func = cx.declare_fn(&sym, &fn_abi);
74
353b0b11
FG
75 attributes::from_fn_attrs(cx, func, instance);
76
77 let instance_def_id = instance.def_id();
78
c295e0f8 79 // TODO(antoyo): set linkage and attributes.
353b0b11
FG
80
81 // Apply an appropriate linkage/visibility value to our item that we
82 // just declared.
83 //
84 // This is sort of subtle. Inside our codegen unit we started off
85 // compilation by predefining all our own `MonoItem` instances. That
86 // is, everything we're codegenning ourselves is already defined. That
87 // means that anything we're actually codegenning in this codegen unit
88 // will have hit the above branch in `get_declared_value`. As a result,
89 // we're guaranteed here that we're declaring a symbol that won't get
90 // defined, or in other words we're referencing a value from another
91 // codegen unit or even another crate.
92 //
93 // So because this is a foreign value we blanket apply an external
94 // linkage directive because it's coming from a different object file.
95 // The visibility here is where it gets tricky. This symbol could be
96 // referencing some foreign crate or foreign library (an `extern`
97 // block) in which case we want to leave the default visibility. We may
98 // also, though, have multiple codegen units. It could be a
99 // monomorphization, in which case its expected visibility depends on
100 // whether we are sharing generics or not. The important thing here is
101 // that the visibility we apply to the declaration is the same one that
102 // has been applied to the definition (wherever that definition may be).
103 let is_generic = instance.substs.non_erasable_generics().next().is_some();
104
105 if is_generic {
106 // This is a monomorphization. Its expected visibility depends
107 // on whether we are in share-generics mode.
108
109 if cx.tcx.sess.opts.share_generics() {
110 // We are in share_generics mode.
111
112 if let Some(instance_def_id) = instance_def_id.as_local() {
113 // This is a definition from the current crate. If the
114 // definition is unreachable for downstream crates or
115 // the current crate does not re-export generics, the
116 // definition of the instance will have been declared
117 // as `hidden`.
118 if cx.tcx.is_unreachable_local_definition(instance_def_id)
119 || !cx.tcx.local_crate_exports_generics()
120 {
121 #[cfg(feature="master")]
122 func.add_attribute(FnAttribute::Visibility(Visibility::Hidden));
123 }
124 } else {
125 // This is a monomorphization of a generic function
126 // defined in an upstream crate.
127 if instance.upstream_monomorphization(tcx).is_some() {
128 // This is instantiated in another crate. It cannot
129 // be `hidden`.
130 } else {
131 // This is a local instantiation of an upstream definition.
132 // If the current crate does not re-export it
133 // (because it is a C library or an executable), it
134 // will have been declared `hidden`.
135 if !cx.tcx.local_crate_exports_generics() {
136 #[cfg(feature="master")]
137 func.add_attribute(FnAttribute::Visibility(Visibility::Hidden));
138 }
139 }
140 }
141 } else {
142 // When not sharing generics, all instances are in the same
143 // crate and have hidden visibility
144 #[cfg(feature="master")]
145 func.add_attribute(FnAttribute::Visibility(Visibility::Hidden));
146 }
147 } else {
148 // This is a non-generic function
149 if cx.tcx.is_codegened_item(instance_def_id) {
150 // This is a function that is instantiated in the local crate
151
152 if instance_def_id.is_local() {
153 // This is function that is defined in the local crate.
154 // If it is not reachable, it is hidden.
155 if !cx.tcx.is_reachable_non_generic(instance_def_id) {
156 #[cfg(feature="master")]
157 func.add_attribute(FnAttribute::Visibility(Visibility::Hidden));
158 }
159 } else {
160 // This is a function from an upstream crate that has
161 // been instantiated here. These are always hidden.
162 #[cfg(feature="master")]
163 func.add_attribute(FnAttribute::Visibility(Visibility::Hidden));
164 }
165 }
166 }
167
c295e0f8
XL
168 func
169 };
170
171 cx.function_instances.borrow_mut().insert(instance, func);
172
173 func
174}