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