Added StaticMethods trait

This commit is contained in:
Denis Merigoux 2018-09-10 16:28:47 +02:00 committed by Eduard-Mihai Burtescu
parent d77e34f35b
commit 3c082a23e8
10 changed files with 383 additions and 336 deletions

View File

@ -24,7 +24,7 @@
use type_of::LayoutLlvmExt;
use value::Value;
use rustc::ty::{self, Ty};
use interfaces::{BaseTypeMethods, DerivedTypeMethods};
use interfaces::{BaseTypeMethods, DerivedTypeMethods, StaticMethods};
use rustc::ty::layout::{Align, LayoutOf};
@ -32,17 +32,6 @@
use std::ffi::{CStr, CString};
pub fn ptrcast(val: &'ll Value, ty: &'ll Type) -> &'ll Value {
unsafe {
llvm::LLVMConstPointerCast(val, ty)
}
}
pub fn bitcast(val: &'ll Value, ty: &'ll Type) -> &'ll Value {
unsafe {
llvm::LLVMConstBitCast(val, ty)
}
}
fn set_global_alignment(cx: &CodegenCx<'ll, '_>,
gv: &'ll Value,
@ -63,178 +52,6 @@ fn set_global_alignment(cx: &CodegenCx<'ll, '_>,
}
}
pub fn addr_of_mut(
cx: &CodegenCx<'ll, '_>,
cv: &'ll Value,
align: Align,
kind: Option<&str>,
) -> &'ll Value {
unsafe {
let gv = match kind {
Some(kind) if !cx.tcx.sess.fewer_names() => {
let name = cx.generate_local_symbol_name(kind);
let gv = declare::define_global(cx, &name[..],
cx.val_ty(cv)).unwrap_or_else(||{
bug!("symbol `{}` is already defined", name);
});
llvm::LLVMRustSetLinkage(gv, llvm::Linkage::PrivateLinkage);
gv
},
_ => declare::define_private_global(cx, cx.val_ty(cv)),
};
llvm::LLVMSetInitializer(gv, cv);
set_global_alignment(cx, gv, align);
SetUnnamedAddr(gv, true);
gv
}
}
pub fn addr_of(
cx: &CodegenCx<'ll, '_>,
cv: &'ll Value,
align: Align,
kind: Option<&str>,
) -> &'ll Value {
if let Some(&gv) = cx.const_globals.borrow().get(&cv) {
unsafe {
// Upgrade the alignment in cases where the same constant is used with different
// alignment requirements
let llalign = align.abi() as u32;
if llalign > llvm::LLVMGetAlignment(gv) {
llvm::LLVMSetAlignment(gv, llalign);
}
}
return gv;
}
let gv = addr_of_mut(cx, cv, align, kind);
unsafe {
llvm::LLVMSetGlobalConstant(gv, True);
}
cx.const_globals.borrow_mut().insert(cv, gv);
gv
}
pub fn get_static(cx: &CodegenCx<'ll, '_>, def_id: DefId) -> &'ll Value {
let instance = Instance::mono(cx.tcx, def_id);
if let Some(&g) = cx.instances.borrow().get(&instance) {
return g;
}
let defined_in_current_codegen_unit = cx.codegen_unit
.items()
.contains_key(&MonoItem::Static(def_id));
assert!(!defined_in_current_codegen_unit,
"consts::get_static() should always hit the cache for \
statics defined in the same CGU, but did not for `{:?}`",
def_id);
let ty = instance.ty(cx.tcx);
let sym = cx.tcx.symbol_name(instance).as_str();
debug!("get_static: sym={} instance={:?}", sym, instance);
let g = if let Some(id) = cx.tcx.hir.as_local_node_id(def_id) {
let llty = cx.layout_of(ty).llvm_type(cx);
let (g, attrs) = match cx.tcx.hir.get(id) {
Node::Item(&hir::Item {
ref attrs, span, node: hir::ItemKind::Static(..), ..
}) => {
if declare::get_declared_value(cx, &sym[..]).is_some() {
span_bug!(span, "Conflicting symbol names for static?");
}
let g = declare::define_global(cx, &sym[..], llty).unwrap();
if !cx.tcx.is_reachable_non_generic(def_id) {
unsafe {
llvm::LLVMRustSetVisibility(g, llvm::Visibility::Hidden);
}
}
(g, attrs)
}
Node::ForeignItem(&hir::ForeignItem {
ref attrs, span, node: hir::ForeignItemKind::Static(..), ..
}) => {
let fn_attrs = cx.tcx.codegen_fn_attrs(def_id);
(check_and_apply_linkage(cx, &fn_attrs, ty, sym, Some(span)), attrs)
}
item => bug!("get_static: expected static, found {:?}", item)
};
debug!("get_static: sym={} attrs={:?}", sym, attrs);
for attr in attrs {
if attr.check_name("thread_local") {
llvm::set_thread_local_mode(g, cx.tls_model);
}
}
g
} else {
// FIXME(nagisa): perhaps the map of externs could be offloaded to llvm somehow?
debug!("get_static: sym={} item_attr={:?}", sym, cx.tcx.item_attrs(def_id));
let attrs = cx.tcx.codegen_fn_attrs(def_id);
let g = check_and_apply_linkage(cx, &attrs, ty, sym, None);
// Thread-local statics in some other crate need to *always* be linked
// against in a thread-local fashion, so we need to be sure to apply the
// thread-local attribute locally if it was present remotely. If we
// don't do this then linker errors can be generated where the linker
// complains that one object files has a thread local version of the
// symbol and another one doesn't.
if attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL) {
llvm::set_thread_local_mode(g, cx.tls_model);
}
let needs_dll_storage_attr =
cx.use_dll_storage_attrs && !cx.tcx.is_foreign_item(def_id) &&
// ThinLTO can't handle this workaround in all cases, so we don't
// emit the attrs. Instead we make them unnecessary by disallowing
// dynamic linking when cross-language LTO is enabled.
!cx.tcx.sess.opts.debugging_opts.cross_lang_lto.enabled();
// If this assertion triggers, there's something wrong with commandline
// argument validation.
debug_assert!(!(cx.tcx.sess.opts.debugging_opts.cross_lang_lto.enabled() &&
cx.tcx.sess.target.target.options.is_like_msvc &&
cx.tcx.sess.opts.cg.prefer_dynamic));
if needs_dll_storage_attr {
// This item is external but not foreign, i.e. it originates from an external Rust
// crate. Since we don't know whether this crate will be linked dynamically or
// statically in the final application, we always mark such symbols as 'dllimport'.
// If final linkage happens to be static, we rely on compiler-emitted __imp_ stubs to
// make things work.
//
// However, in some scenarios we defer emission of statics to downstream
// crates, so there are cases where a static with an upstream DefId
// is actually present in the current crate. We can find out via the
// is_codegened_item query.
if !cx.tcx.is_codegened_item(def_id) {
unsafe {
llvm::LLVMSetDLLStorageClass(g, llvm::DLLStorageClass::DllImport);
}
}
}
g
};
if cx.use_dll_storage_attrs && cx.tcx.is_dllimport_foreign_item(def_id) {
// For foreign (native) libs we know the exact storage type to use.
unsafe {
llvm::LLVMSetDLLStorageClass(g, llvm::DLLStorageClass::DllImport);
}
}
cx.instances.borrow_mut().insert(instance, g);
g
}
fn check_and_apply_linkage(
cx: &CodegenCx<'ll, 'tcx>,
attrs: &CodegenFnAttrs,
@ -294,146 +111,337 @@ fn check_and_apply_linkage(
}
}
pub fn codegen_static<'a, 'tcx>(
cx: &CodegenCx<'a, 'tcx>,
def_id: DefId,
is_mutable: bool,
) {
pub fn ptrcast(val: &'ll Value, ty: &'ll Type) -> &'ll Value {
unsafe {
let attrs = cx.tcx.codegen_fn_attrs(def_id);
llvm::LLVMConstPointerCast(val, ty)
}
}
let (v, alloc) = match ::mir::codegen_static_initializer(cx, def_id) {
Ok(v) => v,
// Error has already been reported
Err(_) => return,
};
impl StaticMethods<'tcx> for CodegenCx<'ll, 'tcx> {
let g = get_static(cx, def_id);
fn static_ptrcast(&self, val: &'ll Value, ty: &'ll Type) -> &'ll Value {
ptrcast(val, ty)
}
// boolean SSA values are i1, but they have to be stored in i8 slots,
// otherwise some LLVM optimization passes don't work as expected
let mut val_llty = cx.val_ty(v);
let v = if val_llty == cx.type_i1() {
val_llty = cx.type_i8();
llvm::LLVMConstZExt(v, val_llty)
} else {
v
};
fn static_bitcast(&self, val: &'ll Value, ty: &'ll Type) -> &'ll Value {
unsafe {
llvm::LLVMConstBitCast(val, ty)
}
}
fn static_addr_of_mut(
&self,
cv: &'ll Value,
align: Align,
kind: Option<&str>,
) -> &'ll Value {
unsafe {
let gv = match kind {
Some(kind) if !&self.tcx.sess.fewer_names() => {
let name = &self.generate_local_symbol_name(kind);
let gv = declare::define_global(&self, &name[..],
&self.val_ty(cv)).unwrap_or_else(||{
bug!("symbol `{}` is already defined", name);
});
llvm::LLVMRustSetLinkage(gv, llvm::Linkage::PrivateLinkage);
gv
},
_ => declare::define_private_global(&self, &self.val_ty(cv)),
};
llvm::LLVMSetInitializer(gv, cv);
set_global_alignment(&self, gv, align);
SetUnnamedAddr(gv, true);
gv
}
}
fn static_addr_of(
&self,
cv: &'ll Value,
align: Align,
kind: Option<&str>,
) -> &'ll Value {
if let Some(&gv) = &self.const_globals.borrow().get(&cv) {
unsafe {
// Upgrade the alignment in cases where the same constant is used with different
// alignment requirements
let llalign = align.abi() as u32;
if llalign > llvm::LLVMGetAlignment(gv) {
llvm::LLVMSetAlignment(gv, llalign);
}
}
return gv;
}
let gv = &self.static_addr_of_mut(cv, align, kind);
unsafe {
llvm::LLVMSetGlobalConstant(gv, True);
}
&self.const_globals.borrow_mut().insert(cv, gv);
gv
}
fn get_static(&self, def_id: DefId) -> &'ll Value {
let instance = Instance::mono(self.tcx, def_id);
if let Some(&g) = &self.instances.borrow().get(&instance) {
return g;
}
let defined_in_current_codegen_unit = &self.codegen_unit
.items()
.contains_key(&MonoItem::Static(def_id));
assert!(!defined_in_current_codegen_unit,
"consts::get_static() should always hit the cache for \
statics defined in the same CGU, but did not for `{:?}`",
def_id);
let ty = instance.ty(self.tcx);
let sym = self.tcx.symbol_name(instance).as_str();
debug!("get_static: sym={} instance={:?}", sym, instance);
let g = if let Some(id) = self.tcx.hir.as_local_node_id(def_id) {
let llty = &self.layout_of(ty).llvm_type(&self);
let (g, attrs) = match &self.tcx.hir.get(id) {
Node::Item(&hir::Item {
ref attrs, span, node: hir::ItemKind::Static(..), ..
}) => {
if declare::get_declared_value(&self, &sym[..]).is_some() {
span_bug!(span, "Conflicting symbol names for static?");
}
let g = declare::define_global(&self, &sym[..], llty).unwrap();
if !&self.tcx.is_reachable_non_generic(def_id) {
unsafe {
llvm::LLVMRustSetVisibility(g, llvm::Visibility::Hidden);
}
}
(g, attrs)
}
Node::ForeignItem(&hir::ForeignItem {
ref attrs, span, node: hir::ForeignItemKind::Static(..), ..
}) => {
let fn_attrs = &self.tcx.codegen_fn_attrs(def_id);
(check_and_apply_linkage(&self, &fn_attrs, ty, sym, Some(span)), attrs)
}
item => bug!("get_static: expected static, found {:?}", item)
};
debug!("get_static: sym={} attrs={:?}", sym, attrs);
for attr in attrs {
if attr.check_name("thread_local") {
llvm::set_thread_local_mode(g, self.tls_model);
}
}
let instance = Instance::mono(cx.tcx, def_id);
let ty = instance.ty(cx.tcx);
let llty = cx.layout_of(ty).llvm_type(cx);
let g = if val_llty == llty {
g
} else {
// If we created the global with the wrong type,
// correct the type.
let empty_string = const_cstr!("");
let name_str_ref = CStr::from_ptr(llvm::LLVMGetValueName(g));
let name_string = CString::new(name_str_ref.to_bytes()).unwrap();
llvm::LLVMSetValueName(g, empty_string.as_ptr());
// FIXME(nagisa): perhaps the map of externs could be offloaded to llvm somehow?
debug!("get_static: sym={} item_attr={:?}", sym, &self.tcx.item_attrs(def_id));
let linkage = llvm::LLVMRustGetLinkage(g);
let visibility = llvm::LLVMRustGetVisibility(g);
let attrs = &self.tcx.codegen_fn_attrs(def_id);
let g = check_and_apply_linkage(&self, &attrs, ty, sym, None);
let new_g = llvm::LLVMRustGetOrInsertGlobal(
cx.llmod, name_string.as_ptr(), val_llty);
// Thread-local statics in some other crate need to *always* be linked
// against in a thread-local fashion, so we need to be sure to apply the
// thread-local attribute locally if it was present remotely. If we
// don't do this then linker errors can be generated where the linker
// complains that one object files has a thread local version of the
// symbol and another one doesn't.
if attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL) {
llvm::set_thread_local_mode(g, self.tls_model);
}
llvm::LLVMRustSetLinkage(new_g, linkage);
llvm::LLVMRustSetVisibility(new_g, visibility);
let needs_dll_storage_attr =
self.use_dll_storage_attrs && !&self.tcx.is_foreign_item(def_id) &&
// ThinLTO can't handle this workaround in all cases, so we don't
// emit the attrs. Instead we make them unnecessary by disallowing
// dynamic linking when cross-language LTO is enabled.
!&self.tcx.sess.opts.debugging_opts.cross_lang_lto.enabled();
// To avoid breaking any invariants, we leave around the old
// global for the moment; we'll replace all references to it
// with the new global later. (See base::codegen_backend.)
cx.statics_to_rauw.borrow_mut().push((g, new_g));
new_g
// If this assertion triggers, there's something wrong with commandline
// argument validation.
debug_assert!(!(self.tcx.sess.opts.debugging_opts.cross_lang_lto.enabled() &&
self.tcx.sess.target.target.options.is_like_msvc &&
self.tcx.sess.opts.cg.prefer_dynamic));
if needs_dll_storage_attr {
// This item is external but not foreign, i.e. it originates from an external Rust
// crate. Since we don't know whether this crate will be linked dynamically or
// statically in the final application, we always mark such symbols as 'dllimport'.
// If final linkage happens to be static, we rely on compiler-emitted __imp_ stubs
// to make things work.
//
// However, in some scenarios we defer emission of statics to downstream
// crates, so there are cases where a static with an upstream DefId
// is actually present in the current crate. We can find out via the
// is_codegened_item query.
if !&self.tcx.is_codegened_item(def_id) {
unsafe {
llvm::LLVMSetDLLStorageClass(g, llvm::DLLStorageClass::DllImport);
}
}
}
g
};
set_global_alignment(cx, g, cx.align_of(ty));
llvm::LLVMSetInitializer(g, v);
// As an optimization, all shared statics which do not have interior
// mutability are placed into read-only memory.
if !is_mutable {
if cx.type_is_freeze(ty) {
llvm::LLVMSetGlobalConstant(g, llvm::True);
if self.use_dll_storage_attrs && self.tcx.is_dllimport_foreign_item(def_id) {
// For foreign (native) libs we know the exact storage type to use.
unsafe {
llvm::LLVMSetDLLStorageClass(g, llvm::DLLStorageClass::DllImport);
}
}
debuginfo::create_global_var_metadata(cx, def_id, g);
&self.instances.borrow_mut().insert(instance, g);
g
}
if attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL) {
llvm::set_thread_local_mode(g, cx.tls_model);
fn codegen_static(
&self,
def_id: DefId,
is_mutable: bool,
) {
unsafe {
let attrs = &self.tcx.codegen_fn_attrs(def_id);
// Do not allow LLVM to change the alignment of a TLS on macOS.
//
// By default a global's alignment can be freely increased.
// This allows LLVM to generate more performant instructions
// e.g. using load-aligned into a SIMD register.
//
// However, on macOS 10.10 or below, the dynamic linker does not
// respect any alignment given on the TLS (radar 24221680).
// This will violate the alignment assumption, and causing segfault at runtime.
//
// This bug is very easy to trigger. In `println!` and `panic!`,
// the `LOCAL_STDOUT`/`LOCAL_STDERR` handles are stored in a TLS,
// which the values would be `mem::replace`d on initialization.
// The implementation of `mem::replace` will use SIMD
// whenever the size is 32 bytes or higher. LLVM notices SIMD is used
// and tries to align `LOCAL_STDOUT`/`LOCAL_STDERR` to a 32-byte boundary,
// which macOS's dyld disregarded and causing crashes
// (see issues #51794, #51758, #50867, #48866 and #44056).
//
// To workaround the bug, we trick LLVM into not increasing
// the global's alignment by explicitly assigning a section to it
// (equivalent to automatically generating a `#[link_section]` attribute).
// See the comment in the `GlobalValue::canIncreaseAlignment()` function
// of `lib/IR/Globals.cpp` for why this works.
//
// When the alignment is not increased, the optimized `mem::replace`
// will use load-unaligned instructions instead, and thus avoiding the crash.
//
// We could remove this hack whenever we decide to drop macOS 10.10 support.
if cx.tcx.sess.target.target.options.is_like_osx {
let sect_name = if alloc.bytes.iter().all(|b| *b == 0) {
CStr::from_bytes_with_nul_unchecked(b"__DATA,__thread_bss\0")
} else {
CStr::from_bytes_with_nul_unchecked(b"__DATA,__thread_data\0")
};
llvm::LLVMSetSection(g, sect_name.as_ptr());
let (v, alloc) = match ::mir::codegen_static_initializer(&self, def_id) {
Ok(v) => v,
// Error has already been reported
Err(_) => return,
};
let g = &self.get_static(def_id);
// boolean SSA values are i1, but they have to be stored in i8 slots,
// otherwise some LLVM optimization passes don't work as expected
let mut val_llty = self.val_ty(v);
let v = if val_llty == self.type_i1() {
val_llty = self.type_i8();
llvm::LLVMConstZExt(v, val_llty)
} else {
v
};
let instance = Instance::mono(self.tcx, def_id);
let ty = instance.ty(self.tcx);
let llty = self.layout_of(ty).llvm_type(&self);
let g = if val_llty == llty {
g
} else {
// If we created the global with the wrong type,
// correct the type.
let empty_string = const_cstr!("");
let name_str_ref = CStr::from_ptr(llvm::LLVMGetValueName(g));
let name_string = CString::new(name_str_ref.to_bytes()).unwrap();
llvm::LLVMSetValueName(g, empty_string.as_ptr());
let linkage = llvm::LLVMRustGetLinkage(g);
let visibility = llvm::LLVMRustGetVisibility(g);
let new_g = llvm::LLVMRustGetOrInsertGlobal(
&self.llmod, name_string.as_ptr(), val_llty);
llvm::LLVMRustSetLinkage(new_g, linkage);
llvm::LLVMRustSetVisibility(new_g, visibility);
// To avoid breaking any invariants, we leave around the old
// global for the moment; we'll replace all references to it
// with the new global later. (See base::codegen_backend.)
&self.statics_to_rauw.borrow_mut().push((g, new_g));
new_g
};
set_global_alignment(&self, g, self.align_of(ty));
llvm::LLVMSetInitializer(g, v);
// As an optimization, all shared statics which do not have interior
// mutability are placed into read-only memory.
if !is_mutable {
if self.type_is_freeze(ty) {
llvm::LLVMSetGlobalConstant(g, llvm::True);
}
}
}
debuginfo::create_global_var_metadata(&self, def_id, g);
// Wasm statics with custom link sections get special treatment as they
// go into custom sections of the wasm executable.
if cx.tcx.sess.opts.target_triple.triple().starts_with("wasm32") {
if let Some(section) = attrs.link_section {
let section = llvm::LLVMMDStringInContext(
cx.llcx,
section.as_str().as_ptr() as *const _,
section.as_str().len() as c_uint,
);
let alloc = llvm::LLVMMDStringInContext(
cx.llcx,
alloc.bytes.as_ptr() as *const _,
alloc.bytes.len() as c_uint,
);
let data = [section, alloc];
let meta = llvm::LLVMMDNodeInContext(cx.llcx, data.as_ptr(), 2);
llvm::LLVMAddNamedMetadataOperand(
cx.llmod,
"wasm.custom_sections\0".as_ptr() as *const _,
meta,
);
if attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL) {
llvm::set_thread_local_mode(g, self.tls_model);
// Do not allow LLVM to change the alignment of a TLS on macOS.
//
// By default a global's alignment can be freely increased.
// This allows LLVM to generate more performant instructions
// e.g. using load-aligned into a SIMD register.
//
// However, on macOS 10.10 or below, the dynamic linker does not
// respect any alignment given on the TLS (radar 24221680).
// This will violate the alignment assumption, and causing segfault at runtime.
//
// This bug is very easy to trigger. In `println!` and `panic!`,
// the `LOCAL_STDOUT`/`LOCAL_STDERR` handles are stored in a TLS,
// which the values would be `mem::replace`d on initialization.
// The implementation of `mem::replace` will use SIMD
// whenever the size is 32 bytes or higher. LLVM notices SIMD is used
// and tries to align `LOCAL_STDOUT`/`LOCAL_STDERR` to a 32-byte boundary,
// which macOS's dyld disregarded and causing crashes
// (see issues #51794, #51758, #50867, #48866 and #44056).
//
// To workaround the bug, we trick LLVM into not increasing
// the global's alignment by explicitly assigning a section to it
// (equivalent to automatically generating a `#[link_section]` attribute).
// See the comment in the `GlobalValue::canIncreaseAlignment()` function
// of `lib/IR/Globals.cpp` for why this works.
//
// When the alignment is not increased, the optimized `mem::replace`
// will use load-unaligned instructions instead, and thus avoiding the crash.
//
// We could remove this hack whenever we decide to drop macOS 10.10 support.
if self.tcx.sess.target.target.options.is_like_osx {
let sect_name = if alloc.bytes.iter().all(|b| *b == 0) {
CStr::from_bytes_with_nul_unchecked(b"__DATA,__thread_bss\0")
} else {
CStr::from_bytes_with_nul_unchecked(b"__DATA,__thread_data\0")
};
llvm::LLVMSetSection(g, sect_name.as_ptr());
}
}
} else {
base::set_link_section(g, &attrs);
}
if attrs.flags.contains(CodegenFnAttrFlags::USED) {
// This static will be stored in the llvm.used variable which is an array of i8*
let cast = llvm::LLVMConstPointerCast(g, cx.type_i8p());
cx.used_statics.borrow_mut().push(cast);
// Wasm statics with custom link sections get special treatment as they
// go into custom sections of the wasm executable.
if self.tcx.sess.opts.target_triple.triple().starts_with("wasm32") {
if let Some(section) = attrs.link_section {
let section = llvm::LLVMMDStringInContext(
&self.llcx,
section.as_str().as_ptr() as *const _,
section.as_str().len() as c_uint,
);
let alloc = llvm::LLVMMDStringInContext(
&self.llcx,
alloc.bytes.as_ptr() as *const _,
alloc.bytes.len() as c_uint,
);
let data = [section, alloc];
let meta = llvm::LLVMMDNodeInContext(&self.llcx, data.as_ptr(), 2);
llvm::LLVMAddNamedMetadataOperand(
&self.llmod,
"wasm.custom_sections\0".as_ptr() as *const _,
meta,
);
}
} else {
base::set_link_section(g, &attrs);
}
if attrs.flags.contains(CodegenFnAttrFlags::USED) {
// This static will be stored in the llvm.used variable which is an array of i8*
let cast = llvm::LLVMConstPointerCast(g, &self.type_i8p());
&self.used_statics.borrow_mut().push(cast);
}
}
}
}

View File

@ -13,9 +13,11 @@
mod consts;
mod type_;
mod intrinsic;
mod statics;
pub use self::builder::BuilderMethods;
pub use self::backend::Backend;
pub use self::consts::ConstMethods;
pub use self::type_::{TypeMethods, BaseTypeMethods, DerivedTypeMethods};
pub use self::intrinsic::{IntrinsicMethods, BaseIntrinsicMethods, DerivedIntrinsicMethods};
pub use self::statics::StaticMethods;

View File

@ -0,0 +1,36 @@
// Copyright 2018 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.
use rustc::ty::layout::Align;
use rustc::hir::def_id::DefId;
use super::backend::Backend;
pub trait StaticMethods<'tcx>: Backend {
fn static_ptrcast(&self, val: Self::Value, ty: Self::Type) -> Self::Value;
fn static_bitcast(&self, val: Self::Value, ty: Self::Type) -> Self::Value;
fn static_addr_of_mut(
&self,
cv: Self::Value,
align: Align,
kind: Option<&str>,
) -> Self::Value;
fn static_addr_of(
&self,
cv: Self::Value,
align: Align,
kind: Option<&str>,
) -> Self::Value;
fn get_static(&self, def_id: DefId) -> Self::Value;
fn codegen_static(
&self,
def_id: DefId,
is_mutable: bool,
);
}

View File

@ -34,6 +34,7 @@
use interfaces::{
BuilderMethods, ConstMethods, BaseTypeMethods, DerivedTypeMethods, DerivedIntrinsicMethods,
StaticMethods,
};
use rustc::session::Session;
@ -853,7 +854,7 @@ fn codegen_msvc_try(
let tcx = cx.tcx;
let tydesc = match tcx.lang_items().msvc_try_filter() {
Some(did) => ::consts::get_static(cx, did),
Some(did) => cx.get_static(did),
None => bug!("msvc_try_filter not defined"),
};
let tok = catchpad.catch_pad(cs, &[tydesc, cx.const_i32(0), slot]);

View File

@ -12,11 +12,10 @@
use callee;
use context::CodegenCx;
use builder::Builder;
use consts;
use monomorphize;
use value::Value;
use interfaces::{BuilderMethods, ConstMethods, BaseTypeMethods, DerivedTypeMethods};
use interfaces::{BuilderMethods, ConstMethods, BaseTypeMethods, DerivedTypeMethods, StaticMethods};
use rustc::ty::{self, Ty};
use rustc::ty::layout::HasDataLayout;
@ -120,7 +119,7 @@ pub fn get_vtable(
let vtable_const = cx.const_struct(&components, false);
let align = cx.data_layout().pointer_align;
let vtable = consts::addr_of(cx, vtable_const, align, Some("vtable"));
let vtable = cx.static_addr_of(vtable_const, align, Some("vtable"));
debuginfo::create_vtable_metadata(cx, ty, vtable);

View File

@ -19,7 +19,6 @@
use callee;
use builder::{Builder, MemFlags};
use common::{self, IntPredicate};
use consts;
use meth;
use monomorphize;
use type_of::LayoutLlvmExt;
@ -28,6 +27,7 @@
use interfaces::{
BuilderMethods, ConstMethods, BaseTypeMethods, DerivedTypeMethods, DerivedIntrinsicMethods,
StaticMethods,
};
use syntax::symbol::Symbol;
@ -380,10 +380,11 @@ fn codegen_terminator(&mut self,
let index = self.codegen_operand(&mut bx, index).immediate();
let file_line_col = bx.cx().const_struct(&[filename, line, col], false);
let file_line_col = consts::addr_of(bx.cx(),
file_line_col,
align,
Some("panic_bounds_check_loc"));
let file_line_col = bx.cx().static_addr_of(
file_line_col,
align,
Some("panic_bounds_check_loc")
);
(lang_items::PanicBoundsCheckFnLangItem,
vec![file_line_col, index, len])
}
@ -395,10 +396,11 @@ fn codegen_terminator(&mut self,
&[msg_str, filename, line, col],
false
);
let msg_file_line_col = consts::addr_of(bx.cx(),
msg_file_line_col,
align,
Some("panic_loc"));
let msg_file_line_col = bx.cx().static_addr_of(
msg_file_line_col,
align,
Some("panic_loc")
);
(lang_items::PanicFnLangItem,
vec![msg_file_line_col])
}
@ -518,10 +520,11 @@ fn codegen_terminator(&mut self,
&[msg_str, filename, line, col],
false,
);
let msg_file_line_col = consts::addr_of(bx.cx,
msg_file_line_col,
align,
Some("panic_loc"));
let msg_file_line_col = bx.cx.static_addr_of(
msg_file_line_col,
align,
Some("panic_loc"),
);
// Obtain the panic entry point.
let def_id =

View File

@ -19,13 +19,12 @@
use rustc::ty::layout::{self, HasDataLayout, LayoutOf, Size};
use builder::Builder;
use common::{CodegenCx};
use consts;
use type_of::LayoutLlvmExt;
use type_::Type;
use syntax::ast::Mutability;
use syntax::source_map::Span;
use value::Value;
use interfaces::{BuilderMethods, ConstMethods, BaseTypeMethods, DerivedTypeMethods};
use interfaces::{BuilderMethods, ConstMethods, BaseTypeMethods, DerivedTypeMethods, StaticMethods};
use super::super::callee;
use super::FunctionCx;
@ -48,7 +47,7 @@ pub fn scalar_to_llvm(
if layout.value == layout::Pointer {
unsafe { llvm::LLVMConstIntToPtr(llval, llty) }
} else {
consts::bitcast(llval, llty)
cx.static_bitcast(llval, llty)
}
},
Scalar::Ptr(ptr) => {
@ -57,9 +56,9 @@ pub fn scalar_to_llvm(
Some(AllocType::Memory(alloc)) => {
let init = const_alloc_to_llvm(cx, alloc);
if alloc.mutability == Mutability::Mutable {
consts::addr_of_mut(cx, init, alloc.align, None)
cx.static_addr_of_mut(init, alloc.align, None)
} else {
consts::addr_of(cx, init, alloc.align, None)
cx.static_addr_of(init, alloc.align, None)
}
}
Some(AllocType::Function(fn_instance)) => {
@ -67,19 +66,19 @@ pub fn scalar_to_llvm(
}
Some(AllocType::Static(def_id)) => {
assert!(cx.tcx.is_static(def_id).is_some());
consts::get_static(cx, def_id)
cx.get_static(def_id)
}
None => bug!("missing allocation {:?}", ptr.alloc_id),
};
let llval = unsafe { llvm::LLVMConstInBoundsGEP(
consts::bitcast(base_addr, cx.type_i8p()),
cx.static_bitcast(base_addr, cx.type_i8p()),
&cx.const_usize(ptr.offset.bytes()),
1,
) };
if layout.value != layout::Pointer {
unsafe { llvm::LLVMConstPtrToInt(llval, llty) }
} else {
consts::bitcast(llval, llty)
cx.static_bitcast(llval, llty)
}
}
}

View File

@ -16,7 +16,6 @@
use base;
use builder::Builder;
use common::{CodegenCx, IntPredicate};
use consts;
use type_of::LayoutLlvmExt;
use value::Value;
use glue;
@ -24,6 +23,7 @@
use interfaces::{
BuilderMethods, ConstMethods, BaseTypeMethods, DerivedTypeMethods, DerivedIntrinsicMethods,
StaticMethods,
};
use super::{FunctionCx, LocalRef};
@ -66,14 +66,14 @@ pub fn from_const_alloc(
offset: Size,
) -> PlaceRef<'tcx, &'ll Value> {
let init = const_alloc_to_llvm(bx.cx(), alloc);
let base_addr = consts::addr_of(bx.cx(), init, layout.align, None);
let base_addr = bx.cx().static_addr_of(init, layout.align, None);
let llval = unsafe { LLVMConstInBoundsGEP(
consts::bitcast(base_addr, bx.cx().type_i8p()),
bx.cx().static_bitcast(base_addr, bx.cx().type_i8p()),
&bx.cx().const_usize(offset.bytes()),
1,
)};
let llval = consts::bitcast(llval, bx.cx().type_ptr_to(layout.llvm_type(bx.cx())));
let llval = bx.cx().static_bitcast(llval, bx.cx().type_ptr_to(layout.llvm_type(bx.cx())));
PlaceRef::new_sized(llval, layout, alloc.align)
}
@ -497,7 +497,7 @@ pub fn codegen_place(&mut self,
}
mir::Place::Static(box mir::Static { def_id, ty }) => {
let layout = cx.layout_of(self.monomorphize(&ty));
PlaceRef::new_sized(consts::get_static(cx, def_id), layout, layout.align)
PlaceRef::new_sized(cx.get_static(def_id), layout, layout.align)
},
mir::Place::Projection(box mir::Projection {
ref base,

View File

@ -20,7 +20,6 @@
use builder::Builder;
use callee;
use common::{self, IntPredicate, RealPredicate};
use consts;
use monomorphize;
use type_::Type;
use type_of::LayoutLlvmExt;
@ -841,7 +840,7 @@ fn cast_int_to_float(bx: &Builder<'_, 'll, '_>,
let max = bx.cx().const_uint_big(int_ty, MAX_F32_PLUS_HALF_ULP);
let overflow = bx.icmp(IntPredicate::IntUGE, x, max);
let infinity_bits = bx.cx().const_u32(ieee::Single::INFINITY.to_bits() as u32);
let infinity = consts::bitcast(infinity_bits, float_ty);
let infinity = bx.bitcast(infinity_bits, float_ty);
bx.select(overflow, infinity, bx.uitofp(x, float_ty))
} else {
if signed {
@ -922,7 +921,7 @@ fn cast_float_to_int(bx: &Builder<'_, 'll, '_>,
64 => bx.cx().const_u64(bits as u64),
n => bug!("unsupported float width {}", n),
};
consts::bitcast(bits_llval, float_ty)
bx.bitcast(bits_llval, float_ty)
};
let (f_min, f_max) = match bx.cx().float_width(float_ty) {
32 => compute_clamp_bounds_single(signed, int_ty),

View File

@ -17,7 +17,6 @@
use asm;
use attributes;
use base;
use consts;
use context::CodegenCx;
use declare;
use llvm;
@ -30,6 +29,7 @@
use rustc::ty::TypeFoldable;
use rustc::ty::layout::LayoutOf;
use std::fmt;
use interfaces::StaticMethods;
pub use rustc::mir::mono::MonoItem;
@ -54,7 +54,7 @@ fn define(&self, cx: &CodegenCx<'a, 'tcx>) {
bug!("Expected Def::Static for {:?}, found nothing", def_id)
}
};
consts::codegen_static(&cx, def_id, is_mutable);
cx.codegen_static(def_id, is_mutable);
}
MonoItem::GlobalAsm(node_id) => {
let item = cx.tcx.hir.expect_item(node_id);