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.
23 use llvm
::{self, ValueRef}
;
24 use llvm
::AttributePlace
::Function
;
25 use rustc
::ty
::{self, Ty}
;
26 use rustc
::ty
::layout
::{self, LayoutOf}
;
27 use rustc
::session
::config
::Sanitizer
;
28 use rustc_target
::spec
::PanicStrategy
;
29 use abi
::{Abi, FnType, FnTypeExt}
;
31 use context
::CodegenCx
;
36 use std
::ffi
::CString
;
39 /// Declare a global value.
41 /// If there’s a value with the same name already declared, the function will
42 /// return its ValueRef instead.
43 pub fn declare_global(cx
: &CodegenCx
, name
: &str, ty
: Type
) -> llvm
::ValueRef
{
44 debug
!("declare_global(name={:?})", name
);
45 let namebuf
= CString
::new(name
).unwrap_or_else(|_
|{
46 bug
!("name {:?} contains an interior null byte", name
)
49 llvm
::LLVMRustGetOrInsertGlobal(cx
.llmod
, namebuf
.as_ptr(), ty
.to_ref())
54 /// Declare a function.
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 fn declare_raw_fn(cx
: &CodegenCx
, name
: &str, callconv
: llvm
::CallConv
, ty
: Type
) -> ValueRef
{
59 debug
!("declare_raw_fn(name={:?}, ty={:?})", name
, ty
);
60 let namebuf
= CString
::new(name
).unwrap_or_else(|_
|{
61 bug
!("name {:?} contains an interior null byte", name
)
64 llvm
::LLVMRustGetOrInsertFunction(cx
.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 cx
.tcx
.sess
.opts
.cg
.no_redzone
73 .unwrap_or(cx
.tcx
.sess
.target
.target
.options
.disable_redzone
) {
74 llvm
::Attribute
::NoRedZone
.apply_llfn(Function
, llfn
);
77 if let Some(ref sanitizer
) = cx
.tcx
.sess
.opts
.debugging_opts
.sanitizer
{
79 Sanitizer
::Address
=> {
80 llvm
::Attribute
::SanitizeAddress
.apply_llfn(Function
, llfn
);
82 Sanitizer
::Memory
=> {
83 llvm
::Attribute
::SanitizeMemory
.apply_llfn(Function
, llfn
);
85 Sanitizer
::Thread
=> {
86 llvm
::Attribute
::SanitizeThread
.apply_llfn(Function
, llfn
);
92 match cx
.tcx
.sess
.opts
.cg
.opt_level
.as_ref().map(String
::as_ref
) {
94 llvm
::Attribute
::OptimizeForSize
.apply_llfn(Function
, llfn
);
97 llvm
::Attribute
::MinSize
.apply_llfn(Function
, llfn
);
98 llvm
::Attribute
::OptimizeForSize
.apply_llfn(Function
, llfn
);
103 if cx
.tcx
.sess
.panic_strategy() != PanicStrategy
::Unwind
{
104 attributes
::unwind(llfn
, false);
111 /// Declare a C ABI function.
113 /// Only use this for foreign function ABIs and glue. For Rust functions use
114 /// `declare_fn` instead.
116 /// If there’s a value with the same name already declared, the function will
117 /// update the declaration and return existing ValueRef instead.
118 pub fn declare_cfn(cx
: &CodegenCx
, name
: &str, fn_type
: Type
) -> ValueRef
{
119 declare_raw_fn(cx
, name
, llvm
::CCallConv
, fn_type
)
123 /// Declare a Rust function.
125 /// If there’s a value with the same name already declared, the function will
126 /// update the declaration and return existing ValueRef instead.
127 pub fn declare_fn
<'a
, 'tcx
>(cx
: &CodegenCx
<'a
, 'tcx
>, name
: &str,
128 fn_type
: Ty
<'tcx
>) -> ValueRef
{
129 debug
!("declare_rust_fn(name={:?}, fn_type={:?})", name
, fn_type
);
130 let sig
= common
::ty_fn_sig(cx
, fn_type
);
131 let sig
= cx
.tcx
.normalize_erasing_late_bound_regions(ty
::ParamEnv
::reveal_all(), &sig
);
132 debug
!("declare_rust_fn (after region erasure) sig={:?}", sig
);
134 let fty
= FnType
::new(cx
, sig
, &[]);
135 let llfn
= declare_raw_fn(cx
, name
, fty
.llvm_cconv(), fty
.llvm_type(cx
));
137 if cx
.layout_of(sig
.output()).abi
== layout
::Abi
::Uninhabited
{
138 llvm
::Attribute
::NoReturn
.apply_llfn(Function
, llfn
);
141 if sig
.abi
!= Abi
::Rust
&& sig
.abi
!= Abi
::RustCall
{
142 attributes
::unwind(llfn
, false);
145 fty
.apply_attrs_llfn(llfn
);
151 /// Declare a global with an intention to define it.
153 /// Use this function when you intend to define a global. This function will
154 /// return None if the name already has a definition associated with it. In that
155 /// case an error should be reported to the user, because it usually happens due
156 /// to user’s fault (e.g. misuse of #[no_mangle] or #[export_name] attributes).
157 pub fn define_global(cx
: &CodegenCx
, name
: &str, ty
: Type
) -> Option
<ValueRef
> {
158 if get_defined_value(cx
, name
).is_some() {
161 Some(declare_global(cx
, name
, ty
))
165 /// Declare a Rust function with an intention to define it.
167 /// Use this function when you intend to define a function. This function will
168 /// return panic if the name already has a definition associated with it. This
169 /// can happen with #[no_mangle] or #[export_name], for example.
170 pub fn define_fn
<'a
, 'tcx
>(cx
: &CodegenCx
<'a
, 'tcx
>,
172 fn_type
: Ty
<'tcx
>) -> ValueRef
{
173 if get_defined_value(cx
, name
).is_some() {
174 cx
.sess().fatal(&format
!("symbol `{}` already defined", name
))
176 declare_fn(cx
, name
, fn_type
)
180 /// Declare a Rust function with an intention to define it.
182 /// Use this function when you intend to define a function. This function will
183 /// return panic if the name already has a definition associated with it. This
184 /// can happen with #[no_mangle] or #[export_name], for example.
185 pub fn define_internal_fn
<'a
, 'tcx
>(cx
: &CodegenCx
<'a
, 'tcx
>,
187 fn_type
: Ty
<'tcx
>) -> ValueRef
{
188 let llfn
= define_fn(cx
, name
, fn_type
);
189 unsafe { llvm::LLVMRustSetLinkage(llfn, llvm::Linkage::InternalLinkage) }
;
194 /// Get declared value by name.
195 pub fn get_declared_value(cx
: &CodegenCx
, name
: &str) -> Option
<ValueRef
> {
196 debug
!("get_declared_value(name={:?})", name
);
197 let namebuf
= CString
::new(name
).unwrap_or_else(|_
|{
198 bug
!("name {:?} contains an interior null byte", name
)
200 let val
= unsafe { llvm::LLVMRustGetNamedValue(cx.llmod, namebuf.as_ptr()) }
;
202 debug
!("get_declared_value: {:?} value is null", name
);
205 debug
!("get_declared_value: {:?} => {:?}", name
, Value(val
));
210 /// Get defined or externally defined (AvailableExternally linkage) value by
212 pub fn get_defined_value(cx
: &CodegenCx
, name
: &str) -> Option
<ValueRef
> {
213 get_declared_value(cx
, name
).and_then(|val
|{
214 let declaration
= unsafe {
215 llvm
::LLVMIsDeclaration(val
) != 0