]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_codegen_llvm/src/declare.rs
New upstream version 1.65.0+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;
ba9703b0 22use rustc_middle::ty::Ty;
064997fb 23use rustc_symbol_mangling::typeid::typeid_for_fnabi;
5e7ed085 24use 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 30fn 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 58impl<'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}