]>
Commit | Line | Data |
---|---|---|
9346a6ac AL |
1 | // Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT |
2 | // file at the top-level directory of this distribution and at | |
3 | // http://rust-lang.org/COPYRIGHT. | |
4 | // | |
5 | // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | |
6 | // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | |
7 | // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | |
8 | // option. This file may not be copied, modified, or distributed | |
9 | // except according to those terms. | |
10 | //! Declare various LLVM values. | |
11 | //! | |
62682a34 SL |
12 | //! Prefer using functions and methods from this module rather than calling LLVM |
13 | //! functions directly. These functions do some additional work to ensure we do | |
14 | //! the right thing given the preconceptions of trans. | |
9346a6ac AL |
15 | //! |
16 | //! Some useful guidelines: | |
17 | //! | |
62682a34 SL |
18 | //! * Use declare_* family of methods if you are declaring, but are not |
19 | //! interested in defining the ValueRef they return. | |
9346a6ac AL |
20 | //! * Use define_* family of methods when you might be defining the ValueRef. |
21 | //! * When in doubt, define. | |
22 | use llvm::{self, ValueRef}; | |
23 | use middle::ty::{self, ClosureTyper}; | |
24 | use syntax::abi; | |
25 | use trans::attributes; | |
26 | use trans::base; | |
27 | use trans::common; | |
28 | use trans::context::CrateContext; | |
29 | use trans::monomorphize; | |
30 | use trans::type_::Type; | |
31 | use trans::type_of; | |
9346a6ac AL |
32 | |
33 | use std::ffi::CString; | |
34 | use libc::c_uint; | |
35 | ||
36 | ||
37 | /// Declare a global value. | |
38 | /// | |
62682a34 SL |
39 | /// If there’s a value with the same name already declared, the function will |
40 | /// return its ValueRef instead. | |
9346a6ac AL |
41 | pub fn declare_global(ccx: &CrateContext, name: &str, ty: Type) -> llvm::ValueRef { |
42 | debug!("declare_global(name={:?})", name); | |
43 | let namebuf = CString::new(name).unwrap_or_else(|_|{ | |
44 | ccx.sess().bug(&format!("name {:?} contains an interior null byte", name)) | |
45 | }); | |
46 | unsafe { | |
47 | llvm::LLVMGetOrInsertGlobal(ccx.llmod(), namebuf.as_ptr(), ty.to_ref()) | |
48 | } | |
49 | } | |
50 | ||
51 | ||
52 | /// Declare a function. | |
53 | /// | |
54 | /// For rust functions use `declare_rust_fn` instead. | |
55 | /// | |
62682a34 SL |
56 | /// If there’s a value with the same name already declared, the function will |
57 | /// update the declaration and return existing ValueRef instead. | |
58 | pub fn declare_fn(ccx: &CrateContext, name: &str, callconv: llvm::CallConv, | |
59 | ty: Type, output: ty::FnOutput) -> ValueRef { | |
9346a6ac AL |
60 | debug!("declare_fn(name={:?})", name); |
61 | let namebuf = CString::new(name).unwrap_or_else(|_|{ | |
62 | ccx.sess().bug(&format!("name {:?} contains an interior null byte", name)) | |
63 | }); | |
64 | let llfn = unsafe { | |
65 | llvm::LLVMGetOrInsertFunction(ccx.llmod(), namebuf.as_ptr(), ty.to_ref()) | |
66 | }; | |
67 | ||
68 | llvm::SetFunctionCallConv(llfn, callconv); | |
62682a34 SL |
69 | // Function addresses in Rust are never significant, allowing functions to |
70 | // be merged. | |
9346a6ac AL |
71 | llvm::SetUnnamedAddr(llfn, true); |
72 | ||
73 | if output == ty::FnDiverging { | |
d9579d0f | 74 | llvm::SetFunctionAttribute(llfn, llvm::Attribute::NoReturn); |
9346a6ac AL |
75 | } |
76 | ||
77 | if ccx.tcx().sess.opts.cg.no_redzone | |
78 | .unwrap_or(ccx.tcx().sess.target.target.options.disable_redzone) { | |
d9579d0f | 79 | llvm::SetFunctionAttribute(llfn, llvm::Attribute::NoRedZone) |
9346a6ac AL |
80 | } |
81 | ||
82 | if ccx.is_split_stack_supported() && !ccx.sess().opts.cg.no_stack_check { | |
83 | attributes::split_stack(llfn, true); | |
84 | } | |
85 | llfn | |
86 | } | |
87 | ||
88 | ||
89 | /// Declare a C ABI function. | |
90 | /// | |
62682a34 SL |
91 | /// Only use this for foreign function ABIs and glue. For Rust functions use |
92 | /// `declare_rust_fn` instead. | |
9346a6ac | 93 | /// |
62682a34 SL |
94 | /// If there’s a value with the same name already declared, the function will |
95 | /// update the declaration and return existing ValueRef instead. | |
96 | pub fn declare_cfn(ccx: &CrateContext, name: &str, fn_type: Type, | |
97 | output: ty::Ty) -> ValueRef { | |
9346a6ac AL |
98 | declare_fn(ccx, name, llvm::CCallConv, fn_type, ty::FnConverging(output)) |
99 | } | |
100 | ||
101 | ||
102 | /// Declare a Rust function. | |
103 | /// | |
62682a34 SL |
104 | /// If there’s a value with the same name already declared, the function will |
105 | /// update the declaration and return existing ValueRef instead. | |
9346a6ac AL |
106 | pub fn declare_rust_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, name: &str, |
107 | fn_type: ty::Ty<'tcx>) -> ValueRef { | |
62682a34 SL |
108 | debug!("declare_rust_fn(name={:?}, fn_type={:?})", name, |
109 | fn_type); | |
9346a6ac | 110 | let fn_type = monomorphize::normalize_associated_type(ccx.tcx(), &fn_type); |
62682a34 SL |
111 | debug!("declare_rust_fn (after normalised associated types) fn_type={:?}", |
112 | fn_type); | |
9346a6ac AL |
113 | |
114 | let function_type; // placeholder so that the memory ownership works out ok | |
115 | let (sig, abi, env) = match fn_type.sty { | |
62682a34 | 116 | ty::TyBareFn(_, ref f) => { |
9346a6ac AL |
117 | (&f.sig, f.abi, None) |
118 | } | |
62682a34 | 119 | ty::TyClosure(closure_did, substs) => { |
9346a6ac AL |
120 | let typer = common::NormalizingClosureTyper::new(ccx.tcx()); |
121 | function_type = typer.closure_type(closure_did, substs); | |
122 | let self_type = base::self_type_for_closure(ccx, closure_did, fn_type); | |
123 | let llenvironment_type = type_of::type_of_explicit_arg(ccx, self_type); | |
62682a34 SL |
124 | debug!("declare_rust_fn function_type={:?} self_type={:?}", |
125 | function_type, self_type); | |
9346a6ac AL |
126 | (&function_type.sig, abi::RustCall, Some(llenvironment_type)) |
127 | } | |
128 | _ => ccx.sess().bug("expected closure or fn") | |
129 | }; | |
130 | ||
131 | let sig = ty::Binder(ty::erase_late_bound_regions(ccx.tcx(), sig)); | |
62682a34 | 132 | debug!("declare_rust_fn (after region erasure) sig={:?}", sig); |
9346a6ac AL |
133 | let llfty = type_of::type_of_rust_fn(ccx, env, &sig, abi); |
134 | debug!("declare_rust_fn llfty={}", ccx.tn().type_to_string(llfty)); | |
135 | ||
62682a34 SL |
136 | // it is ok to directly access sig.0.output because we erased all |
137 | // late-bound-regions above | |
9346a6ac AL |
138 | let llfn = declare_fn(ccx, name, llvm::CCallConv, llfty, sig.0.output); |
139 | attributes::from_fn_type(ccx, fn_type).apply_llfn(llfn); | |
140 | llfn | |
141 | } | |
142 | ||
143 | ||
144 | /// Declare a Rust function with internal linkage. | |
145 | /// | |
62682a34 SL |
146 | /// If there’s a value with the same name already declared, the function will |
147 | /// update the declaration and return existing ValueRef instead. | |
9346a6ac AL |
148 | pub fn declare_internal_rust_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, name: &str, |
149 | fn_type: ty::Ty<'tcx>) -> ValueRef { | |
150 | let llfn = declare_rust_fn(ccx, name, fn_type); | |
151 | llvm::SetLinkage(llfn, llvm::InternalLinkage); | |
152 | llfn | |
153 | } | |
154 | ||
155 | ||
156 | /// Declare a global with an intention to define it. | |
157 | /// | |
62682a34 SL |
158 | /// Use this function when you intend to define a global. This function will |
159 | /// return None if the name already has a definition associated with it. In that | |
160 | /// case an error should be reported to the user, because it usually happens due | |
161 | /// to user’s fault (e.g. misuse of #[no_mangle] or #[export_name] attributes). | |
9346a6ac AL |
162 | pub fn define_global(ccx: &CrateContext, name: &str, ty: Type) -> Option<ValueRef> { |
163 | if get_defined_value(ccx, name).is_some() { | |
164 | None | |
165 | } else { | |
166 | Some(declare_global(ccx, name, ty)) | |
167 | } | |
168 | } | |
169 | ||
170 | ||
171 | /// Declare a function with an intention to define it. | |
172 | /// | |
173 | /// For rust functions use `define_rust_fn` instead. | |
174 | /// | |
62682a34 SL |
175 | /// Use this function when you intend to define a function. This function will |
176 | /// return None if the name already has a definition associated with it. In that | |
177 | /// case an error should be reported to the user, because it usually happens due | |
178 | /// to user’s fault (e.g. misuse of #[no_mangle] or #[export_name] attributes). | |
9346a6ac AL |
179 | pub fn define_fn(ccx: &CrateContext, name: &str, callconv: llvm::CallConv, fn_type: Type, |
180 | output: ty::FnOutput) -> Option<ValueRef> { | |
181 | if get_defined_value(ccx, name).is_some() { | |
182 | None | |
183 | } else { | |
184 | Some(declare_fn(ccx, name, callconv, fn_type, output)) | |
185 | } | |
186 | } | |
187 | ||
188 | ||
189 | /// Declare a C ABI function with an intention to define it. | |
190 | /// | |
62682a34 SL |
191 | /// Use this function when you intend to define a function. This function will |
192 | /// return None if the name already has a definition associated with it. In that | |
193 | /// case an error should be reported to the user, because it usually happens due | |
194 | /// to user’s fault (e.g. misuse of #[no_mangle] or #[export_name] attributes). | |
9346a6ac | 195 | /// |
62682a34 SL |
196 | /// Only use this for foreign function ABIs and glue. For Rust functions use |
197 | /// `declare_rust_fn` instead. | |
9346a6ac AL |
198 | pub fn define_cfn(ccx: &CrateContext, name: &str, fn_type: Type, |
199 | output: ty::Ty) -> Option<ValueRef> { | |
200 | if get_defined_value(ccx, name).is_some() { | |
201 | None | |
202 | } else { | |
203 | Some(declare_cfn(ccx, name, fn_type, output)) | |
204 | } | |
205 | } | |
206 | ||
207 | ||
208 | /// Declare a Rust function with an intention to define it. | |
209 | /// | |
62682a34 SL |
210 | /// Use this function when you intend to define a function. This function will |
211 | /// return None if the name already has a definition associated with it. In that | |
212 | /// case an error should be reported to the user, because it usually happens due | |
213 | /// to user’s fault (e.g. misuse of #[no_mangle] or #[export_name] attributes). | |
9346a6ac AL |
214 | pub fn define_rust_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, name: &str, |
215 | fn_type: ty::Ty<'tcx>) -> Option<ValueRef> { | |
216 | if get_defined_value(ccx, name).is_some() { | |
217 | None | |
218 | } else { | |
219 | Some(declare_rust_fn(ccx, name, fn_type)) | |
220 | } | |
221 | } | |
222 | ||
223 | ||
224 | /// Declare a Rust function with an intention to define it. | |
225 | /// | |
62682a34 SL |
226 | /// Use this function when you intend to define a function. This function will |
227 | /// return None if the name already has a definition associated with it. In that | |
228 | /// case an error should be reported to the user, because it usually happens due | |
229 | /// to user’s fault (e.g. misuse of #[no_mangle] or #[export_name] attributes). | |
9346a6ac AL |
230 | pub fn define_internal_rust_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, name: &str, |
231 | fn_type: ty::Ty<'tcx>) -> Option<ValueRef> { | |
232 | if get_defined_value(ccx, name).is_some() { | |
233 | None | |
234 | } else { | |
235 | Some(declare_internal_rust_fn(ccx, name, fn_type)) | |
236 | } | |
237 | } | |
238 | ||
239 | ||
240 | /// Get defined or externally defined (AvailableExternally linkage) value by name. | |
241 | fn get_defined_value(ccx: &CrateContext, name: &str) -> Option<ValueRef> { | |
242 | debug!("get_defined_value(name={:?})", name); | |
243 | let namebuf = CString::new(name).unwrap_or_else(|_|{ | |
244 | ccx.sess().bug(&format!("name {:?} contains an interior null byte", name)) | |
245 | }); | |
246 | let val = unsafe { llvm::LLVMGetNamedValue(ccx.llmod(), namebuf.as_ptr()) }; | |
247 | if val.is_null() { | |
248 | debug!("get_defined_value: {:?} value is null", name); | |
249 | None | |
250 | } else { | |
251 | let (declaration, aext_link) = unsafe { | |
252 | let linkage = llvm::LLVMGetLinkage(val); | |
253 | (llvm::LLVMIsDeclaration(val) != 0, | |
254 | linkage == llvm::AvailableExternallyLinkage as c_uint) | |
255 | }; | |
62682a34 SL |
256 | debug!("get_defined_value: found {:?} value (declaration: {}, \ |
257 | aext_link: {})", name, declaration, aext_link); | |
9346a6ac AL |
258 | if !declaration || aext_link { |
259 | Some(val) | |
260 | } else { | |
261 | None | |
262 | } | |
263 | } | |
264 | } |