]>
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 | |
9fa01778 XL |
14 | use crate::llvm; |
15 | use crate::llvm::AttributePlace::Function; | |
16 | use crate::abi::{FnType, FnTypeExt}; | |
17 | use crate::attributes; | |
18 | use crate::context::CodegenCx; | |
19 | use crate::type_::Type; | |
20 | use crate::value::Value; | |
a1dfa0c6 | 21 | use rustc::ty::{self, PolyFnSig}; |
0bf4aa26 | 22 | use rustc::ty::layout::LayoutOf; |
8bb4bdeb | 23 | use rustc::session::config::Sanitizer; |
b7449926 | 24 | use rustc_data_structures::small_c_str::SmallCStr; |
a1dfa0c6 | 25 | use rustc_codegen_ssa::traits::*; |
54a0048b | 26 | |
54a0048b SL |
27 | /// Declare a function. |
28 | /// | |
29 | /// If there’s a value with the same name already declared, the function will | |
b7449926 XL |
30 | /// update the declaration and return existing Value instead. |
31 | fn declare_raw_fn( | |
32 | cx: &CodegenCx<'ll, '_>, | |
33 | name: &str, | |
34 | callconv: llvm::CallConv, | |
35 | ty: &'ll Type, | |
36 | ) -> &'ll Value { | |
54a0048b | 37 | debug!("declare_raw_fn(name={:?}, ty={:?})", name, ty); |
b7449926 | 38 | let namebuf = SmallCStr::new(name); |
54a0048b | 39 | let llfn = unsafe { |
b7449926 | 40 | llvm::LLVMRustGetOrInsertFunction(cx.llmod, namebuf.as_ptr(), ty) |
54a0048b SL |
41 | }; |
42 | ||
43 | llvm::SetFunctionCallConv(llfn, callconv); | |
44 | // Function addresses in Rust are never significant, allowing functions to | |
45 | // be merged. | |
46 | llvm::SetUnnamedAddr(llfn, true); | |
47 | ||
2c00a5a8 XL |
48 | if cx.tcx.sess.opts.cg.no_redzone |
49 | .unwrap_or(cx.tcx.sess.target.target.options.disable_redzone) { | |
5bcae85e | 50 | llvm::Attribute::NoRedZone.apply_llfn(Function, llfn); |
54a0048b SL |
51 | } |
52 | ||
2c00a5a8 | 53 | if let Some(ref sanitizer) = cx.tcx.sess.opts.debugging_opts.sanitizer { |
8bb4bdeb XL |
54 | match *sanitizer { |
55 | Sanitizer::Address => { | |
56 | llvm::Attribute::SanitizeAddress.apply_llfn(Function, llfn); | |
57 | }, | |
58 | Sanitizer::Memory => { | |
59 | llvm::Attribute::SanitizeMemory.apply_llfn(Function, llfn); | |
60 | }, | |
61 | Sanitizer::Thread => { | |
62 | llvm::Attribute::SanitizeThread.apply_llfn(Function, llfn); | |
63 | }, | |
64 | _ => {} | |
65 | } | |
66 | } | |
67 | ||
9fa01778 | 68 | attributes::default_optimisation_attrs(cx.tcx.sess, llfn); |
0bf4aa26 | 69 | attributes::non_lazy_bind(cx.sess(), llfn); |
54a0048b SL |
70 | llfn |
71 | } | |
72 | ||
a1dfa0c6 | 73 | impl DeclareMethods<'tcx> for CodegenCx<'ll, 'tcx> { |
54a0048b | 74 | |
a1dfa0c6 XL |
75 | fn declare_global( |
76 | &self, | |
77 | name: &str, ty: &'ll Type | |
78 | ) -> &'ll Value { | |
79 | debug!("declare_global(name={:?})", name); | |
80 | let namebuf = SmallCStr::new(name); | |
81 | unsafe { | |
82 | llvm::LLVMRustGetOrInsertGlobal(self.llmod, namebuf.as_ptr(), ty) | |
83 | } | |
54a0048b SL |
84 | } |
85 | ||
a1dfa0c6 XL |
86 | fn declare_cfn( |
87 | &self, | |
88 | name: &str, | |
89 | fn_type: &'ll Type | |
90 | ) -> &'ll Value { | |
91 | declare_raw_fn(self, name, llvm::CCallConv, fn_type) | |
54a0048b SL |
92 | } |
93 | ||
a1dfa0c6 XL |
94 | fn declare_fn( |
95 | &self, | |
96 | name: &str, | |
97 | sig: PolyFnSig<'tcx>, | |
98 | ) -> &'ll Value { | |
99 | debug!("declare_rust_fn(name={:?}, sig={:?})", name, sig); | |
100 | let sig = self.tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig); | |
101 | debug!("declare_rust_fn (after region erasure) sig={:?}", sig); | |
54a0048b | 102 | |
a1dfa0c6 XL |
103 | let fty = FnType::new(self, sig, &[]); |
104 | let llfn = declare_raw_fn(self, name, fty.llvm_cconv(), fty.llvm_type(self)); | |
54a0048b | 105 | |
a1dfa0c6 XL |
106 | if self.layout_of(sig.output()).abi.is_uninhabited() { |
107 | llvm::Attribute::NoReturn.apply_llfn(Function, llfn); | |
108 | } | |
54a0048b | 109 | |
a1dfa0c6 XL |
110 | fty.apply_attrs_llfn(llfn); |
111 | ||
112 | llfn | |
54a0048b | 113 | } |
54a0048b | 114 | |
a1dfa0c6 XL |
115 | fn define_global( |
116 | &self, | |
117 | name: &str, | |
118 | ty: &'ll Type | |
119 | ) -> Option<&'ll Value> { | |
120 | if self.get_defined_value(name).is_some() { | |
121 | None | |
122 | } else { | |
123 | Some(self.declare_global(name, ty)) | |
124 | } | |
b7449926 | 125 | } |
b7449926 | 126 | |
a1dfa0c6 XL |
127 | fn define_private_global(&self, ty: &'ll Type) -> &'ll Value { |
128 | unsafe { | |
129 | llvm::LLVMRustInsertPrivateGlobal(self.llmod, ty) | |
130 | } | |
54a0048b | 131 | } |
54a0048b | 132 | |
a1dfa0c6 XL |
133 | fn define_fn( |
134 | &self, | |
135 | name: &str, | |
136 | fn_sig: PolyFnSig<'tcx>, | |
137 | ) -> &'ll Value { | |
138 | if self.get_defined_value(name).is_some() { | |
139 | self.sess().fatal(&format!("symbol `{}` already defined", name)) | |
140 | } else { | |
141 | self.declare_fn(name, fn_sig) | |
142 | } | |
143 | } | |
5bcae85e | 144 | |
a1dfa0c6 XL |
145 | fn define_internal_fn( |
146 | &self, | |
147 | name: &str, | |
148 | fn_sig: PolyFnSig<'tcx>, | |
149 | ) -> &'ll Value { | |
150 | let llfn = self.define_fn(name, fn_sig); | |
151 | unsafe { llvm::LLVMRustSetLinkage(llfn, llvm::Linkage::InternalLinkage) }; | |
152 | llfn | |
153 | } | |
54a0048b | 154 | |
a1dfa0c6 XL |
155 | fn get_declared_value(&self, name: &str) -> Option<&'ll Value> { |
156 | debug!("get_declared_value(name={:?})", name); | |
157 | let namebuf = SmallCStr::new(name); | |
158 | unsafe { llvm::LLVMRustGetNamedValue(self.llmod, namebuf.as_ptr()) } | |
159 | } | |
54a0048b | 160 | |
a1dfa0c6 XL |
161 | fn get_defined_value(&self, name: &str) -> Option<&'ll Value> { |
162 | self.get_declared_value(name).and_then(|val|{ | |
163 | let declaration = unsafe { | |
164 | llvm::LLVMIsDeclaration(val) != 0 | |
165 | }; | |
166 | if !declaration { | |
167 | Some(val) | |
168 | } else { | |
169 | None | |
170 | } | |
171 | }) | |
172 | } | |
54a0048b | 173 | } |