]>
Commit | Line | Data |
---|---|---|
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 | 14 | use crate::abi::{FnAbi, FnAbiLlvmExt}; |
9fa01778 XL |
15 | use crate::attributes; |
16 | use crate::context::CodegenCx; | |
dfeec247 XL |
17 | use crate::llvm; |
18 | use crate::llvm::AttributePlace::Function; | |
9fa01778 XL |
19 | use crate::type_::Type; |
20 | use crate::value::Value; | |
064997fb | 21 | use rustc_codegen_ssa::traits::TypeMembershipMethods; |
49aad941 FG |
22 | use rustc_middle::ty::{Instance, Ty}; |
23 | use rustc_symbol_mangling::typeid::{ | |
24 | kcfi_typeid_for_fnabi, kcfi_typeid_for_instance, typeid_for_fnabi, typeid_for_instance, | |
25 | TypeIdOptions, | |
26 | }; | |
5e7ed085 | 27 | use 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 | 33 | fn 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 | 63 | impl<'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 | } |