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.
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.
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.
16 //! Some useful guidelines:
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}
;
25 use trans
::attributes
;
28 use trans
::context
::CrateContext
;
29 use trans
::monomorphize
;
30 use trans
::type_
::Type
;
32 use util
::ppaux
::Repr
;
34 use std
::ffi
::CString
;
38 /// Declare a global value.
40 /// If there’s a value with the same name already declared, the function will return its ValueRef
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
))
48 llvm
::LLVMGetOrInsertGlobal(ccx
.llmod(), namebuf
.as_ptr(), ty
.to_ref())
53 /// Declare a function.
55 /// For rust functions use `declare_rust_fn` instead.
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
))
66 llvm
::LLVMGetOrInsertFunction(ccx
.llmod(), namebuf
.as_ptr(), ty
.to_ref())
69 llvm
::SetFunctionCallConv(llfn
, callconv
);
70 // Function addresses in Rust are never significant, allowing functions to be merged.
71 llvm
::SetUnnamedAddr(llfn
, true);
73 if output
== ty
::FnDiverging
{
74 llvm
::SetFunctionAttribute(llfn
, llvm
::Attribute
::NoReturn
);
77 if ccx
.tcx().sess
.opts
.cg
.no_redzone
78 .unwrap_or(ccx
.tcx().sess
.target
.target
.options
.disable_redzone
) {
79 llvm
::SetFunctionAttribute(llfn
, llvm
::Attribute
::NoRedZone
)
82 if ccx
.is_split_stack_supported() && !ccx
.sess().opts
.cg
.no_stack_check
{
83 attributes
::split_stack(llfn
, true);
89 /// Declare a C ABI function.
91 /// Only use this for foreign function ABIs and glue. For Rust functions use `declare_rust_fn`
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
))
101 /// Declare a Rust function.
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()));
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
)
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
))
126 _
=> ccx
.sess().bug("expected closure or fn")
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
));
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
);
141 /// Declare a Rust function with internal linkage.
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
);
153 /// Declare a global with an intention to define it.
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() {
163 Some(declare_global(ccx
, name
, ty
))
168 /// Declare a function with an intention to define it.
170 /// For rust functions use `define_rust_fn` instead.
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() {
181 Some(declare_fn(ccx
, name
, callconv
, fn_type
, output
))
186 /// Declare a C ABI function with an intention to define it.
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).
193 /// Only use this for foreign function ABIs and glue. For Rust functions use `declare_rust_fn`
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() {
200 Some(declare_cfn(ccx
, name
, fn_type
, output
))
205 /// Declare a Rust function with an intention to define it.
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() {
216 Some(declare_rust_fn(ccx
, name
, fn_type
))
221 /// Declare a Rust function with an intention to define it.
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() {
232 Some(declare_internal_rust_fn(ccx
, name
, fn_type
))
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
))
243 let val
= unsafe { llvm::LLVMGetNamedValue(ccx.llmod(), namebuf.as_ptr()) }
;
245 debug
!("get_defined_value: {:?} value is null", name
);
248 let (declaration
, aext_link
) = unsafe {
249 let linkage
= llvm
::LLVMGetLinkage(val
);
250 (llvm
::LLVMIsDeclaration(val
) != 0,
251 linkage
== llvm
::AvailableExternallyLinkage
as c_uint
)
253 debug
!("get_defined_value: found {:?} value (declaration: {}, aext_link: {})", name
,
254 declaration
, aext_link
);
255 if !declaration
|| aext_link
{