]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_codegen_llvm/src/declare.rs
New upstream version 1.71.1+dfsg1
[rustc.git] / compiler / rustc_codegen_llvm / src / declare.rs
CommitLineData
54a0048b
SL
1//! Declare various LLVM values.
2//!
3//! Prefer using functions and methods from this module rather than calling LLVM
4//! functions directly. These functions do some additional work to ensure we do
94b46f34 5//! the right thing given the preconceptions of codegen.
54a0048b
SL
6//!
7//! Some useful guidelines:
8//!
9//! * Use declare_* family of methods if you are declaring, but are not
b7449926
XL
10//! interested in defining the Value they return.
11//! * Use define_* family of methods when you might be defining the Value.
54a0048b 12//! * When in doubt, define.
476ff2be 13
60c5eb7d 14use crate::abi::{FnAbi, FnAbiLlvmExt};
9fa01778
XL
15use crate::attributes;
16use crate::context::CodegenCx;
dfeec247
XL
17use crate::llvm;
18use crate::llvm::AttributePlace::Function;
9fa01778
XL
19use crate::type_::Type;
20use crate::value::Value;
064997fb 21use rustc_codegen_ssa::traits::TypeMembershipMethods;
49aad941
FG
22use rustc_middle::ty::{Instance, Ty};
23use rustc_symbol_mangling::typeid::{
24 kcfi_typeid_for_fnabi, kcfi_typeid_for_instance, typeid_for_fnabi, typeid_for_instance,
25 TypeIdOptions,
26};
5e7ed085 27use smallvec::SmallVec;
54a0048b 28
54a0048b
SL
29/// Declare a function.
30///
31/// If there’s a value with the same name already declared, the function will
b7449926 32/// update the declaration and return existing Value instead.
a2a8927a 33fn declare_raw_fn<'ll>(
b7449926
XL
34 cx: &CodegenCx<'ll, '_>,
35 name: &str,
36 callconv: llvm::CallConv,
6a06907d 37 unnamed: llvm::UnnamedAddr,
2b03887a 38 visibility: llvm::Visibility,
b7449926
XL
39 ty: &'ll Type,
40) -> &'ll Value {
54a0048b 41 debug!("declare_raw_fn(name={:?}, ty={:?})", name, ty);
ba9703b0
XL
42 let llfn = unsafe {
43 llvm::LLVMRustGetOrInsertFunction(cx.llmod, name.as_ptr().cast(), name.len(), ty)
44 };
54a0048b
SL
45
46 llvm::SetFunctionCallConv(llfn, callconv);
6a06907d 47 llvm::SetUnnamedAddress(llfn, unnamed);
2b03887a 48 llvm::set_visibility(llfn, visibility);
54a0048b 49
5e7ed085
FG
50 let mut attrs = SmallVec::<[_; 4]>::new();
51
29967ef6 52 if cx.tcx.sess.opts.cg.no_redzone.unwrap_or(cx.tcx.sess.target.disable_redzone) {
5e7ed085 53 attrs.push(llvm::AttributeKind::NoRedZone.create_attr(cx.llcx));
54a0048b
SL
54 }
55
5e7ed085
FG
56 attrs.extend(attributes::non_lazy_bind_attr(cx));
57
58 attributes::apply_to_llfn(llfn, Function, &attrs);
5099ac24 59
54a0048b
SL
60 llfn
61}
62
a2a8927a 63impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
1b1a35ee
XL
64 /// Declare a global value.
65 ///
66 /// If there’s a value with the same name already declared, the function will
67 /// return its Value instead.
68 pub fn declare_global(&self, name: &str, ty: &'ll Type) -> &'ll Value {
a1dfa0c6 69 debug!("declare_global(name={:?})", name);
dfeec247 70 unsafe { llvm::LLVMRustGetOrInsertGlobal(self.llmod, name.as_ptr().cast(), name.len(), ty) }
54a0048b
SL
71 }
72
1b1a35ee
XL
73 /// Declare a C ABI function.
74 ///
75 /// Only use this for foreign function ABIs and glue. For Rust functions use
76 /// `declare_fn` instead.
77 ///
78 /// If there’s a value with the same name already declared, the function will
79 /// update the declaration and return existing Value instead.
6a06907d
XL
80 pub fn declare_cfn(
81 &self,
82 name: &str,
83 unnamed: llvm::UnnamedAddr,
84 fn_type: &'ll Type,
85 ) -> &'ll Value {
2b03887a
FG
86 // Declare C ABI functions with the visibility used by C by default.
87 let visibility = if self.tcx.sess.target.default_hidden_visibility {
88 llvm::Visibility::Hidden
89 } else {
90 llvm::Visibility::Default
91 };
92
93 declare_raw_fn(self, name, llvm::CCallConv, unnamed, visibility, fn_type)
54a0048b
SL
94 }
95
487cf647
FG
96 /// Declare an entry Function
97 ///
98 /// The ABI of this function can change depending on the target (although for now the same as
99 /// `declare_cfn`)
100 ///
101 /// If there’s a value with the same name already declared, the function will
102 /// update the declaration and return existing Value instead.
103 pub fn declare_entry_fn(
104 &self,
105 name: &str,
106 callconv: llvm::CallConv,
107 unnamed: llvm::UnnamedAddr,
108 fn_type: &'ll Type,
109 ) -> &'ll Value {
110 let visibility = if self.tcx.sess.target.default_hidden_visibility {
111 llvm::Visibility::Hidden
112 } else {
113 llvm::Visibility::Default
114 };
115 declare_raw_fn(self, name, callconv, unnamed, visibility, fn_type)
116 }
117
1b1a35ee
XL
118 /// Declare a Rust function.
119 ///
120 /// If there’s a value with the same name already declared, the function will
121 /// update the declaration and return existing Value instead.
49aad941
FG
122 pub fn declare_fn(
123 &self,
124 name: &str,
125 fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
126 instance: Option<Instance<'tcx>>,
127 ) -> &'ll Value {
60c5eb7d 128 debug!("declare_rust_fn(name={:?}, fn_abi={:?})", name, fn_abi);
a1dfa0c6 129
6a06907d
XL
130 // Function addresses in Rust are never significant, allowing functions to
131 // be merged.
132 let llfn = declare_raw_fn(
133 self,
134 name,
135 fn_abi.llvm_cconv(),
136 llvm::UnnamedAddr::Global,
2b03887a 137 llvm::Visibility::Default,
6a06907d
XL
138 fn_abi.llvm_type(self),
139 );
60c5eb7d 140 fn_abi.apply_attrs_llfn(self, llfn);
064997fb
FG
141
142 if self.tcx.sess.is_sanitizer_cfi_enabled() {
49aad941
FG
143 if let Some(instance) = instance {
144 let typeid = typeid_for_instance(self.tcx, &instance, TypeIdOptions::empty());
145 self.set_type_metadata(llfn, typeid);
146 let typeid =
147 typeid_for_instance(self.tcx, &instance, TypeIdOptions::GENERALIZE_POINTERS);
148 self.add_type_metadata(llfn, typeid);
149 let typeid =
150 typeid_for_instance(self.tcx, &instance, TypeIdOptions::NORMALIZE_INTEGERS);
151 self.add_type_metadata(llfn, typeid);
152 let typeid = typeid_for_instance(
153 self.tcx,
154 &instance,
155 TypeIdOptions::GENERALIZE_POINTERS | TypeIdOptions::NORMALIZE_INTEGERS,
156 );
157 self.add_type_metadata(llfn, typeid);
158 } else {
159 let typeid = typeid_for_fnabi(self.tcx, fn_abi, TypeIdOptions::empty());
160 self.set_type_metadata(llfn, typeid);
161 let typeid = typeid_for_fnabi(self.tcx, fn_abi, TypeIdOptions::GENERALIZE_POINTERS);
162 self.add_type_metadata(llfn, typeid);
163 let typeid = typeid_for_fnabi(self.tcx, fn_abi, TypeIdOptions::NORMALIZE_INTEGERS);
164 self.add_type_metadata(llfn, typeid);
165 let typeid = typeid_for_fnabi(
166 self.tcx,
167 fn_abi,
168 TypeIdOptions::GENERALIZE_POINTERS | TypeIdOptions::NORMALIZE_INTEGERS,
169 );
170 self.add_type_metadata(llfn, typeid);
171 }
064997fb
FG
172 }
173
9c376795 174 if self.tcx.sess.is_sanitizer_kcfi_enabled() {
49aad941
FG
175 // LLVM KCFI does not support multiple !kcfi_type attachments
176 let mut options = TypeIdOptions::empty();
177 if self.tcx.sess.is_sanitizer_cfi_generalize_pointers_enabled() {
178 options.insert(TypeIdOptions::GENERALIZE_POINTERS);
179 }
180 if self.tcx.sess.is_sanitizer_cfi_normalize_integers_enabled() {
181 options.insert(TypeIdOptions::NORMALIZE_INTEGERS);
182 }
183
184 if let Some(instance) = instance {
185 let kcfi_typeid = kcfi_typeid_for_instance(self.tcx, &instance, options);
186 self.set_kcfi_type_metadata(llfn, kcfi_typeid);
187 } else {
188 let kcfi_typeid = kcfi_typeid_for_fnabi(self.tcx, fn_abi, options);
189 self.set_kcfi_type_metadata(llfn, kcfi_typeid);
190 }
9c376795
FG
191 }
192
a1dfa0c6 193 llfn
54a0048b 194 }
54a0048b 195
1b1a35ee
XL
196 /// Declare a global with an intention to define it.
197 ///
198 /// Use this function when you intend to define a global. This function will
199 /// return `None` if the name already has a definition associated with it. In that
200 /// case an error should be reported to the user, because it usually happens due
201 /// to user’s fault (e.g., misuse of `#[no_mangle]` or `#[export_name]` attributes).
202 pub fn define_global(&self, name: &str, ty: &'ll Type) -> Option<&'ll Value> {
a1dfa0c6
XL
203 if self.get_defined_value(name).is_some() {
204 None
205 } else {
206 Some(self.declare_global(name, ty))
207 }
b7449926 208 }
b7449926 209
1b1a35ee
XL
210 /// Declare a private global
211 ///
212 /// Use this function when you intend to define a global without a name.
213 pub fn define_private_global(&self, ty: &'ll Type) -> &'ll Value {
dfeec247 214 unsafe { llvm::LLVMRustInsertPrivateGlobal(self.llmod, ty) }
54a0048b 215 }
54a0048b 216
1b1a35ee
XL
217 /// Gets declared value by name.
218 pub fn get_declared_value(&self, name: &str) -> Option<&'ll Value> {
a1dfa0c6 219 debug!("get_declared_value(name={:?})", name);
ba9703b0 220 unsafe { llvm::LLVMRustGetNamedValue(self.llmod, name.as_ptr().cast(), name.len()) }
a1dfa0c6 221 }
54a0048b 222
1b1a35ee
XL
223 /// Gets defined or externally defined (AvailableExternally linkage) value by
224 /// name.
225 pub fn get_defined_value(&self, name: &str) -> Option<&'ll Value> {
dfeec247
XL
226 self.get_declared_value(name).and_then(|val| {
227 let declaration = unsafe { llvm::LLVMIsDeclaration(val) != 0 };
228 if !declaration { Some(val) } else { None }
a1dfa0c6
XL
229 })
230 }
54a0048b 231}