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
13 //! functions directly. These functions do some additional work to ensure we do
14 //! the right thing given the preconceptions of trans.
16 //! Some useful guidelines:
18 //! * Use declare_* family of methods if you are declaring, but are not
19 //! interested in defining the 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}
;
26 use trans
::attributes
;
28 use trans
::context
::CrateContext
;
29 use trans
::type_
::Type
;
32 use std
::ffi
::CString
;
36 /// Declare a global value.
38 /// If there’s a value with the same name already declared, the function will
39 /// return its ValueRef instead.
40 pub fn declare_global(ccx
: &CrateContext
, name
: &str, ty
: Type
) -> llvm
::ValueRef
{
41 debug
!("declare_global(name={:?})", name
);
42 let namebuf
= CString
::new(name
).unwrap_or_else(|_
|{
43 ccx
.sess().bug(&format
!("name {:?} contains an interior null byte", name
))
46 llvm
::LLVMGetOrInsertGlobal(ccx
.llmod(), namebuf
.as_ptr(), ty
.to_ref())
51 /// Declare a function.
53 /// For rust functions use `declare_rust_fn` instead.
55 /// If there’s a value with the same name already declared, the function will
56 /// update the declaration and return existing ValueRef instead.
57 pub fn declare_fn(ccx
: &CrateContext
, name
: &str, callconv
: llvm
::CallConv
,
58 ty
: Type
, output
: ty
::FnOutput
) -> ValueRef
{
59 debug
!("declare_fn(name={:?})", name
);
60 let namebuf
= CString
::new(name
).unwrap_or_else(|_
|{
61 ccx
.sess().bug(&format
!("name {:?} contains an interior null byte", name
))
64 llvm
::LLVMGetOrInsertFunction(ccx
.llmod(), namebuf
.as_ptr(), ty
.to_ref())
67 llvm
::SetFunctionCallConv(llfn
, callconv
);
68 // Function addresses in Rust are never significant, allowing functions to
70 llvm
::SetUnnamedAddr(llfn
, true);
72 if output
== ty
::FnDiverging
{
73 llvm
::SetFunctionAttribute(llfn
, llvm
::Attribute
::NoReturn
);
76 if ccx
.tcx().sess
.opts
.cg
.no_redzone
77 .unwrap_or(ccx
.tcx().sess
.target
.target
.options
.disable_redzone
) {
78 llvm
::SetFunctionAttribute(llfn
, llvm
::Attribute
::NoRedZone
)
85 /// Declare a C ABI function.
87 /// Only use this for foreign function ABIs and glue. For Rust functions use
88 /// `declare_rust_fn` instead.
90 /// If there’s a value with the same name already declared, the function will
91 /// update the declaration and return existing ValueRef instead.
92 pub fn declare_cfn(ccx
: &CrateContext
, name
: &str, fn_type
: Type
,
93 output
: ty
::Ty
) -> ValueRef
{
94 declare_fn(ccx
, name
, llvm
::CCallConv
, fn_type
, ty
::FnConverging(output
))
98 /// Declare a Rust function.
100 /// If there’s a value with the same name already declared, the function will
101 /// update the declaration and return existing ValueRef instead.
102 pub fn declare_rust_fn
<'a
, 'tcx
>(ccx
: &CrateContext
<'a
, 'tcx
>, name
: &str,
103 fn_type
: ty
::Ty
<'tcx
>) -> ValueRef
{
104 debug
!("declare_rust_fn(name={:?}, fn_type={:?})", name
,
107 let function_type
; // placeholder so that the memory ownership works out ok
108 let (sig
, abi
, env
) = match fn_type
.sty
{
109 ty
::TyBareFn(_
, ref f
) => {
110 (&f
.sig
, f
.abi
, None
)
112 ty
::TyClosure(closure_did
, ref substs
) => {
113 let infcx
= infer
::normalizing_infer_ctxt(ccx
.tcx(), &ccx
.tcx().tables
);
114 function_type
= infcx
.closure_type(closure_did
, substs
);
115 let self_type
= base
::self_type_for_closure(ccx
, closure_did
, fn_type
);
116 let llenvironment_type
= type_of
::type_of_explicit_arg(ccx
, self_type
);
117 debug
!("declare_rust_fn function_type={:?} self_type={:?}",
118 function_type
, self_type
);
119 (&function_type
.sig
, Abi
::RustCall
, Some(llenvironment_type
))
121 _
=> ccx
.sess().bug("expected closure or fn")
124 let sig
= ccx
.tcx().erase_late_bound_regions(sig
);
125 let sig
= infer
::normalize_associated_type(ccx
.tcx(), &sig
);
126 debug
!("declare_rust_fn (after region erasure) sig={:?}", sig
);
127 let llfty
= type_of
::type_of_rust_fn(ccx
, env
, &sig
, abi
);
128 debug
!("declare_rust_fn llfty={}", ccx
.tn().type_to_string(llfty
));
130 // it is ok to directly access sig.0.output because we erased all
131 // late-bound-regions above
132 let llfn
= declare_fn(ccx
, name
, llvm
::CCallConv
, llfty
, sig
.output
);
133 attributes
::from_fn_type(ccx
, fn_type
).apply_llfn(llfn
);
138 /// Declare a Rust function with internal linkage.
140 /// If there’s a value with the same name already declared, the function will
141 /// update the declaration and return existing ValueRef instead.
142 pub fn declare_internal_rust_fn
<'a
, 'tcx
>(ccx
: &CrateContext
<'a
, 'tcx
>, name
: &str,
143 fn_type
: ty
::Ty
<'tcx
>) -> ValueRef
{
144 let llfn
= declare_rust_fn(ccx
, name
, fn_type
);
145 llvm
::SetLinkage(llfn
, llvm
::InternalLinkage
);
150 /// Declare a global with an intention to define it.
152 /// Use this function when you intend to define a global. This function will
153 /// return None if the name already has a definition associated with it. In that
154 /// case an error should be reported to the user, because it usually happens due
155 /// to user’s fault (e.g. misuse of #[no_mangle] or #[export_name] attributes).
156 pub fn define_global(ccx
: &CrateContext
, name
: &str, ty
: Type
) -> Option
<ValueRef
> {
157 if get_defined_value(ccx
, name
).is_some() {
160 Some(declare_global(ccx
, name
, ty
))
165 /// Declare a function with an intention to define it.
167 /// For rust functions use `define_rust_fn` instead.
169 /// Use this function when you intend to define a function. This function will
170 /// return None if the name already has a definition associated with it. In that
171 /// case an error should be reported to the user, because it usually happens due
172 /// to user’s fault (e.g. misuse of #[no_mangle] or #[export_name] attributes).
173 pub fn define_fn(ccx
: &CrateContext
, name
: &str, callconv
: llvm
::CallConv
,
174 fn_type
: Type
, output
: ty
::FnOutput
) -> Option
<ValueRef
> {
175 if get_defined_value(ccx
, name
).is_some() {
178 Some(declare_fn(ccx
, name
, callconv
, fn_type
, output
))
183 /// Declare a C ABI function with an intention to define it.
185 /// Use this function when you intend to define a function. This function will
186 /// return None if the name already has a definition associated with it. In that
187 /// case an error should be reported to the user, because it usually happens due
188 /// to user’s fault (e.g. misuse of #[no_mangle] or #[export_name] attributes).
190 /// Only use this for foreign function ABIs and glue. For Rust functions use
191 /// `declare_rust_fn` instead.
192 pub fn define_cfn(ccx
: &CrateContext
, name
: &str, fn_type
: Type
,
193 output
: ty
::Ty
) -> Option
<ValueRef
> {
194 if get_defined_value(ccx
, name
).is_some() {
197 Some(declare_cfn(ccx
, name
, fn_type
, output
))
202 /// Declare a Rust function with an intention to define it.
204 /// Use this function when you intend to define a function. This function will
205 /// return None if the name already has a definition associated with it. In that
206 /// case an error should be reported to the user, because it usually happens due
207 /// to user’s fault (e.g. misuse of #[no_mangle] or #[export_name] attributes).
208 pub fn define_rust_fn
<'a
, 'tcx
>(ccx
: &CrateContext
<'a
, 'tcx
>, name
: &str,
209 fn_type
: ty
::Ty
<'tcx
>) -> Option
<ValueRef
> {
210 if get_defined_value(ccx
, name
).is_some() {
213 Some(declare_rust_fn(ccx
, name
, fn_type
))
218 /// Declare a Rust function with an intention to define it.
220 /// Use this function when you intend to define a function. This function will
221 /// return panic if the name already has a definition associated with it. This
222 /// can happen with #[no_mangle] or #[export_name], for example.
223 pub fn define_internal_rust_fn
<'a
, 'tcx
>(ccx
: &CrateContext
<'a
, 'tcx
>,
225 fn_type
: ty
::Ty
<'tcx
>) -> ValueRef
{
226 if get_defined_value(ccx
, name
).is_some() {
227 ccx
.sess().fatal(&format
!("symbol `{}` already defined", name
))
229 declare_internal_rust_fn(ccx
, name
, fn_type
)
234 /// Get defined or externally defined (AvailableExternally linkage) value by
236 fn get_defined_value(ccx
: &CrateContext
, name
: &str) -> Option
<ValueRef
> {
237 debug
!("get_defined_value(name={:?})", name
);
238 let namebuf
= CString
::new(name
).unwrap_or_else(|_
|{
239 ccx
.sess().bug(&format
!("name {:?} contains an interior null byte", name
))
241 let val
= unsafe { llvm::LLVMGetNamedValue(ccx.llmod(), namebuf.as_ptr()) }
;
243 debug
!("get_defined_value: {:?} value is null", name
);
246 let (declaration
, aext_link
) = unsafe {
247 let linkage
= llvm
::LLVMGetLinkage(val
);
248 (llvm
::LLVMIsDeclaration(val
) != 0,
249 linkage
== llvm
::AvailableExternallyLinkage
as c_uint
)
251 debug
!("get_defined_value: found {:?} value (declaration: {}, \
252 aext_link: {})", name
, declaration
, aext_link
);
253 if !declaration
|| aext_link
{