]>
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; | |
dfeec247 | 21 | use log::debug; |
dfeec247 | 22 | use rustc::ty::Ty; |
a1dfa0c6 | 23 | use rustc_codegen_ssa::traits::*; |
dfeec247 | 24 | use rustc_data_structures::small_c_str::SmallCStr; |
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 XL |
29 | /// update the declaration and return existing Value instead. |
30 | fn declare_raw_fn( | |
31 | cx: &CodegenCx<'ll, '_>, | |
32 | name: &str, | |
33 | callconv: llvm::CallConv, | |
34 | ty: &'ll Type, | |
35 | ) -> &'ll Value { | |
54a0048b | 36 | debug!("declare_raw_fn(name={:?}, ty={:?})", name, ty); |
b7449926 | 37 | let namebuf = SmallCStr::new(name); |
dfeec247 | 38 | let llfn = unsafe { llvm::LLVMRustGetOrInsertFunction(cx.llmod, namebuf.as_ptr(), ty) }; |
54a0048b SL |
39 | |
40 | llvm::SetFunctionCallConv(llfn, callconv); | |
41 | // Function addresses in Rust are never significant, allowing functions to | |
42 | // be merged. | |
43 | llvm::SetUnnamedAddr(llfn, true); | |
44 | ||
dfeec247 | 45 | if cx.tcx.sess.opts.cg.no_redzone.unwrap_or(cx.tcx.sess.target.target.options.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 | ||
a1dfa0c6 | 54 | impl DeclareMethods<'tcx> for CodegenCx<'ll, 'tcx> { |
dfeec247 | 55 | fn declare_global(&self, name: &str, ty: &'ll Type) -> &'ll Value { |
a1dfa0c6 | 56 | debug!("declare_global(name={:?})", name); |
dfeec247 | 57 | unsafe { llvm::LLVMRustGetOrInsertGlobal(self.llmod, name.as_ptr().cast(), name.len(), ty) } |
54a0048b SL |
58 | } |
59 | ||
dfeec247 | 60 | fn declare_cfn(&self, name: &str, fn_type: &'ll Type) -> &'ll Value { |
a1dfa0c6 | 61 | declare_raw_fn(self, name, llvm::CCallConv, fn_type) |
54a0048b SL |
62 | } |
63 | ||
dfeec247 | 64 | fn declare_fn(&self, name: &str, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> &'ll Value { |
60c5eb7d | 65 | debug!("declare_rust_fn(name={:?}, fn_abi={:?})", name, fn_abi); |
a1dfa0c6 | 66 | |
60c5eb7d XL |
67 | let llfn = declare_raw_fn(self, name, fn_abi.llvm_cconv(), fn_abi.llvm_type(self)); |
68 | fn_abi.apply_attrs_llfn(self, llfn); | |
a1dfa0c6 | 69 | llfn |
54a0048b | 70 | } |
54a0048b | 71 | |
dfeec247 | 72 | fn define_global(&self, name: &str, ty: &'ll Type) -> Option<&'ll Value> { |
a1dfa0c6 XL |
73 | if self.get_defined_value(name).is_some() { |
74 | None | |
75 | } else { | |
76 | Some(self.declare_global(name, ty)) | |
77 | } | |
b7449926 | 78 | } |
b7449926 | 79 | |
a1dfa0c6 | 80 | fn define_private_global(&self, ty: &'ll Type) -> &'ll Value { |
dfeec247 | 81 | unsafe { llvm::LLVMRustInsertPrivateGlobal(self.llmod, ty) } |
54a0048b | 82 | } |
54a0048b | 83 | |
a1dfa0c6 XL |
84 | fn get_declared_value(&self, name: &str) -> Option<&'ll Value> { |
85 | debug!("get_declared_value(name={:?})", name); | |
86 | let namebuf = SmallCStr::new(name); | |
87 | unsafe { llvm::LLVMRustGetNamedValue(self.llmod, namebuf.as_ptr()) } | |
88 | } | |
54a0048b | 89 | |
a1dfa0c6 | 90 | fn get_defined_value(&self, name: &str) -> Option<&'ll Value> { |
dfeec247 XL |
91 | self.get_declared_value(name).and_then(|val| { |
92 | let declaration = unsafe { llvm::LLVMIsDeclaration(val) != 0 }; | |
93 | if !declaration { Some(val) } else { None } | |
a1dfa0c6 XL |
94 | }) |
95 | } | |
54a0048b | 96 | } |