1 //! Declare various LLVM values.
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
5 //! the right thing given the preconceptions of codegen.
7 //! Some useful guidelines:
9 //! * Use declare_* family of methods if you are declaring, but are not
10 //! interested in defining the Value they return.
11 //! * Use define_* family of methods when you might be defining the Value.
12 //! * When in doubt, define.
14 use crate::abi
::{FnAbi, FnAbiLlvmExt}
;
15 use crate::attributes
;
16 use crate::context
::CodegenCx
;
18 use crate::llvm
::AttributePlace
::Function
;
19 use crate::type_
::Type
;
20 use crate::value
::Value
;
21 use rustc_codegen_ssa
::traits
::*;
22 use rustc_middle
::ty
::Ty
;
25 /// Declare a function.
27 /// If there’s a value with the same name already declared, the function will
28 /// update the declaration and return existing Value instead.
30 cx
: &CodegenCx
<'ll
, '_
>,
32 callconv
: llvm
::CallConv
,
35 debug
!("declare_raw_fn(name={:?}, ty={:?})", name
, ty
);
37 llvm
::LLVMRustGetOrInsertFunction(cx
.llmod
, name
.as_ptr().cast(), name
.len(), ty
)
40 llvm
::SetFunctionCallConv(llfn
, callconv
);
41 // Function addresses in Rust are never significant, allowing functions to
43 llvm
::SetUnnamedAddress(llfn
, llvm
::UnnamedAddr
::Global
);
45 if cx
.tcx
.sess
.opts
.cg
.no_redzone
.unwrap_or(cx
.tcx
.sess
.target
.disable_redzone
) {
46 llvm
::Attribute
::NoRedZone
.apply_llfn(Function
, llfn
);
49 attributes
::default_optimisation_attrs(cx
.tcx
.sess
, llfn
);
50 attributes
::non_lazy_bind(cx
.sess(), llfn
);
54 impl CodegenCx
<'ll
, 'tcx
> {
55 /// Declare a global value.
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
{
60 debug
!("declare_global(name={:?})", name
);
61 unsafe { llvm::LLVMRustGetOrInsertGlobal(self.llmod, name.as_ptr().cast(), name.len(), ty) }
64 /// Declare a C ABI function.
66 /// Only use this for foreign function ABIs and glue. For Rust functions use
67 /// `declare_fn` instead.
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
{
72 declare_raw_fn(self, name
, llvm
::CCallConv
, fn_type
)
75 /// Declare a Rust function.
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
{
80 debug
!("declare_rust_fn(name={:?}, fn_abi={:?})", name
, fn_abi
);
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
);
87 /// Declare a global with an intention to define it.
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
> {
94 if self.get_defined_value(name
).is_some() {
97 Some(self.declare_global(name
, ty
))
101 /// Declare a private global
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
{
105 unsafe { llvm::LLVMRustInsertPrivateGlobal(self.llmod, ty) }
108 /// Gets declared value by name.
109 pub fn get_declared_value(&self, name
: &str) -> Option
<&'ll Value
> {
110 debug
!("get_declared_value(name={:?})", name
);
111 unsafe { llvm::LLVMRustGetNamedValue(self.llmod, name.as_ptr().cast(), name.len()) }
114 /// Gets defined or externally defined (AvailableExternally linkage) value by
116 pub fn get_defined_value(&self, name
: &str) -> Option
<&'ll Value
> {
117 self.get_declared_value(name
).and_then(|val
| {
118 let declaration
= unsafe { llvm::LLVMIsDeclaration(val) != 0 }
;
119 if !declaration { Some(val) }
else { None }