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