]>
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; |
ba9703b0 | 22 | use rustc_middle::ty::Ty; |
064997fb | 23 | use rustc_symbol_mangling::typeid::typeid_for_fnabi; |
5e7ed085 | 24 | use smallvec::SmallVec; |
54a0048b | 25 | |
54a0048b SL |
26 | /// Declare a function. |
27 | /// | |
28 | /// If there’s a value with the same name already declared, the function will | |
b7449926 | 29 | /// update the declaration and return existing Value instead. |
a2a8927a | 30 | fn declare_raw_fn<'ll>( |
b7449926 XL |
31 | cx: &CodegenCx<'ll, '_>, |
32 | name: &str, | |
33 | callconv: llvm::CallConv, | |
6a06907d | 34 | unnamed: llvm::UnnamedAddr, |
b7449926 XL |
35 | ty: &'ll Type, |
36 | ) -> &'ll Value { | |
54a0048b | 37 | debug!("declare_raw_fn(name={:?}, ty={:?})", name, ty); |
ba9703b0 XL |
38 | let llfn = unsafe { |
39 | llvm::LLVMRustGetOrInsertFunction(cx.llmod, name.as_ptr().cast(), name.len(), ty) | |
40 | }; | |
54a0048b SL |
41 | |
42 | llvm::SetFunctionCallConv(llfn, callconv); | |
6a06907d | 43 | llvm::SetUnnamedAddress(llfn, unnamed); |
54a0048b | 44 | |
5e7ed085 FG |
45 | let mut attrs = SmallVec::<[_; 4]>::new(); |
46 | ||
29967ef6 | 47 | if cx.tcx.sess.opts.cg.no_redzone.unwrap_or(cx.tcx.sess.target.disable_redzone) { |
5e7ed085 | 48 | attrs.push(llvm::AttributeKind::NoRedZone.create_attr(cx.llcx)); |
54a0048b SL |
49 | } |
50 | ||
5e7ed085 FG |
51 | attrs.extend(attributes::non_lazy_bind_attr(cx)); |
52 | ||
53 | attributes::apply_to_llfn(llfn, Function, &attrs); | |
5099ac24 | 54 | |
54a0048b SL |
55 | llfn |
56 | } | |
57 | ||
a2a8927a | 58 | impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { |
1b1a35ee XL |
59 | /// Declare a global value. |
60 | /// | |
61 | /// If there’s a value with the same name already declared, the function will | |
62 | /// return its Value instead. | |
63 | pub fn declare_global(&self, name: &str, ty: &'ll Type) -> &'ll Value { | |
a1dfa0c6 | 64 | debug!("declare_global(name={:?})", name); |
dfeec247 | 65 | unsafe { llvm::LLVMRustGetOrInsertGlobal(self.llmod, name.as_ptr().cast(), name.len(), ty) } |
54a0048b SL |
66 | } |
67 | ||
1b1a35ee XL |
68 | /// Declare a C ABI function. |
69 | /// | |
70 | /// Only use this for foreign function ABIs and glue. For Rust functions use | |
71 | /// `declare_fn` instead. | |
72 | /// | |
73 | /// If there’s a value with the same name already declared, the function will | |
74 | /// update the declaration and return existing Value instead. | |
6a06907d XL |
75 | pub fn declare_cfn( |
76 | &self, | |
77 | name: &str, | |
78 | unnamed: llvm::UnnamedAddr, | |
79 | fn_type: &'ll Type, | |
80 | ) -> &'ll Value { | |
81 | declare_raw_fn(self, name, llvm::CCallConv, unnamed, fn_type) | |
54a0048b SL |
82 | } |
83 | ||
1b1a35ee XL |
84 | /// Declare a Rust function. |
85 | /// | |
86 | /// If there’s a value with the same name already declared, the function will | |
87 | /// update the declaration and return existing Value instead. | |
88 | pub fn declare_fn(&self, name: &str, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> &'ll Value { | |
60c5eb7d | 89 | debug!("declare_rust_fn(name={:?}, fn_abi={:?})", name, fn_abi); |
a1dfa0c6 | 90 | |
6a06907d XL |
91 | // Function addresses in Rust are never significant, allowing functions to |
92 | // be merged. | |
93 | let llfn = declare_raw_fn( | |
94 | self, | |
95 | name, | |
96 | fn_abi.llvm_cconv(), | |
97 | llvm::UnnamedAddr::Global, | |
98 | fn_abi.llvm_type(self), | |
99 | ); | |
60c5eb7d | 100 | fn_abi.apply_attrs_llfn(self, llfn); |
064997fb FG |
101 | |
102 | if self.tcx.sess.is_sanitizer_cfi_enabled() { | |
103 | let typeid = typeid_for_fnabi(self.tcx, fn_abi); | |
104 | self.set_type_metadata(llfn, typeid); | |
105 | } | |
106 | ||
a1dfa0c6 | 107 | llfn |
54a0048b | 108 | } |
54a0048b | 109 | |
1b1a35ee XL |
110 | /// Declare a global with an intention to define it. |
111 | /// | |
112 | /// Use this function when you intend to define a global. This function will | |
113 | /// return `None` if the name already has a definition associated with it. In that | |
114 | /// case an error should be reported to the user, because it usually happens due | |
115 | /// to user’s fault (e.g., misuse of `#[no_mangle]` or `#[export_name]` attributes). | |
116 | pub fn define_global(&self, name: &str, ty: &'ll Type) -> Option<&'ll Value> { | |
a1dfa0c6 XL |
117 | if self.get_defined_value(name).is_some() { |
118 | None | |
119 | } else { | |
120 | Some(self.declare_global(name, ty)) | |
121 | } | |
b7449926 | 122 | } |
b7449926 | 123 | |
1b1a35ee XL |
124 | /// Declare a private global |
125 | /// | |
126 | /// Use this function when you intend to define a global without a name. | |
127 | pub fn define_private_global(&self, ty: &'ll Type) -> &'ll Value { | |
dfeec247 | 128 | unsafe { llvm::LLVMRustInsertPrivateGlobal(self.llmod, ty) } |
54a0048b | 129 | } |
54a0048b | 130 | |
1b1a35ee XL |
131 | /// Gets declared value by name. |
132 | pub fn get_declared_value(&self, name: &str) -> Option<&'ll Value> { | |
a1dfa0c6 | 133 | debug!("get_declared_value(name={:?})", name); |
ba9703b0 | 134 | unsafe { llvm::LLVMRustGetNamedValue(self.llmod, name.as_ptr().cast(), name.len()) } |
a1dfa0c6 | 135 | } |
54a0048b | 136 | |
1b1a35ee XL |
137 | /// Gets defined or externally defined (AvailableExternally linkage) value by |
138 | /// name. | |
139 | pub fn get_defined_value(&self, name: &str) -> Option<&'ll Value> { | |
dfeec247 XL |
140 | self.get_declared_value(name).and_then(|val| { |
141 | let declaration = unsafe { llvm::LLVMIsDeclaration(val) != 0 }; | |
142 | if !declaration { Some(val) } else { None } | |
a1dfa0c6 XL |
143 | }) |
144 | } | |
54a0048b | 145 | } |