]>
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 | //! | |
12 | //! Prefer using functions and methods from this module rather than calling LLVM functions | |
13 | //! directly. These functions do some additional work to ensure we do the right thing given | |
14 | //! the preconceptions of trans. | |
15 | //! | |
16 | //! Some useful guidelines: | |
17 | //! | |
18 | //! * Use declare_* family of methods if you are declaring, but are not interested in defining the | |
19 | //! ValueRef they return. | |
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; | |
32 | use util::ppaux::Repr; | |
33 | ||
34 | use std::ffi::CString; | |
35 | use libc::c_uint; | |
36 | ||
37 | ||
38 | /// Declare a global value. | |
39 | /// | |
40 | /// If there’s a value with the same name already declared, the function will return its ValueRef | |
41 | /// instead. | |
42 | pub fn declare_global(ccx: &CrateContext, name: &str, ty: Type) -> llvm::ValueRef { | |
43 | debug!("declare_global(name={:?})", name); | |
44 | let namebuf = CString::new(name).unwrap_or_else(|_|{ | |
45 | ccx.sess().bug(&format!("name {:?} contains an interior null byte", name)) | |
46 | }); | |
47 | unsafe { | |
48 | llvm::LLVMGetOrInsertGlobal(ccx.llmod(), namebuf.as_ptr(), ty.to_ref()) | |
49 | } | |
50 | } | |
51 | ||
52 | ||
53 | /// Declare a function. | |
54 | /// | |
55 | /// For rust functions use `declare_rust_fn` instead. | |
56 | /// | |
57 | /// If there’s a value with the same name already declared, the function will update the | |
58 | /// declaration and return existing ValueRef instead. | |
59 | pub fn declare_fn(ccx: &CrateContext, name: &str, callconv: llvm::CallConv, ty: Type, | |
60 | output: ty::FnOutput) -> ValueRef { | |
61 | debug!("declare_fn(name={:?})", name); | |
62 | let namebuf = CString::new(name).unwrap_or_else(|_|{ | |
63 | ccx.sess().bug(&format!("name {:?} contains an interior null byte", name)) | |
64 | }); | |
65 | let llfn = unsafe { | |
66 | llvm::LLVMGetOrInsertFunction(ccx.llmod(), namebuf.as_ptr(), ty.to_ref()) | |
67 | }; | |
68 | ||
69 | llvm::SetFunctionCallConv(llfn, callconv); | |
70 | // Function addresses in Rust are never significant, allowing functions to be merged. | |
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 | /// | |
91 | /// Only use this for foreign function ABIs and glue. For Rust functions use `declare_rust_fn` | |
92 | /// instead. | |
93 | /// | |
94 | /// If there’s a value with the same name already declared, the function will update the | |
95 | /// declaration and return existing ValueRef instead. | |
96 | pub fn declare_cfn(ccx: &CrateContext, name: &str, fn_type: Type, output: ty::Ty) -> ValueRef { | |
97 | declare_fn(ccx, name, llvm::CCallConv, fn_type, ty::FnConverging(output)) | |
98 | } | |
99 | ||
100 | ||
101 | /// Declare a Rust function. | |
102 | /// | |
103 | /// If there’s a value with the same name already declared, the function will update the | |
104 | /// declaration and return existing ValueRef instead. | |
105 | pub fn declare_rust_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, name: &str, | |
106 | fn_type: ty::Ty<'tcx>) -> ValueRef { | |
107 | debug!("declare_rust_fn(name={:?}, fn_type={})", name, fn_type.repr(ccx.tcx())); | |
108 | let fn_type = monomorphize::normalize_associated_type(ccx.tcx(), &fn_type); | |
109 | debug!("declare_rust_fn (after normalised associated types) fn_type={}", | |
110 | fn_type.repr(ccx.tcx())); | |
111 | ||
112 | let function_type; // placeholder so that the memory ownership works out ok | |
113 | let (sig, abi, env) = match fn_type.sty { | |
114 | ty::ty_bare_fn(_, ref f) => { | |
115 | (&f.sig, f.abi, None) | |
116 | } | |
117 | ty::ty_closure(closure_did, substs) => { | |
118 | let typer = common::NormalizingClosureTyper::new(ccx.tcx()); | |
119 | function_type = typer.closure_type(closure_did, substs); | |
120 | let self_type = base::self_type_for_closure(ccx, closure_did, fn_type); | |
121 | let llenvironment_type = type_of::type_of_explicit_arg(ccx, self_type); | |
122 | debug!("declare_rust_fn function_type={} self_type={}", | |
123 | function_type.repr(ccx.tcx()), self_type.repr(ccx.tcx())); | |
124 | (&function_type.sig, abi::RustCall, Some(llenvironment_type)) | |
125 | } | |
126 | _ => ccx.sess().bug("expected closure or fn") | |
127 | }; | |
128 | ||
129 | let sig = ty::Binder(ty::erase_late_bound_regions(ccx.tcx(), sig)); | |
130 | debug!("declare_rust_fn (after region erasure) sig={}", sig.repr(ccx.tcx())); | |
131 | let llfty = type_of::type_of_rust_fn(ccx, env, &sig, abi); | |
132 | debug!("declare_rust_fn llfty={}", ccx.tn().type_to_string(llfty)); | |
133 | ||
134 | // it is ok to directly access sig.0.output because we erased all late-bound-regions above | |
135 | let llfn = declare_fn(ccx, name, llvm::CCallConv, llfty, sig.0.output); | |
136 | attributes::from_fn_type(ccx, fn_type).apply_llfn(llfn); | |
137 | llfn | |
138 | } | |
139 | ||
140 | ||
141 | /// Declare a Rust function with internal linkage. | |
142 | /// | |
143 | /// If there’s a value with the same name already declared, the function will update the | |
144 | /// declaration and return existing ValueRef instead. | |
145 | pub fn declare_internal_rust_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, name: &str, | |
146 | fn_type: ty::Ty<'tcx>) -> ValueRef { | |
147 | let llfn = declare_rust_fn(ccx, name, fn_type); | |
148 | llvm::SetLinkage(llfn, llvm::InternalLinkage); | |
149 | llfn | |
150 | } | |
151 | ||
152 | ||
153 | /// Declare a global with an intention to define it. | |
154 | /// | |
155 | /// Use this function when you intend to define a global. This function will return None if the | |
156 | /// name already has a definition associated with it. In that case an error should be reported to | |
157 | /// the user, because it usually happens due to user’s fault (e.g. misuse of #[no_mangle] or | |
158 | /// #[export_name] attributes). | |
159 | pub fn define_global(ccx: &CrateContext, name: &str, ty: Type) -> Option<ValueRef> { | |
160 | if get_defined_value(ccx, name).is_some() { | |
161 | None | |
162 | } else { | |
163 | Some(declare_global(ccx, name, ty)) | |
164 | } | |
165 | } | |
166 | ||
167 | ||
168 | /// Declare a function with an intention to define it. | |
169 | /// | |
170 | /// For rust functions use `define_rust_fn` instead. | |
171 | /// | |
172 | /// Use this function when you intend to define a function. This function will return None if the | |
173 | /// name already has a definition associated with it. In that case an error should be reported to | |
174 | /// the user, because it usually happens due to user’s fault (e.g. misuse of #[no_mangle] or | |
175 | /// #[export_name] attributes). | |
176 | pub fn define_fn(ccx: &CrateContext, name: &str, callconv: llvm::CallConv, fn_type: Type, | |
177 | output: ty::FnOutput) -> Option<ValueRef> { | |
178 | if get_defined_value(ccx, name).is_some() { | |
179 | None | |
180 | } else { | |
181 | Some(declare_fn(ccx, name, callconv, fn_type, output)) | |
182 | } | |
183 | } | |
184 | ||
185 | ||
186 | /// Declare a C ABI function with an intention to define it. | |
187 | /// | |
188 | /// Use this function when you intend to define a function. This function will return None if the | |
189 | /// name already has a definition associated with it. In that case an error should be reported to | |
190 | /// the user, because it usually happens due to user’s fault (e.g. misuse of #[no_mangle] or | |
191 | /// #[export_name] attributes). | |
192 | /// | |
193 | /// Only use this for foreign function ABIs and glue. For Rust functions use `declare_rust_fn` | |
194 | /// instead. | |
195 | pub fn define_cfn(ccx: &CrateContext, name: &str, fn_type: Type, | |
196 | output: ty::Ty) -> Option<ValueRef> { | |
197 | if get_defined_value(ccx, name).is_some() { | |
198 | None | |
199 | } else { | |
200 | Some(declare_cfn(ccx, name, fn_type, output)) | |
201 | } | |
202 | } | |
203 | ||
204 | ||
205 | /// Declare a Rust function with an intention to define it. | |
206 | /// | |
207 | /// Use this function when you intend to define a function. This function will return None if the | |
208 | /// name already has a definition associated with it. In that case an error should be reported to | |
209 | /// the user, because it usually happens due to user’s fault (e.g. misuse of #[no_mangle] or | |
210 | /// #[export_name] attributes). | |
211 | pub fn define_rust_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, name: &str, | |
212 | fn_type: ty::Ty<'tcx>) -> Option<ValueRef> { | |
213 | if get_defined_value(ccx, name).is_some() { | |
214 | None | |
215 | } else { | |
216 | Some(declare_rust_fn(ccx, name, fn_type)) | |
217 | } | |
218 | } | |
219 | ||
220 | ||
221 | /// Declare a Rust function with an intention to define it. | |
222 | /// | |
223 | /// Use this function when you intend to define a function. This function will return None if the | |
224 | /// name already has a definition associated with it. In that case an error should be reported to | |
225 | /// the user, because it usually happens due to user’s fault (e.g. misuse of #[no_mangle] or | |
226 | /// #[export_name] attributes). | |
227 | pub fn define_internal_rust_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, name: &str, | |
228 | fn_type: ty::Ty<'tcx>) -> Option<ValueRef> { | |
229 | if get_defined_value(ccx, name).is_some() { | |
230 | None | |
231 | } else { | |
232 | Some(declare_internal_rust_fn(ccx, name, fn_type)) | |
233 | } | |
234 | } | |
235 | ||
236 | ||
237 | /// Get defined or externally defined (AvailableExternally linkage) value by name. | |
238 | fn get_defined_value(ccx: &CrateContext, name: &str) -> Option<ValueRef> { | |
239 | debug!("get_defined_value(name={:?})", name); | |
240 | let namebuf = CString::new(name).unwrap_or_else(|_|{ | |
241 | ccx.sess().bug(&format!("name {:?} contains an interior null byte", name)) | |
242 | }); | |
243 | let val = unsafe { llvm::LLVMGetNamedValue(ccx.llmod(), namebuf.as_ptr()) }; | |
244 | if val.is_null() { | |
245 | debug!("get_defined_value: {:?} value is null", name); | |
246 | None | |
247 | } else { | |
248 | let (declaration, aext_link) = unsafe { | |
249 | let linkage = llvm::LLVMGetLinkage(val); | |
250 | (llvm::LLVMIsDeclaration(val) != 0, | |
251 | linkage == llvm::AvailableExternallyLinkage as c_uint) | |
252 | }; | |
253 | debug!("get_defined_value: found {:?} value (declaration: {}, aext_link: {})", name, | |
254 | declaration, aext_link); | |
255 | if !declaration || aext_link { | |
256 | Some(val) | |
257 | } else { | |
258 | None | |
259 | } | |
260 | } | |
261 | } |