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}
;
25 use abi
::{Abi, FnType}
;
27 use context
::CrateContext
;
31 use std
::ffi
::CString
;
34 /// Declare a global value.
36 /// If there’s a value with the same name already declared, the function will
37 /// return its ValueRef instead.
38 pub fn declare_global(ccx
: &CrateContext
, name
: &str, ty
: Type
) -> llvm
::ValueRef
{
39 debug
!("declare_global(name={:?})", name
);
40 let namebuf
= CString
::new(name
).unwrap_or_else(|_
|{
41 bug
!("name {:?} contains an interior null byte", name
)
44 llvm
::LLVMGetOrInsertGlobal(ccx
.llmod(), namebuf
.as_ptr(), ty
.to_ref())
49 /// Declare a function.
51 /// If there’s a value with the same name already declared, the function will
52 /// update the declaration and return existing ValueRef instead.
53 fn declare_raw_fn(ccx
: &CrateContext
, name
: &str, callconv
: llvm
::CallConv
, ty
: Type
) -> ValueRef
{
54 debug
!("declare_raw_fn(name={:?}, ty={:?})", name
, ty
);
55 let namebuf
= CString
::new(name
).unwrap_or_else(|_
|{
56 bug
!("name {:?} contains an interior null byte", name
)
59 llvm
::LLVMGetOrInsertFunction(ccx
.llmod(), namebuf
.as_ptr(), ty
.to_ref())
62 llvm
::SetFunctionCallConv(llfn
, callconv
);
63 // Function addresses in Rust are never significant, allowing functions to
65 llvm
::SetUnnamedAddr(llfn
, true);
67 if ccx
.tcx().sess
.opts
.cg
.no_redzone
68 .unwrap_or(ccx
.tcx().sess
.target
.target
.options
.disable_redzone
) {
69 llvm
::SetFunctionAttribute(llfn
, llvm
::Attribute
::NoRedZone
)
76 /// Declare a C ABI function.
78 /// Only use this for foreign function ABIs and glue. For Rust functions use
79 /// `declare_fn` instead.
81 /// If there’s a value with the same name already declared, the function will
82 /// update the declaration and return existing ValueRef instead.
83 pub fn declare_cfn(ccx
: &CrateContext
, name
: &str, fn_type
: Type
) -> ValueRef
{
84 declare_raw_fn(ccx
, name
, llvm
::CCallConv
, fn_type
)
88 /// Declare a Rust function.
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_fn
<'a
, 'tcx
>(ccx
: &CrateContext
<'a
, 'tcx
>, name
: &str,
93 fn_type
: ty
::Ty
<'tcx
>) -> ValueRef
{
94 debug
!("declare_rust_fn(name={:?}, fn_type={:?})", name
, fn_type
);
95 let abi
= fn_type
.fn_abi();
96 let sig
= ccx
.tcx().erase_late_bound_regions(fn_type
.fn_sig());
97 let sig
= infer
::normalize_associated_type(ccx
.tcx(), &sig
);
98 debug
!("declare_rust_fn (after region erasure) sig={:?}", sig
);
100 let fty
= FnType
::new(ccx
, abi
, &sig
, &[]);
101 let llfn
= declare_raw_fn(ccx
, name
, fty
.cconv
, fty
.llvm_type(ccx
));
103 if sig
.output
== ty
::FnDiverging
{
104 llvm
::SetFunctionAttribute(llfn
, llvm
::Attribute
::NoReturn
);
107 if abi
!= Abi
::Rust
&& abi
!= Abi
::RustCall
{
108 attributes
::unwind(llfn
, false);
111 fty
.apply_attrs_llfn(llfn
);
117 /// Declare a global with an intention to define it.
119 /// Use this function when you intend to define a global. This function will
120 /// return None if the name already has a definition associated with it. In that
121 /// case an error should be reported to the user, because it usually happens due
122 /// to user’s fault (e.g. misuse of #[no_mangle] or #[export_name] attributes).
123 pub fn define_global(ccx
: &CrateContext
, name
: &str, ty
: Type
) -> Option
<ValueRef
> {
124 if get_defined_value(ccx
, name
).is_some() {
127 Some(declare_global(ccx
, name
, ty
))
132 /// Declare a Rust function with an intention to define it.
134 /// Use this function when you intend to define a function. This function will
135 /// return panic if the name already has a definition associated with it. This
136 /// can happen with #[no_mangle] or #[export_name], for example.
137 pub fn define_internal_fn
<'a
, 'tcx
>(ccx
: &CrateContext
<'a
, 'tcx
>,
139 fn_type
: ty
::Ty
<'tcx
>) -> ValueRef
{
140 if get_defined_value(ccx
, name
).is_some() {
141 ccx
.sess().fatal(&format
!("symbol `{}` already defined", name
))
143 let llfn
= declare_fn(ccx
, name
, fn_type
);
144 llvm
::SetLinkage(llfn
, llvm
::InternalLinkage
);
150 /// Get declared value by name.
151 pub fn get_declared_value(ccx
: &CrateContext
, name
: &str) -> Option
<ValueRef
> {
152 debug
!("get_declared_value(name={:?})", name
);
153 let namebuf
= CString
::new(name
).unwrap_or_else(|_
|{
154 bug
!("name {:?} contains an interior null byte", name
)
156 let val
= unsafe { llvm::LLVMGetNamedValue(ccx.llmod(), namebuf.as_ptr()) }
;
158 debug
!("get_declared_value: {:?} value is null", name
);
161 debug
!("get_declared_value: {:?} => {:?}", name
, Value(val
));
166 /// Get defined or externally defined (AvailableExternally linkage) value by
168 pub fn get_defined_value(ccx
: &CrateContext
, name
: &str) -> Option
<ValueRef
> {
169 get_declared_value(ccx
, name
).and_then(|val
|{
170 let declaration
= unsafe {
171 llvm
::LLVMIsDeclaration(val
) != 0