2015-03-04 01:08:06 +02:00
|
|
|
|
// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
|
|
|
|
|
// file at the top-level directory of this distribution and at
|
|
|
|
|
// http://rust-lang.org/COPYRIGHT.
|
|
|
|
|
//
|
|
|
|
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
|
|
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
|
|
|
// option. This file may not be copied, modified, or distributed
|
|
|
|
|
// except according to those terms.
|
|
|
|
|
//! Declare various LLVM values.
|
|
|
|
|
//!
|
2015-05-11 14:58:58 -07:00
|
|
|
|
//! Prefer using functions and methods from this module rather than calling LLVM
|
|
|
|
|
//! functions directly. These functions do some additional work to ensure we do
|
|
|
|
|
//! the right thing given the preconceptions of trans.
|
2015-03-04 01:08:06 +02:00
|
|
|
|
//!
|
|
|
|
|
//! Some useful guidelines:
|
|
|
|
|
//!
|
2015-05-11 14:58:58 -07:00
|
|
|
|
//! * Use declare_* family of methods if you are declaring, but are not
|
|
|
|
|
//! interested in defining the ValueRef they return.
|
2015-03-04 01:08:06 +02:00
|
|
|
|
//! * Use define_* family of methods when you might be defining the ValueRef.
|
|
|
|
|
//! * When in doubt, define.
|
|
|
|
|
use llvm::{self, ValueRef};
|
2016-08-03 00:25:19 +03:00
|
|
|
|
use llvm::AttributePlace::Function;
|
2016-03-22 17:30:57 +02:00
|
|
|
|
use rustc::ty;
|
2016-03-22 19:23:36 +02:00
|
|
|
|
use abi::{Abi, FnType};
|
|
|
|
|
use attributes;
|
|
|
|
|
use context::CrateContext;
|
|
|
|
|
use type_::Type;
|
2016-04-05 13:01:00 +03:00
|
|
|
|
use value::Value;
|
2015-03-04 01:08:06 +02:00
|
|
|
|
|
|
|
|
|
use std::ffi::CString;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// Declare a global value.
|
|
|
|
|
///
|
2015-05-11 14:58:58 -07:00
|
|
|
|
/// If there’s a value with the same name already declared, the function will
|
|
|
|
|
/// return its ValueRef instead.
|
2015-03-04 01:08:06 +02:00
|
|
|
|
pub fn declare_global(ccx: &CrateContext, name: &str, ty: Type) -> llvm::ValueRef {
|
|
|
|
|
debug!("declare_global(name={:?})", name);
|
|
|
|
|
let namebuf = CString::new(name).unwrap_or_else(|_|{
|
2016-03-29 01:46:02 +02:00
|
|
|
|
bug!("name {:?} contains an interior null byte", name)
|
2015-03-04 01:08:06 +02:00
|
|
|
|
});
|
|
|
|
|
unsafe {
|
2016-08-02 02:35:09 +03:00
|
|
|
|
llvm::LLVMRustGetOrInsertGlobal(ccx.llmod(), namebuf.as_ptr(), ty.to_ref())
|
2015-03-04 01:08:06 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// Declare a function.
|
|
|
|
|
///
|
2015-05-11 14:58:58 -07:00
|
|
|
|
/// If there’s a value with the same name already declared, the function will
|
|
|
|
|
/// update the declaration and return existing ValueRef instead.
|
2016-02-23 21:46:08 +02:00
|
|
|
|
fn declare_raw_fn(ccx: &CrateContext, name: &str, callconv: llvm::CallConv, ty: Type) -> ValueRef {
|
|
|
|
|
debug!("declare_raw_fn(name={:?}, ty={:?})", name, ty);
|
2015-03-04 01:08:06 +02:00
|
|
|
|
let namebuf = CString::new(name).unwrap_or_else(|_|{
|
2016-03-29 01:46:02 +02:00
|
|
|
|
bug!("name {:?} contains an interior null byte", name)
|
2015-03-04 01:08:06 +02:00
|
|
|
|
});
|
|
|
|
|
let llfn = unsafe {
|
2016-08-02 02:35:09 +03:00
|
|
|
|
llvm::LLVMRustGetOrInsertFunction(ccx.llmod(), namebuf.as_ptr(), ty.to_ref())
|
2015-03-04 01:08:06 +02:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
llvm::SetFunctionCallConv(llfn, callconv);
|
2015-05-11 14:58:58 -07:00
|
|
|
|
// Function addresses in Rust are never significant, allowing functions to
|
|
|
|
|
// be merged.
|
2015-03-04 01:08:06 +02:00
|
|
|
|
llvm::SetUnnamedAddr(llfn, true);
|
|
|
|
|
|
|
|
|
|
if ccx.tcx().sess.opts.cg.no_redzone
|
|
|
|
|
.unwrap_or(ccx.tcx().sess.target.target.options.disable_redzone) {
|
2016-08-03 00:25:19 +03:00
|
|
|
|
llvm::Attribute::NoRedZone.apply_llfn(Function, llfn);
|
2015-03-04 01:08:06 +02:00
|
|
|
|
}
|
|
|
|
|
|
2016-03-27 12:42:47 -07:00
|
|
|
|
match ccx.tcx().sess.opts.cg.opt_level.as_ref().map(String::as_ref) {
|
|
|
|
|
Some("s") => {
|
2016-08-03 00:25:19 +03:00
|
|
|
|
llvm::Attribute::OptimizeForSize.apply_llfn(Function, llfn);
|
2016-03-27 12:42:47 -07:00
|
|
|
|
},
|
|
|
|
|
Some("z") => {
|
2016-08-03 00:25:19 +03:00
|
|
|
|
llvm::Attribute::MinSize.apply_llfn(Function, llfn);
|
|
|
|
|
llvm::Attribute::OptimizeForSize.apply_llfn(Function, llfn);
|
2016-03-27 12:42:47 -07:00
|
|
|
|
},
|
|
|
|
|
_ => {},
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-04 01:08:06 +02:00
|
|
|
|
llfn
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// Declare a C ABI function.
|
|
|
|
|
///
|
2015-05-11 14:58:58 -07:00
|
|
|
|
/// Only use this for foreign function ABIs and glue. For Rust functions use
|
2016-02-23 21:57:22 +02:00
|
|
|
|
/// `declare_fn` instead.
|
2015-03-04 01:08:06 +02:00
|
|
|
|
///
|
2015-05-11 14:58:58 -07:00
|
|
|
|
/// If there’s a value with the same name already declared, the function will
|
|
|
|
|
/// update the declaration and return existing ValueRef instead.
|
2016-02-23 21:46:08 +02:00
|
|
|
|
pub fn declare_cfn(ccx: &CrateContext, name: &str, fn_type: Type) -> ValueRef {
|
|
|
|
|
declare_raw_fn(ccx, name, llvm::CCallConv, fn_type)
|
2015-03-04 01:08:06 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// Declare a Rust function.
|
|
|
|
|
///
|
2015-05-11 14:58:58 -07:00
|
|
|
|
/// If there’s a value with the same name already declared, the function will
|
|
|
|
|
/// update the declaration and return existing ValueRef instead.
|
2016-02-23 21:57:22 +02:00
|
|
|
|
pub fn declare_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, name: &str,
|
|
|
|
|
fn_type: ty::Ty<'tcx>) -> ValueRef {
|
2016-02-24 01:16:27 +02:00
|
|
|
|
debug!("declare_rust_fn(name={:?}, fn_type={:?})", name, fn_type);
|
2016-03-06 16:30:21 +02:00
|
|
|
|
let abi = fn_type.fn_abi();
|
|
|
|
|
let sig = ccx.tcx().erase_late_bound_regions(fn_type.fn_sig());
|
2016-03-11 02:33:20 +02:00
|
|
|
|
let sig = ccx.tcx().normalize_associated_type(&sig);
|
2015-06-18 20:25:05 +03:00
|
|
|
|
debug!("declare_rust_fn (after region erasure) sig={:?}", sig);
|
2016-02-23 21:57:22 +02:00
|
|
|
|
|
2016-03-06 16:30:21 +02:00
|
|
|
|
let fty = FnType::new(ccx, abi, &sig, &[]);
|
2016-02-25 12:11:02 +02:00
|
|
|
|
let llfn = declare_raw_fn(ccx, name, fty.cconv, fty.llvm_type(ccx));
|
2015-03-04 01:08:06 +02:00
|
|
|
|
|
2016-08-02 15:56:20 +08:00
|
|
|
|
// FIXME(canndrew): This is_never should really be an is_uninhabited
|
|
|
|
|
if sig.output.is_never() {
|
2016-08-03 00:25:19 +03:00
|
|
|
|
llvm::Attribute::NoReturn.apply_llfn(Function, llfn);
|
2016-02-23 21:57:22 +02:00
|
|
|
|
}
|
|
|
|
|
|
2016-03-06 16:30:21 +02:00
|
|
|
|
if abi != Abi::Rust && abi != Abi::RustCall {
|
2016-02-25 12:11:02 +02:00
|
|
|
|
attributes::unwind(llfn, false);
|
2016-02-26 01:10:40 +02:00
|
|
|
|
}
|
2016-02-25 12:11:02 +02:00
|
|
|
|
|
2016-02-26 01:10:40 +02:00
|
|
|
|
fty.apply_attrs_llfn(llfn);
|
2015-03-04 01:08:06 +02:00
|
|
|
|
|
|
|
|
|
llfn
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// Declare a global with an intention to define it.
|
|
|
|
|
///
|
2015-05-11 14:58:58 -07:00
|
|
|
|
/// Use this function when you intend to define a global. This function will
|
|
|
|
|
/// return None if the name already has a definition associated with it. In that
|
|
|
|
|
/// case an error should be reported to the user, because it usually happens due
|
|
|
|
|
/// to user’s fault (e.g. misuse of #[no_mangle] or #[export_name] attributes).
|
2015-03-04 01:08:06 +02:00
|
|
|
|
pub fn define_global(ccx: &CrateContext, name: &str, ty: Type) -> Option<ValueRef> {
|
|
|
|
|
if get_defined_value(ccx, name).is_some() {
|
|
|
|
|
None
|
|
|
|
|
} else {
|
|
|
|
|
Some(declare_global(ccx, name, ty))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Declare a Rust function with an intention to define it.
|
|
|
|
|
///
|
2015-05-11 14:58:58 -07:00
|
|
|
|
/// Use this function when you intend to define a function. This function will
|
2015-07-20 13:27:38 -07:00
|
|
|
|
/// return panic if the name already has a definition associated with it. This
|
|
|
|
|
/// can happen with #[no_mangle] or #[export_name], for example.
|
2016-05-09 23:56:49 -04:00
|
|
|
|
pub fn define_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
|
|
|
|
name: &str,
|
|
|
|
|
fn_type: ty::Ty<'tcx>) -> ValueRef {
|
2015-03-04 01:08:06 +02:00
|
|
|
|
if get_defined_value(ccx, name).is_some() {
|
2015-07-20 13:27:38 -07:00
|
|
|
|
ccx.sess().fatal(&format!("symbol `{}` already defined", name))
|
2015-03-04 01:08:06 +02:00
|
|
|
|
} else {
|
2016-05-09 23:56:49 -04:00
|
|
|
|
declare_fn(ccx, name, fn_type)
|
2015-03-04 01:08:06 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-05-09 23:56:49 -04:00
|
|
|
|
/// Declare a Rust function with an intention to define it.
|
|
|
|
|
///
|
|
|
|
|
/// Use this function when you intend to define a function. This function will
|
|
|
|
|
/// return panic if the name already has a definition associated with it. This
|
|
|
|
|
/// can happen with #[no_mangle] or #[export_name], for example.
|
|
|
|
|
pub fn define_internal_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
|
|
|
|
name: &str,
|
|
|
|
|
fn_type: ty::Ty<'tcx>) -> ValueRef {
|
|
|
|
|
let llfn = define_fn(ccx, name, fn_type);
|
2016-08-03 00:25:19 +03:00
|
|
|
|
unsafe { llvm::LLVMSetLinkage(llfn, llvm::InternalLinkage) };
|
2016-05-09 23:56:49 -04:00
|
|
|
|
llfn
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-04 01:08:06 +02:00
|
|
|
|
|
2016-04-05 13:01:00 +03:00
|
|
|
|
/// Get declared value by name.
|
|
|
|
|
pub fn get_declared_value(ccx: &CrateContext, name: &str) -> Option<ValueRef> {
|
|
|
|
|
debug!("get_declared_value(name={:?})", name);
|
2015-03-04 01:08:06 +02:00
|
|
|
|
let namebuf = CString::new(name).unwrap_or_else(|_|{
|
2016-03-29 01:46:02 +02:00
|
|
|
|
bug!("name {:?} contains an interior null byte", name)
|
2015-03-04 01:08:06 +02:00
|
|
|
|
});
|
2016-08-02 02:35:09 +03:00
|
|
|
|
let val = unsafe { llvm::LLVMRustGetNamedValue(ccx.llmod(), namebuf.as_ptr()) };
|
2015-03-04 01:08:06 +02:00
|
|
|
|
if val.is_null() {
|
2016-04-05 13:01:00 +03:00
|
|
|
|
debug!("get_declared_value: {:?} value is null", name);
|
2015-03-04 01:08:06 +02:00
|
|
|
|
None
|
|
|
|
|
} else {
|
2016-04-05 13:01:00 +03:00
|
|
|
|
debug!("get_declared_value: {:?} => {:?}", name, Value(val));
|
|
|
|
|
Some(val)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Get defined or externally defined (AvailableExternally linkage) value by
|
|
|
|
|
/// name.
|
|
|
|
|
pub fn get_defined_value(ccx: &CrateContext, name: &str) -> Option<ValueRef> {
|
|
|
|
|
get_declared_value(ccx, name).and_then(|val|{
|
2016-04-01 15:24:56 +02:00
|
|
|
|
let declaration = unsafe {
|
|
|
|
|
llvm::LLVMIsDeclaration(val) != 0
|
2015-03-04 01:08:06 +02:00
|
|
|
|
};
|
2016-04-01 15:24:56 +02:00
|
|
|
|
if !declaration {
|
2015-03-04 01:08:06 +02:00
|
|
|
|
Some(val)
|
|
|
|
|
} else {
|
|
|
|
|
None
|
|
|
|
|
}
|
2016-04-05 13:01:00 +03:00
|
|
|
|
})
|
2015-03-04 01:08:06 +02:00
|
|
|
|
}
|