Traitification of common.rs methods
This commit is contained in:
parent
3889c2dcfb
commit
8714e6bce6
25 changed files with 518 additions and 417 deletions
|
@ -11,7 +11,6 @@
|
||||||
use llvm::{self, AttributePlace};
|
use llvm::{self, AttributePlace};
|
||||||
use base;
|
use base;
|
||||||
use builder::{Builder, MemFlags};
|
use builder::{Builder, MemFlags};
|
||||||
use common::C_usize;
|
|
||||||
use context::CodegenCx;
|
use context::CodegenCx;
|
||||||
use mir::place::PlaceRef;
|
use mir::place::PlaceRef;
|
||||||
use mir::operand::OperandValue;
|
use mir::operand::OperandValue;
|
||||||
|
@ -19,7 +18,7 @@ use type_::Type;
|
||||||
use type_of::{LayoutLlvmExt, PointerKind};
|
use type_of::{LayoutLlvmExt, PointerKind};
|
||||||
use value::Value;
|
use value::Value;
|
||||||
|
|
||||||
use interfaces::BuilderMethods;
|
use interfaces::{BuilderMethods, CommonMethods};
|
||||||
|
|
||||||
use rustc_target::abi::{HasDataLayout, LayoutOf, Size, TyLayout, Abi as LayoutAbi};
|
use rustc_target::abi::{HasDataLayout, LayoutOf, Size, TyLayout, Abi as LayoutAbi};
|
||||||
use rustc::ty::{self, Ty};
|
use rustc::ty::{self, Ty};
|
||||||
|
@ -245,7 +244,7 @@ impl ArgTypeExt<'ll, 'tcx> for ArgType<'tcx, Ty<'tcx>> {
|
||||||
self.layout.align,
|
self.layout.align,
|
||||||
bx.pointercast(llscratch, Type::i8p(cx)),
|
bx.pointercast(llscratch, Type::i8p(cx)),
|
||||||
scratch_align,
|
scratch_align,
|
||||||
C_usize(cx, self.layout.size.bytes()),
|
CodegenCx::c_usize(cx, self.layout.size.bytes()),
|
||||||
MemFlags::empty());
|
MemFlags::empty());
|
||||||
|
|
||||||
bx.lifetime_end(llscratch, scratch_size);
|
bx.lifetime_end(llscratch, scratch_size);
|
||||||
|
|
|
@ -9,14 +9,14 @@
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use llvm;
|
use llvm;
|
||||||
use common::*;
|
use context::CodegenCx;
|
||||||
use type_::Type;
|
use type_::Type;
|
||||||
use type_of::LayoutLlvmExt;
|
use type_of::LayoutLlvmExt;
|
||||||
use builder::Builder;
|
use builder::Builder;
|
||||||
use value::Value;
|
use value::Value;
|
||||||
|
|
||||||
use rustc::hir;
|
use rustc::hir;
|
||||||
use interfaces::BuilderMethods;
|
use interfaces::{BuilderMethods, CommonMethods};
|
||||||
|
|
||||||
use mir::place::PlaceRef;
|
use mir::place::PlaceRef;
|
||||||
use mir::operand::OperandValue;
|
use mir::operand::OperandValue;
|
||||||
|
@ -111,7 +111,7 @@ pub fn codegen_inline_asm(
|
||||||
let kind = llvm::LLVMGetMDKindIDInContext(bx.cx.llcx,
|
let kind = llvm::LLVMGetMDKindIDInContext(bx.cx.llcx,
|
||||||
key.as_ptr() as *const c_char, key.len() as c_uint);
|
key.as_ptr() as *const c_char, key.len() as c_uint);
|
||||||
|
|
||||||
let val: &'ll Value = C_i32(bx.cx, ia.ctxt.outer().as_u32() as i32);
|
let val: &'ll Value = CodegenCx::c_i32(bx.cx, ia.ctxt.outer().as_u32() as i32);
|
||||||
|
|
||||||
llvm::LLVMSetMetadata(r, kind,
|
llvm::LLVMSetMetadata(r, kind,
|
||||||
llvm::LLVMMDNodeInContext(bx.cx.llcx, &val, 1));
|
llvm::LLVMMDNodeInContext(bx.cx.llcx, &val, 1));
|
||||||
|
|
|
@ -740,7 +740,7 @@ fn link_natively(sess: &Session,
|
||||||
// with some thread pool working in the background. It seems that no one
|
// with some thread pool working in the background. It seems that no one
|
||||||
// currently knows a fix for this so in the meantime we're left with this...
|
// currently knows a fix for this so in the meantime we're left with this...
|
||||||
info!("{:?}", &cmd);
|
info!("{:?}", &cmd);
|
||||||
let retry_on_segfault = env::var("RUSTC_RETRY_LINKER_ON_SEGFAULT").is_ok();
|
let retry_on_segfault = env::var("RUSTc_RETRY_LINKER_ON_SEGFAULT").is_ok();
|
||||||
let mut prog;
|
let mut prog;
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
loop {
|
loop {
|
||||||
|
|
|
@ -45,8 +45,8 @@ use syntax::ext::hygiene::Mark;
|
||||||
use syntax_pos::MultiSpan;
|
use syntax_pos::MultiSpan;
|
||||||
use syntax_pos::symbol::Symbol;
|
use syntax_pos::symbol::Symbol;
|
||||||
use type_::Type;
|
use type_::Type;
|
||||||
use context::{is_pie_binary, get_reloc_model};
|
use context::{is_pie_binary, get_reloc_model, CodegenCx};
|
||||||
use common::{C_bytes_in_context, val_ty};
|
use interfaces::CommonMethods;
|
||||||
use jobserver::{Client, Acquired};
|
use jobserver::{Client, Acquired};
|
||||||
use rustc_demangle;
|
use rustc_demangle;
|
||||||
|
|
||||||
|
@ -884,10 +884,10 @@ unsafe fn embed_bitcode(cgcx: &CodegenContext,
|
||||||
llcx: &llvm::Context,
|
llcx: &llvm::Context,
|
||||||
llmod: &llvm::Module,
|
llmod: &llvm::Module,
|
||||||
bitcode: Option<&[u8]>) {
|
bitcode: Option<&[u8]>) {
|
||||||
let llconst = C_bytes_in_context(llcx, bitcode.unwrap_or(&[]));
|
let llconst = CodegenCx::c_bytes_in_context(llcx, bitcode.unwrap_or(&[]));
|
||||||
let llglobal = llvm::LLVMAddGlobal(
|
let llglobal = llvm::LLVMAddGlobal(
|
||||||
llmod,
|
llmod,
|
||||||
val_ty(llconst),
|
CodegenCx::val_ty(llconst),
|
||||||
"rustc.embedded.module\0".as_ptr() as *const _,
|
"rustc.embedded.module\0".as_ptr() as *const _,
|
||||||
);
|
);
|
||||||
llvm::LLVMSetInitializer(llglobal, llconst);
|
llvm::LLVMSetInitializer(llglobal, llconst);
|
||||||
|
@ -904,10 +904,10 @@ unsafe fn embed_bitcode(cgcx: &CodegenContext,
|
||||||
llvm::LLVMRustSetLinkage(llglobal, llvm::Linkage::PrivateLinkage);
|
llvm::LLVMRustSetLinkage(llglobal, llvm::Linkage::PrivateLinkage);
|
||||||
llvm::LLVMSetGlobalConstant(llglobal, llvm::True);
|
llvm::LLVMSetGlobalConstant(llglobal, llvm::True);
|
||||||
|
|
||||||
let llconst = C_bytes_in_context(llcx, &[]);
|
let llconst = CodegenCx::c_bytes_in_context(llcx, &[]);
|
||||||
let llglobal = llvm::LLVMAddGlobal(
|
let llglobal = llvm::LLVMAddGlobal(
|
||||||
llmod,
|
llmod,
|
||||||
val_ty(llconst),
|
CodegenCx::val_ty(llconst),
|
||||||
"rustc.embedded.cmdline\0".as_ptr() as *const _,
|
"rustc.embedded.cmdline\0".as_ptr() as *const _,
|
||||||
);
|
);
|
||||||
llvm::LLVMSetInitializer(llglobal, llconst);
|
llvm::LLVMSetInitializer(llglobal, llconst);
|
||||||
|
|
|
@ -53,9 +53,8 @@ use mir::place::PlaceRef;
|
||||||
use attributes;
|
use attributes;
|
||||||
use builder::{Builder, MemFlags};
|
use builder::{Builder, MemFlags};
|
||||||
use callee;
|
use callee;
|
||||||
use common::{C_bool, C_bytes_in_context, C_usize};
|
|
||||||
use rustc_mir::monomorphize::item::DefPathBasedNames;
|
use rustc_mir::monomorphize::item::DefPathBasedNames;
|
||||||
use common::{C_struct_in_context, C_array, val_ty, IntPredicate, RealPredicate};
|
use common::{IntPredicate, RealPredicate};
|
||||||
use consts;
|
use consts;
|
||||||
use context::CodegenCx;
|
use context::CodegenCx;
|
||||||
use debuginfo;
|
use debuginfo;
|
||||||
|
@ -75,7 +74,7 @@ use rustc_data_structures::small_c_str::SmallCStr;
|
||||||
use rustc_data_structures::sync::Lrc;
|
use rustc_data_structures::sync::Lrc;
|
||||||
use rustc_data_structures::indexed_vec::Idx;
|
use rustc_data_structures::indexed_vec::Idx;
|
||||||
|
|
||||||
use interfaces::BuilderMethods;
|
use interfaces::{BuilderMethods, CommonMethods};
|
||||||
|
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
|
@ -199,7 +198,7 @@ pub fn unsized_info(
|
||||||
let (source, target) = cx.tcx.struct_lockstep_tails(source, target);
|
let (source, target) = cx.tcx.struct_lockstep_tails(source, target);
|
||||||
match (&source.sty, &target.sty) {
|
match (&source.sty, &target.sty) {
|
||||||
(&ty::Array(_, len), &ty::Slice(_)) => {
|
(&ty::Array(_, len), &ty::Slice(_)) => {
|
||||||
C_usize(cx, len.unwrap_usize(cx.tcx))
|
CodegenCx::c_usize(cx, len.unwrap_usize(cx.tcx))
|
||||||
}
|
}
|
||||||
(&ty::Dynamic(..), &ty::Dynamic(..)) => {
|
(&ty::Dynamic(..), &ty::Dynamic(..)) => {
|
||||||
// For now, upcasts are limited to changes in marker
|
// For now, upcasts are limited to changes in marker
|
||||||
|
@ -351,8 +350,8 @@ fn cast_shift_rhs<'ll, F, G>(op: hir::BinOpKind,
|
||||||
{
|
{
|
||||||
// Shifts may have any size int on the rhs
|
// Shifts may have any size int on the rhs
|
||||||
if op.is_shift() {
|
if op.is_shift() {
|
||||||
let mut rhs_llty = val_ty(rhs);
|
let mut rhs_llty = CodegenCx::val_ty(rhs);
|
||||||
let mut lhs_llty = val_ty(lhs);
|
let mut lhs_llty = CodegenCx::val_ty(lhs);
|
||||||
if rhs_llty.kind() == TypeKind::Vector {
|
if rhs_llty.kind() == TypeKind::Vector {
|
||||||
rhs_llty = rhs_llty.element_type()
|
rhs_llty = rhs_llty.element_type()
|
||||||
}
|
}
|
||||||
|
@ -393,7 +392,7 @@ pub fn from_immediate<'a, 'll: 'a, 'tcx: 'll>(
|
||||||
bx: &Builder<'_ ,'ll, '_, &'ll Value>,
|
bx: &Builder<'_ ,'ll, '_, &'ll Value>,
|
||||||
val: &'ll Value
|
val: &'ll Value
|
||||||
) -> &'ll Value {
|
) -> &'ll Value {
|
||||||
if val_ty(val) == Type::i1(bx.cx()) {
|
if CodegenCx::val_ty(val) == Type::i1(bx.cx()) {
|
||||||
bx.zext(val, Type::i8(bx.cx()))
|
bx.zext(val, Type::i8(bx.cx()))
|
||||||
} else {
|
} else {
|
||||||
val
|
val
|
||||||
|
@ -434,7 +433,7 @@ pub fn call_memcpy<'a, 'll: 'a, 'tcx: 'll>(
|
||||||
if flags.contains(MemFlags::NONTEMPORAL) {
|
if flags.contains(MemFlags::NONTEMPORAL) {
|
||||||
// HACK(nox): This is inefficient but there is no nontemporal memcpy.
|
// HACK(nox): This is inefficient but there is no nontemporal memcpy.
|
||||||
let val = bx.load(src, src_align);
|
let val = bx.load(src, src_align);
|
||||||
let ptr = bx.pointercast(dst, val_ty(val).ptr_to());
|
let ptr = bx.pointercast(dst, CodegenCx::val_ty(val).ptr_to());
|
||||||
bx.store_with_flags(val, ptr, dst_align, flags);
|
bx.store_with_flags(val, ptr, dst_align, flags);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -460,7 +459,7 @@ pub fn memcpy_ty<'a, 'll: 'a, 'tcx: 'll>(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
call_memcpy(bx, dst, dst_align, src, src_align, C_usize(bx.cx(), size), flags);
|
call_memcpy(bx, dst, dst_align, src, src_align, CodegenCx::c_usize(bx.cx(), size), flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn call_memset(
|
pub fn call_memset(
|
||||||
|
@ -474,7 +473,7 @@ pub fn call_memset(
|
||||||
let ptr_width = &bx.cx.sess().target.target.target_pointer_width;
|
let ptr_width = &bx.cx.sess().target.target.target_pointer_width;
|
||||||
let intrinsic_key = format!("llvm.memset.p0i8.i{}", ptr_width);
|
let intrinsic_key = format!("llvm.memset.p0i8.i{}", ptr_width);
|
||||||
let llintrinsicfn = bx.cx.get_intrinsic(&intrinsic_key);
|
let llintrinsicfn = bx.cx.get_intrinsic(&intrinsic_key);
|
||||||
let volatile = C_bool(bx.cx, volatile);
|
let volatile = CodegenCx::c_bool(bx.cx, volatile);
|
||||||
bx.call(llintrinsicfn, &[ptr, fill_byte, size, align, volatile], None)
|
bx.call(llintrinsicfn, &[ptr, fill_byte, size, align, volatile], None)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -649,12 +648,12 @@ fn write_metadata<'a, 'gcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>,
|
||||||
DeflateEncoder::new(&mut compressed, Compression::fast())
|
DeflateEncoder::new(&mut compressed, Compression::fast())
|
||||||
.write_all(&metadata.raw_data).unwrap();
|
.write_all(&metadata.raw_data).unwrap();
|
||||||
|
|
||||||
let llmeta = C_bytes_in_context(metadata_llcx, &compressed);
|
let llmeta = CodegenCx::c_bytes_in_context(metadata_llcx, &compressed);
|
||||||
let llconst = C_struct_in_context(metadata_llcx, &[llmeta], false);
|
let llconst = CodegenCx::c_struct_in_context(metadata_llcx, &[llmeta], false);
|
||||||
let name = exported_symbols::metadata_symbol_name(tcx);
|
let name = exported_symbols::metadata_symbol_name(tcx);
|
||||||
let buf = CString::new(name).unwrap();
|
let buf = CString::new(name).unwrap();
|
||||||
let llglobal = unsafe {
|
let llglobal = unsafe {
|
||||||
llvm::LLVMAddGlobal(metadata_llmod, val_ty(llconst), buf.as_ptr())
|
llvm::LLVMAddGlobal(metadata_llmod, CodegenCx::val_ty(llconst), buf.as_ptr())
|
||||||
};
|
};
|
||||||
unsafe {
|
unsafe {
|
||||||
llvm::LLVMSetInitializer(llglobal, llconst);
|
llvm::LLVMSetInitializer(llglobal, llconst);
|
||||||
|
@ -1140,7 +1139,7 @@ fn compile_codegen_unit<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
// Run replace-all-uses-with for statics that need it
|
// Run replace-all-uses-with for statics that need it
|
||||||
for &(old_g, new_g) in cx.statics_to_rauw.borrow().iter() {
|
for &(old_g, new_g) in cx.statics_to_rauw.borrow().iter() {
|
||||||
unsafe {
|
unsafe {
|
||||||
let bitcast = llvm::LLVMConstPointerCast(new_g, val_ty(old_g));
|
let bitcast = llvm::LLVMConstPointerCast(new_g, CodegenCx::val_ty(old_g));
|
||||||
llvm::LLVMReplaceAllUsesWith(old_g, bitcast);
|
llvm::LLVMReplaceAllUsesWith(old_g, bitcast);
|
||||||
llvm::LLVMDeleteGlobal(old_g);
|
llvm::LLVMDeleteGlobal(old_g);
|
||||||
}
|
}
|
||||||
|
@ -1151,11 +1150,11 @@ fn compile_codegen_unit<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
if !cx.used_statics.borrow().is_empty() {
|
if !cx.used_statics.borrow().is_empty() {
|
||||||
let name = const_cstr!("llvm.used");
|
let name = const_cstr!("llvm.used");
|
||||||
let section = const_cstr!("llvm.metadata");
|
let section = const_cstr!("llvm.metadata");
|
||||||
let array = C_array(Type::i8(&cx).ptr_to(), &*cx.used_statics.borrow());
|
let array = CodegenCx::c_array(Type::i8(&cx).ptr_to(), &*cx.used_statics.borrow());
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let g = llvm::LLVMAddGlobal(cx.llmod,
|
let g = llvm::LLVMAddGlobal(cx.llmod,
|
||||||
val_ty(array),
|
CodegenCx::val_ty(array),
|
||||||
name.as_ptr());
|
name.as_ptr());
|
||||||
llvm::LLVMSetInitializer(g, array);
|
llvm::LLVMSetInitializer(g, array);
|
||||||
llvm::LLVMRustSetLinkage(g, llvm::Linkage::AppendingLinkage);
|
llvm::LLVMRustSetLinkage(g, llvm::Linkage::AppendingLinkage);
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
use llvm::{AtomicRmwBinOp, AtomicOrdering, SynchronizationScope, AsmDialect};
|
use llvm::{AtomicRmwBinOp, AtomicOrdering, SynchronizationScope, AsmDialect};
|
||||||
use llvm::{self, False, OperandBundleDef, BasicBlock};
|
use llvm::{self, False, OperandBundleDef, BasicBlock};
|
||||||
use common::{self, *};
|
use common::{self, *};
|
||||||
|
use context::CodegenCx;
|
||||||
use type_;
|
use type_;
|
||||||
use value::Value;
|
use value::Value;
|
||||||
use libc::{c_uint, c_char};
|
use libc::{c_uint, c_char};
|
||||||
|
@ -18,7 +19,7 @@ use rustc::ty::TyCtxt;
|
||||||
use rustc::ty::layout::{Align, Size};
|
use rustc::ty::layout::{Align, Size};
|
||||||
use rustc::session::{config, Session};
|
use rustc::session::{config, Session};
|
||||||
use rustc_data_structures::small_c_str::SmallCStr;
|
use rustc_data_structures::small_c_str::SmallCStr;
|
||||||
use interfaces::{BuilderMethods, Backend};
|
use interfaces::{BuilderMethods, Backend, CommonMethods};
|
||||||
use syntax;
|
use syntax;
|
||||||
|
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
@ -59,6 +60,7 @@ impl Backend for Builder<'a, 'll, 'tcx> {
|
||||||
type Value = &'ll Value;
|
type Value = &'ll Value;
|
||||||
type BasicBlock = &'ll BasicBlock;
|
type BasicBlock = &'ll BasicBlock;
|
||||||
type Type = &'ll type_::Type;
|
type Type = &'ll type_::Type;
|
||||||
|
type Context = &'ll llvm::Context;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BuilderMethods<'a, 'll, 'tcx> for Builder<'a, 'll, 'tcx> {
|
impl BuilderMethods<'a, 'll, 'tcx> for Builder<'a, 'll, 'tcx> {
|
||||||
|
@ -525,10 +527,10 @@ impl BuilderMethods<'a, 'll, 'tcx> for Builder<'a, 'll, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let llty = val_ty(load);
|
let llty = CodegenCx::val_ty(load);
|
||||||
let v = [
|
let v = [
|
||||||
C_uint_big(llty, range.start),
|
CodegenCx::c_uint_big(llty, range.start),
|
||||||
C_uint_big(llty, range.end)
|
CodegenCx::c_uint_big(llty, range.end)
|
||||||
];
|
];
|
||||||
|
|
||||||
llvm::LLVMSetMetadata(load, llvm::MD_range as c_uint,
|
llvm::LLVMSetMetadata(load, llvm::MD_range as c_uint,
|
||||||
|
@ -575,7 +577,7 @@ impl BuilderMethods<'a, 'll, 'tcx> for Builder<'a, 'll, 'tcx> {
|
||||||
// *always* point to a metadata value of the integer 1.
|
// *always* point to a metadata value of the integer 1.
|
||||||
//
|
//
|
||||||
// [1]: http://llvm.org/docs/LangRef.html#store-instruction
|
// [1]: http://llvm.org/docs/LangRef.html#store-instruction
|
||||||
let one = C_i32(self.cx, 1);
|
let one = CodegenCx::c_i32(self.cx, 1);
|
||||||
let node = llvm::LLVMMDNodeInContext(self.cx.llcx, &one, 1);
|
let node = llvm::LLVMMDNodeInContext(self.cx.llcx, &one, 1);
|
||||||
llvm::LLVMSetMetadata(store, llvm::MD_nontemporal as c_uint, node);
|
llvm::LLVMSetMetadata(store, llvm::MD_nontemporal as c_uint, node);
|
||||||
}
|
}
|
||||||
|
@ -758,7 +760,7 @@ impl BuilderMethods<'a, 'll, 'tcx> for Builder<'a, 'll, 'tcx> {
|
||||||
|
|
||||||
let argtys = inputs.iter().map(|v| {
|
let argtys = inputs.iter().map(|v| {
|
||||||
debug!("Asm Input Type: {:?}", *v);
|
debug!("Asm Input Type: {:?}", *v);
|
||||||
val_ty(*v)
|
CodegenCx::val_ty(*v)
|
||||||
}).collect::<Vec<_>>();
|
}).collect::<Vec<_>>();
|
||||||
|
|
||||||
debug!("Asm Output Type: {:?}", output);
|
debug!("Asm Output Type: {:?}", output);
|
||||||
|
@ -857,11 +859,11 @@ impl BuilderMethods<'a, 'll, 'tcx> for Builder<'a, 'll, 'tcx> {
|
||||||
|
|
||||||
fn vector_splat(&self, num_elts: usize, elt: &'ll Value) -> &'ll Value {
|
fn vector_splat(&self, num_elts: usize, elt: &'ll Value) -> &'ll Value {
|
||||||
unsafe {
|
unsafe {
|
||||||
let elt_ty = val_ty(elt);
|
let elt_ty = CodegenCx::val_ty(elt);
|
||||||
let undef = llvm::LLVMGetUndef(type_::Type::vector(elt_ty, num_elts as u64));
|
let undef = llvm::LLVMGetUndef(type_::Type::vector(elt_ty, num_elts as u64));
|
||||||
let vec = self.insert_element(undef, elt, C_i32(self.cx, 0));
|
let vec = self.insert_element(undef, elt, CodegenCx::c_i32(self.cx, 0));
|
||||||
let vec_i32_ty = type_::Type::vector(type_::Type::i32(self.cx), num_elts as u64);
|
let vec_i32_ty = type_::Type::vector(type_::Type::i32(self.cx), num_elts as u64);
|
||||||
self.shuffle_vector(vec, undef, C_null(vec_i32_ty))
|
self.shuffle_vector(vec, undef, CodegenCx::c_null(vec_i32_ty))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1137,8 +1139,8 @@ impl BuilderMethods<'a, 'll, 'tcx> for Builder<'a, 'll, 'tcx> {
|
||||||
fn check_store<'b>(&self,
|
fn check_store<'b>(&self,
|
||||||
val: &'ll Value,
|
val: &'ll Value,
|
||||||
ptr: &'ll Value) -> &'ll Value {
|
ptr: &'ll Value) -> &'ll Value {
|
||||||
let dest_ptr_ty = val_ty(ptr);
|
let dest_ptr_ty = CodegenCx::val_ty(ptr);
|
||||||
let stored_ty = val_ty(val);
|
let stored_ty = CodegenCx::val_ty(val);
|
||||||
let stored_ptr_ty = stored_ty.ptr_to();
|
let stored_ptr_ty = stored_ty.ptr_to();
|
||||||
|
|
||||||
assert_eq!(dest_ptr_ty.kind(), llvm::TypeKind::Pointer);
|
assert_eq!(dest_ptr_ty.kind(), llvm::TypeKind::Pointer);
|
||||||
|
@ -1158,7 +1160,7 @@ impl BuilderMethods<'a, 'll, 'tcx> for Builder<'a, 'll, 'tcx> {
|
||||||
typ: &str,
|
typ: &str,
|
||||||
llfn: &'ll Value,
|
llfn: &'ll Value,
|
||||||
args: &'b [&'ll Value]) -> Cow<'b, [&'ll Value]> {
|
args: &'b [&'ll Value]) -> Cow<'b, [&'ll Value]> {
|
||||||
let mut fn_ty = val_ty(llfn);
|
let mut fn_ty = CodegenCx::val_ty(llfn);
|
||||||
// Strip off pointers
|
// Strip off pointers
|
||||||
while fn_ty.kind() == llvm::TypeKind::Pointer {
|
while fn_ty.kind() == llvm::TypeKind::Pointer {
|
||||||
fn_ty = fn_ty.element_type();
|
fn_ty = fn_ty.element_type();
|
||||||
|
@ -1170,7 +1172,7 @@ impl BuilderMethods<'a, 'll, 'tcx> for Builder<'a, 'll, 'tcx> {
|
||||||
let param_tys = fn_ty.func_params();
|
let param_tys = fn_ty.func_params();
|
||||||
|
|
||||||
let all_args_match = param_tys.iter()
|
let all_args_match = param_tys.iter()
|
||||||
.zip(args.iter().map(|&v| val_ty(v)))
|
.zip(args.iter().map(|&v| CodegenCx::val_ty(v)))
|
||||||
.all(|(expected_ty, actual_ty)| *expected_ty == actual_ty);
|
.all(|(expected_ty, actual_ty)| *expected_ty == actual_ty);
|
||||||
|
|
||||||
if all_args_match {
|
if all_args_match {
|
||||||
|
@ -1181,7 +1183,7 @@ impl BuilderMethods<'a, 'll, 'tcx> for Builder<'a, 'll, 'tcx> {
|
||||||
.zip(args.iter())
|
.zip(args.iter())
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(|(i, (expected_ty, &actual_val))| {
|
.map(|(i, (expected_ty, &actual_val))| {
|
||||||
let actual_ty = val_ty(actual_val);
|
let actual_ty = CodegenCx::val_ty(actual_val);
|
||||||
if expected_ty != actual_ty {
|
if expected_ty != actual_ty {
|
||||||
debug!("Type mismatch in function call of {:?}. \
|
debug!("Type mismatch in function call of {:?}. \
|
||||||
Expected {:?} for param {}, got {:?}; injecting bitcast",
|
Expected {:?} for param {}, got {:?}; injecting bitcast",
|
||||||
|
@ -1225,7 +1227,7 @@ impl BuilderMethods<'a, 'll, 'tcx> for Builder<'a, 'll, 'tcx> {
|
||||||
let lifetime_intrinsic = self.cx.get_intrinsic(intrinsic);
|
let lifetime_intrinsic = self.cx.get_intrinsic(intrinsic);
|
||||||
|
|
||||||
let ptr = self.pointercast(ptr, type_::Type::i8p(self.cx));
|
let ptr = self.pointercast(ptr, type_::Type::i8p(self.cx));
|
||||||
self.call(lifetime_intrinsic, &[C_u64(self.cx, size), ptr], None);
|
self.call(lifetime_intrinsic, &[CodegenCx::c_u64(self.cx, size), ptr], None);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call(&self, llfn: &'ll Value, args: &[&'ll Value],
|
fn call(&self, llfn: &'ll Value, args: &[&'ll Value],
|
||||||
|
|
|
@ -15,13 +15,14 @@
|
||||||
//! closure.
|
//! closure.
|
||||||
|
|
||||||
use attributes;
|
use attributes;
|
||||||
use common::{self, CodegenCx};
|
use common::{CodegenCx};
|
||||||
use consts;
|
use consts;
|
||||||
use declare;
|
use declare;
|
||||||
use llvm;
|
use llvm;
|
||||||
use monomorphize::Instance;
|
use monomorphize::Instance;
|
||||||
use type_of::LayoutLlvmExt;
|
use type_of::LayoutLlvmExt;
|
||||||
use value::Value;
|
use value::Value;
|
||||||
|
use interfaces::CommonMethods;
|
||||||
|
|
||||||
use rustc::hir::def_id::DefId;
|
use rustc::hir::def_id::DefId;
|
||||||
use rustc::ty::{self, TypeFoldable};
|
use rustc::ty::{self, TypeFoldable};
|
||||||
|
@ -83,7 +84,7 @@ pub fn get_fn(
|
||||||
// This can occur on either a crate-local or crate-external
|
// This can occur on either a crate-local or crate-external
|
||||||
// reference. It also occurs when testing libcore and in some
|
// reference. It also occurs when testing libcore and in some
|
||||||
// other weird situations. Annoying.
|
// other weird situations. Annoying.
|
||||||
if common::val_ty(llfn) != llptrty {
|
if CodegenCx::val_ty(llfn) != llptrty {
|
||||||
debug!("get_fn: casting {:?} to {:?}", llfn, llptrty);
|
debug!("get_fn: casting {:?} to {:?}", llfn, llptrty);
|
||||||
consts::ptrcast(llfn, llptrty)
|
consts::ptrcast(llfn, llptrty)
|
||||||
} else {
|
} else {
|
||||||
|
@ -92,7 +93,7 @@ pub fn get_fn(
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let llfn = declare::declare_fn(cx, &sym, sig);
|
let llfn = declare::declare_fn(cx, &sym, sig);
|
||||||
assert_eq!(common::val_ty(llfn), llptrty);
|
assert_eq!(CodegenCx::val_ty(llfn), llptrty);
|
||||||
debug!("get_fn: not casting pointer!");
|
debug!("get_fn: not casting pointer!");
|
||||||
|
|
||||||
if instance.def.is_inline(tcx) {
|
if instance.def.is_inline(tcx) {
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
//! Code that is useful in various codegen modules.
|
//! Code that is useful in various codegen modules.
|
||||||
|
|
||||||
use llvm::{self, TypeKind};
|
use llvm::{self, TypeKind};
|
||||||
use llvm::{True, False, Bool};
|
use llvm::{True, False, Bool, BasicBlock};
|
||||||
use rustc::hir::def_id::DefId;
|
use rustc::hir::def_id::DefId;
|
||||||
use rustc::middle::lang_items::LangItem;
|
use rustc::middle::lang_items::LangItem;
|
||||||
use abi;
|
use abi;
|
||||||
|
@ -24,6 +24,7 @@ use declare;
|
||||||
use type_::Type;
|
use type_::Type;
|
||||||
use type_of::LayoutLlvmExt;
|
use type_of::LayoutLlvmExt;
|
||||||
use value::Value;
|
use value::Value;
|
||||||
|
use interfaces::{Backend, CommonMethods};
|
||||||
|
|
||||||
use rustc::ty::{self, Ty, TyCtxt};
|
use rustc::ty::{self, Ty, TyCtxt};
|
||||||
use rustc::ty::layout::{HasDataLayout, LayoutOf};
|
use rustc::ty::layout::{HasDataLayout, LayoutOf};
|
||||||
|
@ -192,225 +193,241 @@ impl Funclet<'ll> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn val_ty(v: &'ll Value) -> &'ll Type {
|
impl Backend for CodegenCx<'ll, 'tcx, &'ll Value> {
|
||||||
unsafe {
|
type Value = &'ll Value;
|
||||||
llvm::LLVMTypeOf(v)
|
type BasicBlock = &'ll BasicBlock;
|
||||||
}
|
type Type = &'ll Type;
|
||||||
|
type Context = &'ll llvm::Context;
|
||||||
}
|
}
|
||||||
|
|
||||||
// LLVM constant constructors.
|
impl<'ll, 'tcx : 'll> CommonMethods for CodegenCx<'ll, 'tcx, &'ll Value> {
|
||||||
pub fn C_null(t: &'ll Type) -> &'ll Value {
|
fn val_ty(v: &'ll Value) -> &'ll Type {
|
||||||
unsafe {
|
unsafe {
|
||||||
llvm::LLVMConstNull(t)
|
llvm::LLVMTypeOf(v)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
pub fn C_undef(t: &'ll Type) -> &'ll Value {
|
|
||||||
unsafe {
|
|
||||||
llvm::LLVMGetUndef(t)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn C_int(t: &'ll Type, i: i64) -> &'ll Value {
|
|
||||||
unsafe {
|
|
||||||
llvm::LLVMConstInt(t, i as u64, True)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn C_uint(t: &'ll Type, i: u64) -> &'ll Value {
|
|
||||||
unsafe {
|
|
||||||
llvm::LLVMConstInt(t, i, False)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn C_uint_big(t: &'ll Type, u: u128) -> &'ll Value {
|
|
||||||
unsafe {
|
|
||||||
let words = [u as u64, (u >> 64) as u64];
|
|
||||||
llvm::LLVMConstIntOfArbitraryPrecision(t, 2, words.as_ptr())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn C_bool(cx: &CodegenCx<'ll, '_>, val: bool) -> &'ll Value {
|
|
||||||
C_uint(Type::i1(cx), val as u64)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn C_i32(cx: &CodegenCx<'ll, '_>, i: i32) -> &'ll Value {
|
|
||||||
C_int(Type::i32(cx), i as i64)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn C_u32(cx: &CodegenCx<'ll, '_>, i: u32) -> &'ll Value {
|
|
||||||
C_uint(Type::i32(cx), i as u64)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn C_u64(cx: &CodegenCx<'ll, '_>, i: u64) -> &'ll Value {
|
|
||||||
C_uint(Type::i64(cx), i)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn C_usize(cx: &CodegenCx<'ll, '_>, i: u64) -> &'ll Value {
|
|
||||||
let bit_size = cx.data_layout().pointer_size.bits();
|
|
||||||
if bit_size < 64 {
|
|
||||||
// make sure it doesn't overflow
|
|
||||||
assert!(i < (1<<bit_size));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
C_uint(cx.isize_ty, i)
|
// LLVM constant constructors.
|
||||||
}
|
fn c_null(t: &'ll Type) -> &'ll Value {
|
||||||
|
unsafe {
|
||||||
|
llvm::LLVMConstNull(t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn C_u8(cx: &CodegenCx<'ll, '_>, i: u8) -> &'ll Value {
|
fn c_undef(t: &'ll Type) -> &'ll Value {
|
||||||
C_uint(Type::i8(cx), i as u64)
|
unsafe {
|
||||||
}
|
llvm::LLVMGetUndef(t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn c_int(t: &'ll Type, i: i64) -> &'ll Value {
|
||||||
|
unsafe {
|
||||||
|
llvm::LLVMConstInt(t, i as u64, True)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// This is a 'c-like' raw string, which differs from
|
fn c_uint(t: &'ll Type, i: u64) -> &'ll Value {
|
||||||
// our boxed-and-length-annotated strings.
|
unsafe {
|
||||||
pub fn C_cstr(
|
llvm::LLVMConstInt(t, i, False)
|
||||||
cx: &CodegenCx<'ll, '_>,
|
}
|
||||||
s: LocalInternedString,
|
}
|
||||||
null_terminated: bool,
|
|
||||||
) -> &'ll Value {
|
fn c_uint_big(t: &'ll Type, u: u128) -> &'ll Value {
|
||||||
unsafe {
|
unsafe {
|
||||||
if let Some(&llval) = cx.const_cstr_cache.borrow().get(&s) {
|
let words = [u as u64, (u >> 64) as u64];
|
||||||
return llval;
|
llvm::LLVMConstIntOfArbitraryPrecision(t, 2, words.as_ptr())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn c_bool(&self, val: bool) -> &'ll Value {
|
||||||
|
Self::c_uint(Type::i1(&self), val as u64)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn c_i32(&self, i: i32) -> &'ll Value {
|
||||||
|
Self::c_int(Type::i32(&self), i as i64)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn c_u32(&self, i: u32) -> &'ll Value {
|
||||||
|
Self::c_uint(Type::i32(&self), i as u64)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn c_u64(&self, i: u64) -> &'ll Value {
|
||||||
|
Self::c_uint(Type::i64(&self), i)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn c_usize(&self, i: u64) -> &'ll Value {
|
||||||
|
let bit_size = self.data_layout().pointer_size.bits();
|
||||||
|
if bit_size < 64 {
|
||||||
|
// make sure it doesn't overflow
|
||||||
|
assert!(i < (1<<bit_size));
|
||||||
}
|
}
|
||||||
|
|
||||||
let sc = llvm::LLVMConstStringInContext(cx.llcx,
|
Self::c_uint(&self.isize_ty, i)
|
||||||
s.as_ptr() as *const c_char,
|
|
||||||
s.len() as c_uint,
|
|
||||||
!null_terminated as Bool);
|
|
||||||
let sym = cx.generate_local_symbol_name("str");
|
|
||||||
let g = declare::define_global(cx, &sym[..], val_ty(sc)).unwrap_or_else(||{
|
|
||||||
bug!("symbol `{}` is already defined", sym);
|
|
||||||
});
|
|
||||||
llvm::LLVMSetInitializer(g, sc);
|
|
||||||
llvm::LLVMSetGlobalConstant(g, True);
|
|
||||||
llvm::LLVMRustSetLinkage(g, llvm::Linkage::InternalLinkage);
|
|
||||||
|
|
||||||
cx.const_cstr_cache.borrow_mut().insert(s, g);
|
|
||||||
g
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// NB: Do not use `do_spill_noroot` to make this into a constant string, or
|
fn c_u8(&self, i: u8) -> &'ll Value {
|
||||||
// you will be kicked off fast isel. See issue #4352 for an example of this.
|
Self::c_uint(Type::i8(&self), i as u64)
|
||||||
pub fn C_str_slice(cx: &CodegenCx<'ll, '_>, s: LocalInternedString) -> &'ll Value {
|
|
||||||
let len = s.len();
|
|
||||||
let cs = consts::ptrcast(C_cstr(cx, s, false),
|
|
||||||
cx.layout_of(cx.tcx.mk_str()).llvm_type(cx).ptr_to());
|
|
||||||
C_fat_ptr(cx, cs, C_usize(cx, len as u64))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn C_fat_ptr(cx: &CodegenCx<'ll, '_>, ptr: &'ll Value, meta: &'ll Value) -> &'ll Value {
|
|
||||||
assert_eq!(abi::FAT_PTR_ADDR, 0);
|
|
||||||
assert_eq!(abi::FAT_PTR_EXTRA, 1);
|
|
||||||
C_struct(cx, &[ptr, meta], false)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn C_struct(cx: &CodegenCx<'ll, '_>, elts: &[&'ll Value], packed: bool) -> &'ll Value {
|
|
||||||
C_struct_in_context(cx.llcx, elts, packed)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn C_struct_in_context(
|
|
||||||
llcx: &'ll llvm::Context,
|
|
||||||
elts: &[&'ll Value],
|
|
||||||
packed: bool,
|
|
||||||
) -> &'ll Value {
|
|
||||||
unsafe {
|
|
||||||
llvm::LLVMConstStructInContext(llcx,
|
|
||||||
elts.as_ptr(), elts.len() as c_uint,
|
|
||||||
packed as Bool)
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
pub fn C_array(ty: &'ll Type, elts: &[&'ll Value]) -> &'ll Value {
|
|
||||||
unsafe {
|
// This is a 'c-like' raw string, which differs from
|
||||||
return llvm::LLVMConstArray(ty, elts.as_ptr(), elts.len() as c_uint);
|
// our boxed-and-length-annotated strings.
|
||||||
|
fn c_cstr(
|
||||||
|
&self,
|
||||||
|
s: LocalInternedString,
|
||||||
|
null_terminated: bool,
|
||||||
|
) -> &'ll Value {
|
||||||
|
unsafe {
|
||||||
|
if let Some(&llval) = &self.const_cstr_cache.borrow().get(&s) {
|
||||||
|
return llval;
|
||||||
|
}
|
||||||
|
|
||||||
|
let sc = llvm::LLVMConstStringInContext(&self.llcx,
|
||||||
|
s.as_ptr() as *const c_char,
|
||||||
|
s.len() as c_uint,
|
||||||
|
!null_terminated as Bool);
|
||||||
|
let sym = &self.generate_local_symbol_name("str");
|
||||||
|
let g = declare::define_global(&self, &sym[..], Self::val_ty(sc)).unwrap_or_else(||{
|
||||||
|
bug!("symbol `{}` is already defined", sym);
|
||||||
|
});
|
||||||
|
llvm::LLVMSetInitializer(g, sc);
|
||||||
|
llvm::LLVMSetGlobalConstant(g, True);
|
||||||
|
llvm::LLVMRustSetLinkage(g, llvm::Linkage::InternalLinkage);
|
||||||
|
|
||||||
|
&self.const_cstr_cache.borrow_mut().insert(s, g);
|
||||||
|
g
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
pub fn C_vector(elts: &[&'ll Value]) -> &'ll Value {
|
// NB: Do not use `do_spill_noroot` to make this into a constant string, or
|
||||||
unsafe {
|
// you will be kicked off fast isel. See issue #4352 for an example of this.
|
||||||
return llvm::LLVMConstVector(elts.as_ptr(), elts.len() as c_uint);
|
fn c_str_slice(&self, s: LocalInternedString) -> &'ll Value {
|
||||||
|
let len = s.len();
|
||||||
|
let cs = consts::ptrcast(&self.c_cstr(s, false),
|
||||||
|
&self.layout_of(&self.tcx.mk_str()).llvm_type(&self).ptr_to());
|
||||||
|
&self.c_fat_ptr(cs, &self.c_usize(len as u64))
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
pub fn C_bytes(cx: &CodegenCx<'ll, '_>, bytes: &[u8]) -> &'ll Value {
|
fn c_fat_ptr(
|
||||||
C_bytes_in_context(cx.llcx, bytes)
|
&self,
|
||||||
}
|
ptr: &'ll Value,
|
||||||
|
meta: &'ll Value
|
||||||
pub fn C_bytes_in_context(llcx: &'ll llvm::Context, bytes: &[u8]) -> &'ll Value {
|
) -> &'ll Value {
|
||||||
unsafe {
|
assert_eq!(abi::FAT_PTR_ADDR, 0);
|
||||||
let ptr = bytes.as_ptr() as *const c_char;
|
assert_eq!(abi::FAT_PTR_EXTRA, 1);
|
||||||
return llvm::LLVMConstStringInContext(llcx, ptr, bytes.len() as c_uint, True);
|
&self.c_struct(&[ptr, meta], false)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
pub fn const_get_elt(v: &'ll Value, idx: u64) -> &'ll Value {
|
fn c_struct(
|
||||||
unsafe {
|
&self,
|
||||||
assert_eq!(idx as c_uint as u64, idx);
|
elts: &[&'ll Value],
|
||||||
let us = &[idx as c_uint];
|
packed: bool
|
||||||
let r = llvm::LLVMConstExtractValue(v, us.as_ptr(), us.len() as c_uint);
|
) -> &'ll Value {
|
||||||
|
Self::c_struct_in_context(&self.llcx, elts, packed)
|
||||||
debug!("const_get_elt(v={:?}, idx={}, r={:?})",
|
|
||||||
v, idx, r);
|
|
||||||
|
|
||||||
r
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
pub fn const_get_real(v: &'ll Value) -> Option<(f64, bool)> {
|
fn c_struct_in_context(
|
||||||
unsafe {
|
llcx: &'a llvm::Context,
|
||||||
if is_const_real(v) {
|
elts: &[&'a Value],
|
||||||
let mut loses_info: llvm::Bool = ::std::mem::uninitialized();
|
packed: bool,
|
||||||
let r = llvm::LLVMConstRealGetDouble(v, &mut loses_info);
|
) -> &'a Value {
|
||||||
let loses_info = if loses_info == 1 { true } else { false };
|
unsafe {
|
||||||
Some((r, loses_info))
|
llvm::LLVMConstStructInContext(llcx,
|
||||||
} else {
|
elts.as_ptr(), elts.len() as c_uint,
|
||||||
None
|
packed as Bool)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn c_array(ty: &'ll Type, elts: &[&'ll Value]) -> &'ll Value {
|
||||||
|
unsafe {
|
||||||
|
return llvm::LLVMConstArray(ty, elts.as_ptr(), elts.len() as c_uint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn c_vector(elts: &[&'ll Value]) -> &'ll Value {
|
||||||
|
unsafe {
|
||||||
|
return llvm::LLVMConstVector(elts.as_ptr(), elts.len() as c_uint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn c_bytes(&self, bytes: &[u8]) -> &'ll Value {
|
||||||
|
Self::c_bytes_in_context(&self.llcx, bytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn c_bytes_in_context(llcx: &'ll llvm::Context, bytes: &[u8]) -> &'ll Value {
|
||||||
|
unsafe {
|
||||||
|
let ptr = bytes.as_ptr() as *const c_char;
|
||||||
|
return llvm::LLVMConstStringInContext(llcx, ptr, bytes.len() as c_uint, True);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn const_get_elt(v: &'ll Value, idx: u64) -> &'ll Value {
|
||||||
|
unsafe {
|
||||||
|
assert_eq!(idx as c_uint as u64, idx);
|
||||||
|
let us = &[idx as c_uint];
|
||||||
|
let r = llvm::LLVMConstExtractValue(v, us.as_ptr(), us.len() as c_uint);
|
||||||
|
|
||||||
|
debug!("const_get_elt(v={:?}, idx={}, r={:?})",
|
||||||
|
v, idx, r);
|
||||||
|
|
||||||
|
r
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn const_get_real(v: &'ll Value) -> Option<(f64, bool)> {
|
||||||
|
unsafe {
|
||||||
|
if Self::is_const_real(v) {
|
||||||
|
let mut loses_info: llvm::Bool = ::std::mem::uninitialized();
|
||||||
|
let r = llvm::LLVMConstRealGetDouble(v, &mut loses_info);
|
||||||
|
let loses_info = if loses_info == 1 { true } else { false };
|
||||||
|
Some((r, loses_info))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn const_to_uint(v: &'ll Value) -> u64 {
|
||||||
|
unsafe {
|
||||||
|
llvm::LLVMConstIntGetZExtValue(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_const_integral(v: &'ll Value) -> bool {
|
||||||
|
unsafe {
|
||||||
|
llvm::LLVMIsAConstantInt(v).is_some()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_const_real(v: &'ll Value) -> bool {
|
||||||
|
unsafe {
|
||||||
|
llvm::LLVMIsAConstantFP(v).is_some()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn const_to_opt_u128(v: &'ll Value, sign_ext: bool) -> Option<u128> {
|
||||||
|
unsafe {
|
||||||
|
if Self::is_const_integral(v) {
|
||||||
|
let (mut lo, mut hi) = (0u64, 0u64);
|
||||||
|
let success = llvm::LLVMRustConstInt128Get(v, sign_ext,
|
||||||
|
&mut hi, &mut lo);
|
||||||
|
if success {
|
||||||
|
Some(hi_lo_to_u128(lo, hi))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn const_to_uint(v: &'ll Value) -> u64 {
|
|
||||||
unsafe {
|
|
||||||
llvm::LLVMConstIntGetZExtValue(v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_const_integral(v: &'ll Value) -> bool {
|
|
||||||
unsafe {
|
|
||||||
llvm::LLVMIsAConstantInt(v).is_some()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_const_real(v: &'ll Value) -> bool {
|
|
||||||
unsafe {
|
|
||||||
llvm::LLVMIsAConstantFP(v).is_some()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn hi_lo_to_u128(lo: u64, hi: u64) -> u128 {
|
fn hi_lo_to_u128(lo: u64, hi: u64) -> u128 {
|
||||||
((hi as u128) << 64) | (lo as u128)
|
((hi as u128) << 64) | (lo as u128)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn const_to_opt_u128(v: &'ll Value, sign_ext: bool) -> Option<u128> {
|
|
||||||
unsafe {
|
|
||||||
if is_const_integral(v) {
|
|
||||||
let (mut lo, mut hi) = (0u64, 0u64);
|
|
||||||
let success = llvm::LLVMRustConstInt128Get(v, sign_ext,
|
|
||||||
&mut hi, &mut lo);
|
|
||||||
if success {
|
|
||||||
Some(hi_lo_to_u128(lo, hi))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn langcall(tcx: TyCtxt,
|
pub fn langcall(tcx: TyCtxt,
|
||||||
span: Option<Span>,
|
span: Option<Span>,
|
||||||
msg: &str,
|
msg: &str,
|
||||||
|
@ -456,7 +473,7 @@ pub fn build_unchecked_rshift(
|
||||||
}
|
}
|
||||||
|
|
||||||
fn shift_mask_rhs(bx: &Builder<'a, 'll, 'tcx>, rhs: &'ll Value) -> &'ll Value {
|
fn shift_mask_rhs(bx: &Builder<'a, 'll, 'tcx>, rhs: &'ll Value) -> &'ll Value {
|
||||||
let rhs_llty = val_ty(rhs);
|
let rhs_llty = CodegenCx::val_ty(rhs);
|
||||||
bx.and(rhs, shift_mask_val(bx, rhs_llty, rhs_llty, false))
|
bx.and(rhs, shift_mask_val(bx, rhs_llty, rhs_llty, false))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -472,9 +489,9 @@ pub fn shift_mask_val(
|
||||||
// i8/u8 can shift by at most 7, i16/u16 by at most 15, etc.
|
// i8/u8 can shift by at most 7, i16/u16 by at most 15, etc.
|
||||||
let val = llty.int_width() - 1;
|
let val = llty.int_width() - 1;
|
||||||
if invert {
|
if invert {
|
||||||
C_int(mask_llty, !val as i64)
|
CodegenCx::c_int(mask_llty, !val as i64)
|
||||||
} else {
|
} else {
|
||||||
C_uint(mask_llty, val)
|
CodegenCx::c_uint(mask_llty, val)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
TypeKind::Vector => {
|
TypeKind::Vector => {
|
||||||
|
|
|
@ -15,7 +15,7 @@ use rustc::hir::Node;
|
||||||
use debuginfo;
|
use debuginfo;
|
||||||
use base;
|
use base;
|
||||||
use monomorphize::MonoItem;
|
use monomorphize::MonoItem;
|
||||||
use common::{CodegenCx, val_ty};
|
use common::CodegenCx;
|
||||||
use declare;
|
use declare;
|
||||||
use monomorphize::Instance;
|
use monomorphize::Instance;
|
||||||
use syntax_pos::Span;
|
use syntax_pos::Span;
|
||||||
|
@ -24,6 +24,7 @@ use type_::Type;
|
||||||
use type_of::LayoutLlvmExt;
|
use type_of::LayoutLlvmExt;
|
||||||
use value::Value;
|
use value::Value;
|
||||||
use rustc::ty::{self, Ty};
|
use rustc::ty::{self, Ty};
|
||||||
|
use interfaces::CommonMethods;
|
||||||
|
|
||||||
use rustc::ty::layout::{Align, LayoutOf};
|
use rustc::ty::layout::{Align, LayoutOf};
|
||||||
|
|
||||||
|
@ -72,13 +73,14 @@ pub fn addr_of_mut(
|
||||||
let gv = match kind {
|
let gv = match kind {
|
||||||
Some(kind) if !cx.tcx.sess.fewer_names() => {
|
Some(kind) if !cx.tcx.sess.fewer_names() => {
|
||||||
let name = cx.generate_local_symbol_name(kind);
|
let name = cx.generate_local_symbol_name(kind);
|
||||||
let gv = declare::define_global(cx, &name[..], val_ty(cv)).unwrap_or_else(||{
|
let gv = declare::define_global(cx, &name[..],
|
||||||
bug!("symbol `{}` is already defined", name);
|
CodegenCx::val_ty(cv)).unwrap_or_else(||{
|
||||||
|
bug!("symbol `{}` is already defined", name);
|
||||||
});
|
});
|
||||||
llvm::LLVMRustSetLinkage(gv, llvm::Linkage::PrivateLinkage);
|
llvm::LLVMRustSetLinkage(gv, llvm::Linkage::PrivateLinkage);
|
||||||
gv
|
gv
|
||||||
},
|
},
|
||||||
_ => declare::define_private_global(cx, val_ty(cv)),
|
_ => declare::define_private_global(cx, CodegenCx::val_ty(cv)),
|
||||||
};
|
};
|
||||||
llvm::LLVMSetInitializer(gv, cv);
|
llvm::LLVMSetInitializer(gv, cv);
|
||||||
set_global_alignment(cx, gv, align);
|
set_global_alignment(cx, gv, align);
|
||||||
|
@ -310,7 +312,7 @@ pub fn codegen_static<'a, 'tcx>(
|
||||||
|
|
||||||
// boolean SSA values are i1, but they have to be stored in i8 slots,
|
// boolean SSA values are i1, but they have to be stored in i8 slots,
|
||||||
// otherwise some LLVM optimization passes don't work as expected
|
// otherwise some LLVM optimization passes don't work as expected
|
||||||
let mut val_llty = val_ty(v);
|
let mut val_llty = CodegenCx::val_ty(v);
|
||||||
let v = if val_llty == Type::i1(cx) {
|
let v = if val_llty == Type::i1(cx) {
|
||||||
val_llty = Type::i8(cx);
|
val_llty = Type::i8(cx);
|
||||||
llvm::LLVMConstZExt(v, val_llty)
|
llvm::LLVMConstZExt(v, val_llty)
|
||||||
|
|
|
@ -12,13 +12,13 @@
|
||||||
|
|
||||||
use llvm;
|
use llvm;
|
||||||
|
|
||||||
use common::{C_bytes, CodegenCx, C_i32};
|
use common::CodegenCx;
|
||||||
use builder::Builder;
|
use builder::Builder;
|
||||||
use declare;
|
use declare;
|
||||||
use rustc::session::config::DebugInfo;
|
use rustc::session::config::DebugInfo;
|
||||||
use type_::Type;
|
use type_::Type;
|
||||||
use value::Value;
|
use value::Value;
|
||||||
use interfaces::BuilderMethods;
|
use interfaces::{BuilderMethods, CommonMethods};
|
||||||
|
|
||||||
use syntax::attr;
|
use syntax::attr;
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@ pub fn insert_reference_to_gdb_debug_scripts_section_global(bx: &Builder) {
|
||||||
let gdb_debug_scripts_section = get_or_insert_gdb_debug_scripts_section_global(bx.cx);
|
let gdb_debug_scripts_section = get_or_insert_gdb_debug_scripts_section_global(bx.cx);
|
||||||
// Load just the first byte as that's all that's necessary to force
|
// Load just the first byte as that's all that's necessary to force
|
||||||
// LLVM to keep around the reference to the global.
|
// LLVM to keep around the reference to the global.
|
||||||
let indices = [C_i32(bx.cx, 0), C_i32(bx.cx, 0)];
|
let indices = [CodegenCx::c_i32(bx.cx, 0), CodegenCx::c_i32(bx.cx, 0)];
|
||||||
let element = bx.inbounds_gep(gdb_debug_scripts_section, &indices);
|
let element = bx.inbounds_gep(gdb_debug_scripts_section, &indices);
|
||||||
let volative_load_instruction = bx.volatile_load(element);
|
let volative_load_instruction = bx.volatile_load(element);
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -64,7 +64,7 @@ pub fn get_or_insert_gdb_debug_scripts_section_global(cx: &CodegenCx<'ll, '_>)
|
||||||
bug!("symbol `{}` is already defined", section_var_name)
|
bug!("symbol `{}` is already defined", section_var_name)
|
||||||
});
|
});
|
||||||
llvm::LLVMSetSection(section_var, section_name.as_ptr() as *const _);
|
llvm::LLVMSetSection(section_var, section_name.as_ptr() as *const _);
|
||||||
llvm::LLVMSetInitializer(section_var, C_bytes(cx, section_contents));
|
llvm::LLVMSetInitializer(section_var, CodegenCx::c_bytes(cx, section_contents));
|
||||||
llvm::LLVMSetGlobalConstant(section_var, llvm::True);
|
llvm::LLVMSetGlobalConstant(section_var, llvm::True);
|
||||||
llvm::LLVMSetUnnamedAddr(section_var, llvm::True);
|
llvm::LLVMSetUnnamedAddr(section_var, llvm::True);
|
||||||
llvm::LLVMRustSetLinkage(section_var, llvm::Linkage::LinkOnceODRLinkage);
|
llvm::LLVMRustSetLinkage(section_var, llvm::Linkage::LinkOnceODRLinkage);
|
||||||
|
|
|
@ -18,6 +18,7 @@ use super::namespace::mangled_name_of_instance;
|
||||||
use super::type_names::compute_debuginfo_type_name;
|
use super::type_names::compute_debuginfo_type_name;
|
||||||
use super::{CrateDebugContext};
|
use super::{CrateDebugContext};
|
||||||
use abi;
|
use abi;
|
||||||
|
use interfaces::CommonMethods;
|
||||||
use value::Value;
|
use value::Value;
|
||||||
|
|
||||||
use llvm;
|
use llvm;
|
||||||
|
@ -32,7 +33,7 @@ use rustc::hir::def_id::{DefId, CrateNum, LOCAL_CRATE};
|
||||||
use rustc::ich::NodeIdHashingMode;
|
use rustc::ich::NodeIdHashingMode;
|
||||||
use rustc_data_structures::fingerprint::Fingerprint;
|
use rustc_data_structures::fingerprint::Fingerprint;
|
||||||
use rustc::ty::Instance;
|
use rustc::ty::Instance;
|
||||||
use common::{CodegenCx, C_u64};
|
use common::CodegenCx;
|
||||||
use rustc::ty::{self, AdtKind, ParamEnv, Ty, TyCtxt};
|
use rustc::ty::{self, AdtKind, ParamEnv, Ty, TyCtxt};
|
||||||
use rustc::ty::layout::{self, Align, HasDataLayout, Integer, IntegerExt, LayoutOf,
|
use rustc::ty::layout::{self, Align, HasDataLayout, Integer, IntegerExt, LayoutOf,
|
||||||
PrimitiveExt, Size, TyLayout};
|
PrimitiveExt, Size, TyLayout};
|
||||||
|
@ -1810,7 +1811,7 @@ fn set_members_of_composite_type(cx: &CodegenCx<'ll, '_>,
|
||||||
member_description.offset.bits(),
|
member_description.offset.bits(),
|
||||||
match member_description.discriminant {
|
match member_description.discriminant {
|
||||||
None => None,
|
None => None,
|
||||||
Some(value) => Some(C_u64(cx, value)),
|
Some(value) => Some(cx.c_u64(value)),
|
||||||
},
|
},
|
||||||
member_description.flags,
|
member_description.flags,
|
||||||
member_description.type_metadata))
|
member_description.type_metadata))
|
||||||
|
|
|
@ -16,11 +16,12 @@ use std;
|
||||||
|
|
||||||
use builder::Builder;
|
use builder::Builder;
|
||||||
use common::*;
|
use common::*;
|
||||||
|
use context::CodegenCx;
|
||||||
use meth;
|
use meth;
|
||||||
use rustc::ty::layout::LayoutOf;
|
use rustc::ty::layout::LayoutOf;
|
||||||
use rustc::ty::{self, Ty};
|
use rustc::ty::{self, Ty};
|
||||||
use value::Value;
|
use value::Value;
|
||||||
use interfaces::BuilderMethods;
|
use interfaces::{BuilderMethods, CommonMethods};
|
||||||
|
|
||||||
pub fn size_and_align_of_dst(
|
pub fn size_and_align_of_dst(
|
||||||
bx: &Builder<'_, 'll, 'tcx>,
|
bx: &Builder<'_, 'll, 'tcx>,
|
||||||
|
@ -33,8 +34,8 @@ pub fn size_and_align_of_dst(
|
||||||
let (size, align) = bx.cx.size_and_align_of(t);
|
let (size, align) = bx.cx.size_and_align_of(t);
|
||||||
debug!("size_and_align_of_dst t={} info={:?} size: {:?} align: {:?}",
|
debug!("size_and_align_of_dst t={} info={:?} size: {:?} align: {:?}",
|
||||||
t, info, size, align);
|
t, info, size, align);
|
||||||
let size = C_usize(bx.cx, size.bytes());
|
let size = CodegenCx::c_usize(bx.cx, size.bytes());
|
||||||
let align = C_usize(bx.cx, align.abi());
|
let align = CodegenCx::c_usize(bx.cx, align.abi());
|
||||||
return (size, align);
|
return (size, align);
|
||||||
}
|
}
|
||||||
match t.sty {
|
match t.sty {
|
||||||
|
@ -48,8 +49,8 @@ pub fn size_and_align_of_dst(
|
||||||
// The info in this case is the length of the str, so the size is that
|
// The info in this case is the length of the str, so the size is that
|
||||||
// times the unit size.
|
// times the unit size.
|
||||||
let (size, align) = bx.cx.size_and_align_of(unit);
|
let (size, align) = bx.cx.size_and_align_of(unit);
|
||||||
(bx.mul(info.unwrap(), C_usize(bx.cx, size.bytes())),
|
(bx.mul(info.unwrap(), CodegenCx::c_usize(bx.cx, size.bytes())),
|
||||||
C_usize(bx.cx, align.abi()))
|
CodegenCx::c_usize(bx.cx, align.abi()))
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
let cx = bx.cx;
|
let cx = bx.cx;
|
||||||
|
@ -65,8 +66,8 @@ pub fn size_and_align_of_dst(
|
||||||
let sized_align = layout.align.abi();
|
let sized_align = layout.align.abi();
|
||||||
debug!("DST {} statically sized prefix size: {} align: {}",
|
debug!("DST {} statically sized prefix size: {} align: {}",
|
||||||
t, sized_size, sized_align);
|
t, sized_size, sized_align);
|
||||||
let sized_size = C_usize(cx, sized_size);
|
let sized_size = CodegenCx::c_usize(cx, sized_size);
|
||||||
let sized_align = C_usize(cx, sized_align);
|
let sized_align = CodegenCx::c_usize(cx, sized_align);
|
||||||
|
|
||||||
// Recurse to get the size of the dynamically sized field (must be
|
// Recurse to get the size of the dynamically sized field (must be
|
||||||
// the last field).
|
// the last field).
|
||||||
|
@ -92,12 +93,12 @@ pub fn size_and_align_of_dst(
|
||||||
|
|
||||||
// Choose max of two known alignments (combined value must
|
// Choose max of two known alignments (combined value must
|
||||||
// be aligned according to more restrictive of the two).
|
// be aligned according to more restrictive of the two).
|
||||||
let align = match (const_to_opt_u128(sized_align, false),
|
let align = match (CodegenCx::const_to_opt_u128(sized_align, false),
|
||||||
const_to_opt_u128(unsized_align, false)) {
|
CodegenCx::const_to_opt_u128(unsized_align, false)) {
|
||||||
(Some(sized_align), Some(unsized_align)) => {
|
(Some(sized_align), Some(unsized_align)) => {
|
||||||
// If both alignments are constant, (the sized_align should always be), then
|
// If both alignments are constant, (the sized_align should always be), then
|
||||||
// pick the correct alignment statically.
|
// pick the correct alignment statically.
|
||||||
C_usize(cx, std::cmp::max(sized_align, unsized_align) as u64)
|
CodegenCx::c_usize(cx, std::cmp::max(sized_align, unsized_align) as u64)
|
||||||
}
|
}
|
||||||
_ => bx.select(bx.icmp(IntPredicate::IntUGT, sized_align, unsized_align),
|
_ => bx.select(bx.icmp(IntPredicate::IntUGT, sized_align, unsized_align),
|
||||||
sized_align,
|
sized_align,
|
||||||
|
@ -115,7 +116,7 @@ pub fn size_and_align_of_dst(
|
||||||
//
|
//
|
||||||
// `(size + (align-1)) & -align`
|
// `(size + (align-1)) & -align`
|
||||||
|
|
||||||
let addend = bx.sub(align, C_usize(bx.cx, 1));
|
let addend = bx.sub(align, CodegenCx::c_usize(bx.cx, 1));
|
||||||
let size = bx.and(bx.add(size, addend), bx.neg(align));
|
let size = bx.and(bx.add(size, addend), bx.neg(align));
|
||||||
|
|
||||||
(size, align)
|
(size, align)
|
||||||
|
|
|
@ -12,4 +12,5 @@ pub trait Backend {
|
||||||
type Value;
|
type Value;
|
||||||
type BasicBlock;
|
type BasicBlock;
|
||||||
type Type;
|
type Type;
|
||||||
|
type Context;
|
||||||
}
|
}
|
||||||
|
|
61
src/librustc_codegen_llvm/interfaces/common.rs
Normal file
61
src/librustc_codegen_llvm/interfaces/common.rs
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
// 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 super::Backend;
|
||||||
|
use syntax::symbol::LocalInternedString;
|
||||||
|
|
||||||
|
pub trait CommonMethods : Backend {
|
||||||
|
fn val_ty(v: Self::Value) -> Self::Type;
|
||||||
|
|
||||||
|
// Constant constructors
|
||||||
|
fn c_null(t: Self::Type) -> Self::Value;
|
||||||
|
fn c_undef(t: Self::Type) -> Self::Value;
|
||||||
|
fn c_int(t: Self::Type, i: i64) -> Self::Value;
|
||||||
|
fn c_uint(t: Self::Type, i: u64) -> Self::Value;
|
||||||
|
fn c_uint_big(t: Self::Type, u: u128) -> Self::Value;
|
||||||
|
fn c_bool(&self, val: bool) -> Self::Value;
|
||||||
|
fn c_i32(&self, i: i32) -> Self::Value;
|
||||||
|
fn c_u32(&self, i: u32) -> Self::Value;
|
||||||
|
fn c_u64(&self, i: u64) -> Self::Value;
|
||||||
|
fn c_usize(&self, i: u64) -> Self::Value;
|
||||||
|
fn c_u8(&self, i: u8) -> Self::Value;
|
||||||
|
fn c_cstr(
|
||||||
|
&self,
|
||||||
|
s: LocalInternedString,
|
||||||
|
null_terminated: bool,
|
||||||
|
) -> Self::Value;
|
||||||
|
fn c_str_slice(&self, s: LocalInternedString) -> Self::Value;
|
||||||
|
fn c_fat_ptr(
|
||||||
|
&self,
|
||||||
|
ptr: Self::Value,
|
||||||
|
meta: Self::Value
|
||||||
|
) -> Self::Value;
|
||||||
|
fn c_struct(
|
||||||
|
&self,
|
||||||
|
elts: &[Self::Value],
|
||||||
|
packed: bool
|
||||||
|
) -> Self::Value;
|
||||||
|
fn c_struct_in_context(
|
||||||
|
llcx: Self::Context,
|
||||||
|
elts: &[Self::Value],
|
||||||
|
packed: bool,
|
||||||
|
) -> Self::Value;
|
||||||
|
fn c_array(ty: Self::Type, elts: &[Self::Value]) -> Self::Value;
|
||||||
|
fn c_vector(elts: &[Self::Value]) -> Self::Value;
|
||||||
|
fn c_bytes(&self, bytes: &[u8]) -> Self::Value;
|
||||||
|
fn c_bytes_in_context(llcx: Self::Context, bytes: &[u8]) -> Self::Value;
|
||||||
|
|
||||||
|
fn const_get_elt(v: Self::Value, idx: u64) -> Self::Value;
|
||||||
|
fn const_get_real(v: Self::Value) -> Option<(f64, bool)>;
|
||||||
|
fn const_to_uint(v: Self::Value) -> u64;
|
||||||
|
fn is_const_integral(v: Self::Value) -> bool;
|
||||||
|
fn is_const_real(v: Self::Value) -> bool;
|
||||||
|
fn const_to_opt_u128(v: Self::Value, sign_ext: bool) -> Option<u128>;
|
||||||
|
}
|
|
@ -10,6 +10,8 @@
|
||||||
|
|
||||||
mod builder;
|
mod builder;
|
||||||
mod backend;
|
mod backend;
|
||||||
|
mod common;
|
||||||
|
|
||||||
pub use self::builder::BuilderMethods;
|
pub use self::builder::BuilderMethods;
|
||||||
pub use self::backend::Backend;
|
pub use self::backend::Backend;
|
||||||
|
pub use self::common::CommonMethods;
|
||||||
|
|
|
@ -19,6 +19,7 @@ use mir::place::PlaceRef;
|
||||||
use mir::operand::{OperandRef, OperandValue};
|
use mir::operand::{OperandRef, OperandValue};
|
||||||
use base::*;
|
use base::*;
|
||||||
use common::*;
|
use common::*;
|
||||||
|
use context::CodegenCx;
|
||||||
use declare;
|
use declare;
|
||||||
use glue;
|
use glue;
|
||||||
use type_::Type;
|
use type_::Type;
|
||||||
|
@ -31,7 +32,7 @@ use syntax::symbol::Symbol;
|
||||||
use builder::Builder;
|
use builder::Builder;
|
||||||
use value::Value;
|
use value::Value;
|
||||||
|
|
||||||
use interfaces::BuilderMethods;
|
use interfaces::{BuilderMethods, CommonMethods};
|
||||||
|
|
||||||
use rustc::session::Session;
|
use rustc::session::Session;
|
||||||
use syntax_pos::Span;
|
use syntax_pos::Span;
|
||||||
|
@ -126,11 +127,11 @@ pub fn codegen_intrinsic_call(
|
||||||
},
|
},
|
||||||
"likely" => {
|
"likely" => {
|
||||||
let expect = cx.get_intrinsic(&("llvm.expect.i1"));
|
let expect = cx.get_intrinsic(&("llvm.expect.i1"));
|
||||||
bx.call(expect, &[args[0].immediate(), C_bool(cx, true)], None)
|
bx.call(expect, &[args[0].immediate(), CodegenCx::c_bool(cx, true)], None)
|
||||||
}
|
}
|
||||||
"unlikely" => {
|
"unlikely" => {
|
||||||
let expect = cx.get_intrinsic(&("llvm.expect.i1"));
|
let expect = cx.get_intrinsic(&("llvm.expect.i1"));
|
||||||
bx.call(expect, &[args[0].immediate(), C_bool(cx, false)], None)
|
bx.call(expect, &[args[0].immediate(), CodegenCx::c_bool(cx, false)], None)
|
||||||
}
|
}
|
||||||
"try" => {
|
"try" => {
|
||||||
try_intrinsic(bx, cx,
|
try_intrinsic(bx, cx,
|
||||||
|
@ -146,7 +147,7 @@ pub fn codegen_intrinsic_call(
|
||||||
}
|
}
|
||||||
"size_of" => {
|
"size_of" => {
|
||||||
let tp_ty = substs.type_at(0);
|
let tp_ty = substs.type_at(0);
|
||||||
C_usize(cx, cx.size_of(tp_ty).bytes())
|
CodegenCx::c_usize(cx, cx.size_of(tp_ty).bytes())
|
||||||
}
|
}
|
||||||
"size_of_val" => {
|
"size_of_val" => {
|
||||||
let tp_ty = substs.type_at(0);
|
let tp_ty = substs.type_at(0);
|
||||||
|
@ -155,12 +156,12 @@ pub fn codegen_intrinsic_call(
|
||||||
glue::size_and_align_of_dst(bx, tp_ty, Some(meta));
|
glue::size_and_align_of_dst(bx, tp_ty, Some(meta));
|
||||||
llsize
|
llsize
|
||||||
} else {
|
} else {
|
||||||
C_usize(cx, cx.size_of(tp_ty).bytes())
|
CodegenCx::c_usize(cx, cx.size_of(tp_ty).bytes())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"min_align_of" => {
|
"min_align_of" => {
|
||||||
let tp_ty = substs.type_at(0);
|
let tp_ty = substs.type_at(0);
|
||||||
C_usize(cx, cx.align_of(tp_ty).abi())
|
CodegenCx::c_usize(cx, cx.align_of(tp_ty).abi())
|
||||||
}
|
}
|
||||||
"min_align_of_val" => {
|
"min_align_of_val" => {
|
||||||
let tp_ty = substs.type_at(0);
|
let tp_ty = substs.type_at(0);
|
||||||
|
@ -169,20 +170,20 @@ pub fn codegen_intrinsic_call(
|
||||||
glue::size_and_align_of_dst(bx, tp_ty, Some(meta));
|
glue::size_and_align_of_dst(bx, tp_ty, Some(meta));
|
||||||
llalign
|
llalign
|
||||||
} else {
|
} else {
|
||||||
C_usize(cx, cx.align_of(tp_ty).abi())
|
CodegenCx::c_usize(cx, cx.align_of(tp_ty).abi())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"pref_align_of" => {
|
"pref_align_of" => {
|
||||||
let tp_ty = substs.type_at(0);
|
let tp_ty = substs.type_at(0);
|
||||||
C_usize(cx, cx.align_of(tp_ty).pref())
|
CodegenCx::c_usize(cx, cx.align_of(tp_ty).pref())
|
||||||
}
|
}
|
||||||
"type_name" => {
|
"type_name" => {
|
||||||
let tp_ty = substs.type_at(0);
|
let tp_ty = substs.type_at(0);
|
||||||
let ty_name = Symbol::intern(&tp_ty.to_string()).as_str();
|
let ty_name = Symbol::intern(&tp_ty.to_string()).as_str();
|
||||||
C_str_slice(cx, ty_name)
|
CodegenCx::c_str_slice(cx, ty_name)
|
||||||
}
|
}
|
||||||
"type_id" => {
|
"type_id" => {
|
||||||
C_u64(cx, cx.tcx.type_id_hash(substs.type_at(0)))
|
CodegenCx::c_u64(cx, cx.tcx.type_id_hash(substs.type_at(0)))
|
||||||
}
|
}
|
||||||
"init" => {
|
"init" => {
|
||||||
let ty = substs.type_at(0);
|
let ty = substs.type_at(0);
|
||||||
|
@ -191,7 +192,14 @@ pub fn codegen_intrinsic_call(
|
||||||
// If we store a zero constant, LLVM will drown in vreg allocation for large data
|
// If we store a zero constant, LLVM will drown in vreg allocation for large data
|
||||||
// structures, and the generated code will be awful. (A telltale sign of this is
|
// structures, and the generated code will be awful. (A telltale sign of this is
|
||||||
// large quantities of `mov [byte ptr foo],0` in the generated code.)
|
// large quantities of `mov [byte ptr foo],0` in the generated code.)
|
||||||
memset_intrinsic(bx, false, ty, llresult, C_u8(cx, 0), C_usize(cx, 1));
|
memset_intrinsic(
|
||||||
|
bx,
|
||||||
|
false,
|
||||||
|
ty,
|
||||||
|
llresult,
|
||||||
|
CodegenCx::c_u8(cx, 0),
|
||||||
|
CodegenCx::c_usize(cx, 1)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -202,7 +210,7 @@ pub fn codegen_intrinsic_call(
|
||||||
"needs_drop" => {
|
"needs_drop" => {
|
||||||
let tp_ty = substs.type_at(0);
|
let tp_ty = substs.type_at(0);
|
||||||
|
|
||||||
C_bool(cx, bx.cx.type_needs_drop(tp_ty))
|
CodegenCx::c_bool(cx, bx.cx.type_needs_drop(tp_ty))
|
||||||
}
|
}
|
||||||
"offset" => {
|
"offset" => {
|
||||||
let ptr = args[0].immediate();
|
let ptr = args[0].immediate();
|
||||||
|
@ -279,9 +287,9 @@ pub fn codegen_intrinsic_call(
|
||||||
};
|
};
|
||||||
bx.call(expect, &[
|
bx.call(expect, &[
|
||||||
args[0].immediate(),
|
args[0].immediate(),
|
||||||
C_i32(cx, rw),
|
CodegenCx::c_i32(cx, rw),
|
||||||
args[1].immediate(),
|
args[1].immediate(),
|
||||||
C_i32(cx, cache_type)
|
CodegenCx::c_i32(cx, cache_type)
|
||||||
], None)
|
], None)
|
||||||
},
|
},
|
||||||
"ctlz" | "ctlz_nonzero" | "cttz" | "cttz_nonzero" | "ctpop" | "bswap" |
|
"ctlz" | "ctlz_nonzero" | "cttz" | "cttz_nonzero" | "ctpop" | "bswap" |
|
||||||
|
@ -294,12 +302,12 @@ pub fn codegen_intrinsic_call(
|
||||||
Some((width, signed)) =>
|
Some((width, signed)) =>
|
||||||
match name {
|
match name {
|
||||||
"ctlz" | "cttz" => {
|
"ctlz" | "cttz" => {
|
||||||
let y = C_bool(bx.cx, false);
|
let y = CodegenCx::c_bool(bx.cx, false);
|
||||||
let llfn = cx.get_intrinsic(&format!("llvm.{}.i{}", name, width));
|
let llfn = cx.get_intrinsic(&format!("llvm.{}.i{}", name, width));
|
||||||
bx.call(llfn, &[args[0].immediate(), y], None)
|
bx.call(llfn, &[args[0].immediate(), y], None)
|
||||||
}
|
}
|
||||||
"ctlz_nonzero" | "cttz_nonzero" => {
|
"ctlz_nonzero" | "cttz_nonzero" => {
|
||||||
let y = C_bool(bx.cx, true);
|
let y = CodegenCx::c_bool(bx.cx, true);
|
||||||
let llvm_name = &format!("llvm.{}.i{}", &name[..4], width);
|
let llvm_name = &format!("llvm.{}.i{}", &name[..4], width);
|
||||||
let llfn = cx.get_intrinsic(llvm_name);
|
let llfn = cx.get_intrinsic(llvm_name);
|
||||||
bx.call(llfn, &[args[0].immediate(), y], None)
|
bx.call(llfn, &[args[0].immediate(), y], None)
|
||||||
|
@ -380,7 +388,7 @@ pub fn codegen_intrinsic_call(
|
||||||
} else {
|
} else {
|
||||||
// rotate_left: (X << (S % BW)) | (X >> ((BW - S) % BW))
|
// rotate_left: (X << (S % BW)) | (X >> ((BW - S) % BW))
|
||||||
// rotate_right: (X << ((BW - S) % BW)) | (X >> (S % BW))
|
// rotate_right: (X << ((BW - S) % BW)) | (X >> (S % BW))
|
||||||
let width = C_uint(Type::ix(cx, width), width);
|
let width = CodegenCx::c_uint(Type::ix(cx, width), width);
|
||||||
let shift = bx.urem(raw_shift, width);
|
let shift = bx.urem(raw_shift, width);
|
||||||
let inv_shift = bx.urem(bx.sub(width, raw_shift), width);
|
let inv_shift = bx.urem(bx.sub(width, raw_shift), width);
|
||||||
let shift1 = bx.shl(val, if is_left { shift } else { inv_shift });
|
let shift1 = bx.shl(val, if is_left { shift } else { inv_shift });
|
||||||
|
@ -717,7 +725,7 @@ fn copy_intrinsic(
|
||||||
) -> &'ll Value {
|
) -> &'ll Value {
|
||||||
let cx = bx.cx;
|
let cx = bx.cx;
|
||||||
let (size, align) = cx.size_and_align_of(ty);
|
let (size, align) = cx.size_and_align_of(ty);
|
||||||
let size = C_usize(cx, size.bytes());
|
let size = CodegenCx::c_usize(cx, size.bytes());
|
||||||
let align = align.abi();
|
let align = align.abi();
|
||||||
let dst_ptr = bx.pointercast(dst, Type::i8p(cx));
|
let dst_ptr = bx.pointercast(dst, Type::i8p(cx));
|
||||||
let src_ptr = bx.pointercast(src, Type::i8p(cx));
|
let src_ptr = bx.pointercast(src, Type::i8p(cx));
|
||||||
|
@ -738,8 +746,8 @@ fn memset_intrinsic(
|
||||||
) -> &'ll Value {
|
) -> &'ll Value {
|
||||||
let cx = bx.cx;
|
let cx = bx.cx;
|
||||||
let (size, align) = cx.size_and_align_of(ty);
|
let (size, align) = cx.size_and_align_of(ty);
|
||||||
let size = C_usize(cx, size.bytes());
|
let size = CodegenCx::c_usize(cx, size.bytes());
|
||||||
let align = C_i32(cx, align.abi() as i32);
|
let align = CodegenCx::c_i32(cx, align.abi() as i32);
|
||||||
let dst = bx.pointercast(dst, Type::i8p(cx));
|
let dst = bx.pointercast(dst, Type::i8p(cx));
|
||||||
call_memset(bx, dst, val, bx.mul(size, count), align, volatile)
|
call_memset(bx, dst, val, bx.mul(size, count), align, volatile)
|
||||||
}
|
}
|
||||||
|
@ -755,7 +763,7 @@ fn try_intrinsic(
|
||||||
if bx.sess().no_landing_pads() {
|
if bx.sess().no_landing_pads() {
|
||||||
bx.call(func, &[data], None);
|
bx.call(func, &[data], None);
|
||||||
let ptr_align = bx.tcx().data_layout.pointer_align;
|
let ptr_align = bx.tcx().data_layout.pointer_align;
|
||||||
bx.store(C_null(Type::i8p(&bx.cx)), dest, ptr_align);
|
bx.store(CodegenCx::c_null(Type::i8p(&bx.cx)), dest, ptr_align);
|
||||||
} else if wants_msvc_seh(bx.sess()) {
|
} else if wants_msvc_seh(bx.sess()) {
|
||||||
codegen_msvc_try(bx, cx, func, data, local_ptr, dest);
|
codegen_msvc_try(bx, cx, func, data, local_ptr, dest);
|
||||||
} else {
|
} else {
|
||||||
|
@ -836,7 +844,7 @@ fn codegen_msvc_try(
|
||||||
let slot = bx.alloca(i64p, "slot", ptr_align);
|
let slot = bx.alloca(i64p, "slot", ptr_align);
|
||||||
bx.invoke(func, &[data], normal.llbb(), catchswitch.llbb(), None);
|
bx.invoke(func, &[data], normal.llbb(), catchswitch.llbb(), None);
|
||||||
|
|
||||||
normal.ret(C_i32(cx, 0));
|
normal.ret(CodegenCx::c_i32(cx, 0));
|
||||||
|
|
||||||
let cs = catchswitch.catch_switch(None, None, 1);
|
let cs = catchswitch.catch_switch(None, None, 1);
|
||||||
catchswitch.add_handler(cs, catchpad.llbb());
|
catchswitch.add_handler(cs, catchpad.llbb());
|
||||||
|
@ -846,19 +854,19 @@ fn codegen_msvc_try(
|
||||||
Some(did) => ::consts::get_static(cx, did),
|
Some(did) => ::consts::get_static(cx, did),
|
||||||
None => bug!("msvc_try_filter not defined"),
|
None => bug!("msvc_try_filter not defined"),
|
||||||
};
|
};
|
||||||
let tok = catchpad.catch_pad(cs, &[tydesc, C_i32(cx, 0), slot]);
|
let tok = catchpad.catch_pad(cs, &[tydesc, CodegenCx::c_i32(cx, 0), slot]);
|
||||||
let addr = catchpad.load(slot, ptr_align);
|
let addr = catchpad.load(slot, ptr_align);
|
||||||
|
|
||||||
let i64_align = bx.tcx().data_layout.i64_align;
|
let i64_align = bx.tcx().data_layout.i64_align;
|
||||||
let arg1 = catchpad.load(addr, i64_align);
|
let arg1 = catchpad.load(addr, i64_align);
|
||||||
let val1 = C_i32(cx, 1);
|
let val1 = CodegenCx::c_i32(cx, 1);
|
||||||
let arg2 = catchpad.load(catchpad.inbounds_gep(addr, &[val1]), i64_align);
|
let arg2 = catchpad.load(catchpad.inbounds_gep(addr, &[val1]), i64_align);
|
||||||
let local_ptr = catchpad.bitcast(local_ptr, i64p);
|
let local_ptr = catchpad.bitcast(local_ptr, i64p);
|
||||||
catchpad.store(arg1, local_ptr, i64_align);
|
catchpad.store(arg1, local_ptr, i64_align);
|
||||||
catchpad.store(arg2, catchpad.inbounds_gep(local_ptr, &[val1]), i64_align);
|
catchpad.store(arg2, catchpad.inbounds_gep(local_ptr, &[val1]), i64_align);
|
||||||
catchpad.catch_ret(tok, caught.llbb());
|
catchpad.catch_ret(tok, caught.llbb());
|
||||||
|
|
||||||
caught.ret(C_i32(cx, 1));
|
caught.ret(CodegenCx::c_i32(cx, 1));
|
||||||
});
|
});
|
||||||
|
|
||||||
// Note that no invoke is used here because by definition this function
|
// Note that no invoke is used here because by definition this function
|
||||||
|
@ -914,7 +922,7 @@ fn codegen_gnu_try(
|
||||||
let data = llvm::get_param(bx.llfn(), 1);
|
let data = llvm::get_param(bx.llfn(), 1);
|
||||||
let local_ptr = llvm::get_param(bx.llfn(), 2);
|
let local_ptr = llvm::get_param(bx.llfn(), 2);
|
||||||
bx.invoke(func, &[data], then.llbb(), catch.llbb(), None);
|
bx.invoke(func, &[data], then.llbb(), catch.llbb(), None);
|
||||||
then.ret(C_i32(cx, 0));
|
then.ret(CodegenCx::c_i32(cx, 0));
|
||||||
|
|
||||||
// Type indicator for the exception being thrown.
|
// Type indicator for the exception being thrown.
|
||||||
//
|
//
|
||||||
|
@ -924,11 +932,11 @@ fn codegen_gnu_try(
|
||||||
// rust_try ignores the selector.
|
// rust_try ignores the selector.
|
||||||
let lpad_ty = Type::struct_(cx, &[Type::i8p(cx), Type::i32(cx)], false);
|
let lpad_ty = Type::struct_(cx, &[Type::i8p(cx), Type::i32(cx)], false);
|
||||||
let vals = catch.landing_pad(lpad_ty, bx.cx.eh_personality(), 1);
|
let vals = catch.landing_pad(lpad_ty, bx.cx.eh_personality(), 1);
|
||||||
catch.add_clause(vals, C_null(Type::i8p(cx)));
|
catch.add_clause(vals, CodegenCx::c_null(Type::i8p(cx)));
|
||||||
let ptr = catch.extract_value(vals, 0);
|
let ptr = catch.extract_value(vals, 0);
|
||||||
let ptr_align = bx.tcx().data_layout.pointer_align;
|
let ptr_align = bx.tcx().data_layout.pointer_align;
|
||||||
catch.store(ptr, catch.bitcast(local_ptr, Type::i8p(cx).ptr_to()), ptr_align);
|
catch.store(ptr, catch.bitcast(local_ptr, Type::i8p(cx).ptr_to()), ptr_align);
|
||||||
catch.ret(C_i32(cx, 1));
|
catch.ret(CodegenCx::c_i32(cx, 1));
|
||||||
});
|
});
|
||||||
|
|
||||||
// Note that no invoke is used here because by definition this function
|
// Note that no invoke is used here because by definition this function
|
||||||
|
@ -1106,8 +1114,8 @@ fn generic_simd_intrinsic(
|
||||||
let indices: Option<Vec<_>> = (0..n)
|
let indices: Option<Vec<_>> = (0..n)
|
||||||
.map(|i| {
|
.map(|i| {
|
||||||
let arg_idx = i;
|
let arg_idx = i;
|
||||||
let val = const_get_elt(vector, i as u64);
|
let val = CodegenCx::const_get_elt(vector, i as u64);
|
||||||
match const_to_opt_u128(val, true) {
|
match CodegenCx::const_to_opt_u128(val, true) {
|
||||||
None => {
|
None => {
|
||||||
emit_error!("shuffle index #{} is not a constant", arg_idx);
|
emit_error!("shuffle index #{} is not a constant", arg_idx);
|
||||||
None
|
None
|
||||||
|
@ -1117,18 +1125,18 @@ fn generic_simd_intrinsic(
|
||||||
arg_idx, total_len);
|
arg_idx, total_len);
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
Some(idx) => Some(C_i32(bx.cx, idx as i32)),
|
Some(idx) => Some(CodegenCx::c_i32(bx.cx, idx as i32)),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
let indices = match indices {
|
let indices = match indices {
|
||||||
Some(i) => i,
|
Some(i) => i,
|
||||||
None => return Ok(C_null(llret_ty))
|
None => return Ok(CodegenCx::c_null(llret_ty))
|
||||||
};
|
};
|
||||||
|
|
||||||
return Ok(bx.shuffle_vector(args[0].immediate(),
|
return Ok(bx.shuffle_vector(args[0].immediate(),
|
||||||
args[1].immediate(),
|
args[1].immediate(),
|
||||||
C_vector(&indices)))
|
CodegenCx::c_vector(&indices)))
|
||||||
}
|
}
|
||||||
|
|
||||||
if name == "simd_insert" {
|
if name == "simd_insert" {
|
||||||
|
@ -1379,7 +1387,7 @@ fn generic_simd_intrinsic(
|
||||||
|
|
||||||
// Alignment of T, must be a constant integer value:
|
// Alignment of T, must be a constant integer value:
|
||||||
let alignment_ty = Type::i32(bx.cx);
|
let alignment_ty = Type::i32(bx.cx);
|
||||||
let alignment = C_i32(bx.cx, bx.cx.align_of(in_elem).abi() as i32);
|
let alignment = CodegenCx::c_i32(bx.cx, bx.cx.align_of(in_elem).abi() as i32);
|
||||||
|
|
||||||
// Truncate the mask vector to a vector of i1s:
|
// Truncate the mask vector to a vector of i1s:
|
||||||
let (mask, mask_ty) = {
|
let (mask, mask_ty) = {
|
||||||
|
@ -1479,7 +1487,7 @@ fn generic_simd_intrinsic(
|
||||||
|
|
||||||
// Alignment of T, must be a constant integer value:
|
// Alignment of T, must be a constant integer value:
|
||||||
let alignment_ty = Type::i32(bx.cx);
|
let alignment_ty = Type::i32(bx.cx);
|
||||||
let alignment = C_i32(bx.cx, bx.cx.align_of(in_elem).abi() as i32);
|
let alignment = CodegenCx::c_i32(bx.cx, bx.cx.align_of(in_elem).abi() as i32);
|
||||||
|
|
||||||
// Truncate the mask vector to a vector of i1s:
|
// Truncate the mask vector to a vector of i1s:
|
||||||
let (mask, mask_ty) = {
|
let (mask, mask_ty) = {
|
||||||
|
@ -1541,7 +1549,7 @@ fn generic_simd_intrinsic(
|
||||||
// code is generated
|
// code is generated
|
||||||
// * if the accumulator of the fmul isn't 1, incorrect
|
// * if the accumulator of the fmul isn't 1, incorrect
|
||||||
// code is generated
|
// code is generated
|
||||||
match const_get_real(acc) {
|
match CodegenCx::const_get_real(acc) {
|
||||||
None => return_error!("accumulator of {} is not a constant", $name),
|
None => return_error!("accumulator of {} is not a constant", $name),
|
||||||
Some((v, loses_info)) => {
|
Some((v, loses_info)) => {
|
||||||
if $name.contains("mul") && v != 1.0_f64 {
|
if $name.contains("mul") && v != 1.0_f64 {
|
||||||
|
@ -1557,8 +1565,8 @@ fn generic_simd_intrinsic(
|
||||||
} else {
|
} else {
|
||||||
// unordered arithmetic reductions do not:
|
// unordered arithmetic reductions do not:
|
||||||
match f.bit_width() {
|
match f.bit_width() {
|
||||||
32 => C_undef(Type::f32(bx.cx)),
|
32 => CodegenCx::c_undef(Type::f32(bx.cx)),
|
||||||
64 => C_undef(Type::f64(bx.cx)),
|
64 => CodegenCx::c_undef(Type::f64(bx.cx)),
|
||||||
v => {
|
v => {
|
||||||
return_error!(r#"
|
return_error!(r#"
|
||||||
unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#,
|
unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#,
|
||||||
|
|
|
@ -215,7 +215,7 @@ pub enum TypeKind {
|
||||||
Double = 3,
|
Double = 3,
|
||||||
X86_FP80 = 4,
|
X86_FP80 = 4,
|
||||||
FP128 = 5,
|
FP128 = 5,
|
||||||
PPC_FP128 = 6,
|
PPc_FP128 = 6,
|
||||||
Label = 7,
|
Label = 7,
|
||||||
Integer = 8,
|
Integer = 8,
|
||||||
Function = 9,
|
Function = 9,
|
||||||
|
|
|
@ -10,14 +10,14 @@
|
||||||
|
|
||||||
use abi::{FnType, FnTypeExt};
|
use abi::{FnType, FnTypeExt};
|
||||||
use callee;
|
use callee;
|
||||||
use common::*;
|
use context::CodegenCx;
|
||||||
use builder::Builder;
|
use builder::Builder;
|
||||||
use consts;
|
use consts;
|
||||||
use monomorphize;
|
use monomorphize;
|
||||||
use type_::Type;
|
use type_::Type;
|
||||||
use value::Value;
|
use value::Value;
|
||||||
|
|
||||||
use interfaces::BuilderMethods;
|
use interfaces::{BuilderMethods, CommonMethods};
|
||||||
|
|
||||||
use rustc::ty::{self, Ty};
|
use rustc::ty::{self, Ty};
|
||||||
use rustc::ty::layout::HasDataLayout;
|
use rustc::ty::layout::HasDataLayout;
|
||||||
|
@ -43,7 +43,10 @@ impl<'a, 'tcx> VirtualIndex {
|
||||||
|
|
||||||
let llvtable = bx.pointercast(llvtable, fn_ty.ptr_to_llvm_type(bx.cx).ptr_to());
|
let llvtable = bx.pointercast(llvtable, fn_ty.ptr_to_llvm_type(bx.cx).ptr_to());
|
||||||
let ptr_align = bx.tcx().data_layout.pointer_align;
|
let ptr_align = bx.tcx().data_layout.pointer_align;
|
||||||
let ptr = bx.load(bx.inbounds_gep(llvtable, &[C_usize(bx.cx, self.0)]), ptr_align);
|
let ptr = bx.load(
|
||||||
|
bx.inbounds_gep(llvtable, &[CodegenCx::c_usize(bx.cx, self.0)]),
|
||||||
|
ptr_align
|
||||||
|
);
|
||||||
bx.nonnull_metadata(ptr);
|
bx.nonnull_metadata(ptr);
|
||||||
// Vtable loads are invariant
|
// Vtable loads are invariant
|
||||||
bx.set_invariant_load(ptr);
|
bx.set_invariant_load(ptr);
|
||||||
|
@ -60,7 +63,10 @@ impl<'a, 'tcx> VirtualIndex {
|
||||||
|
|
||||||
let llvtable = bx.pointercast(llvtable, Type::isize(bx.cx).ptr_to());
|
let llvtable = bx.pointercast(llvtable, Type::isize(bx.cx).ptr_to());
|
||||||
let usize_align = bx.tcx().data_layout.pointer_align;
|
let usize_align = bx.tcx().data_layout.pointer_align;
|
||||||
let ptr = bx.load(bx.inbounds_gep(llvtable, &[C_usize(bx.cx, self.0)]), usize_align);
|
let ptr = bx.load(
|
||||||
|
bx.inbounds_gep(llvtable, &[CodegenCx::c_usize(bx.cx, self.0)]),
|
||||||
|
usize_align
|
||||||
|
);
|
||||||
// Vtable loads are invariant
|
// Vtable loads are invariant
|
||||||
bx.set_invariant_load(ptr);
|
bx.set_invariant_load(ptr);
|
||||||
ptr
|
ptr
|
||||||
|
@ -90,7 +96,7 @@ pub fn get_vtable(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Not in the cache. Build it.
|
// Not in the cache. Build it.
|
||||||
let nullptr = C_null(Type::i8p(cx));
|
let nullptr = CodegenCx::c_null(Type::i8p(cx));
|
||||||
|
|
||||||
let methods = tcx.vtable_methods(trait_ref.with_self_ty(tcx, ty));
|
let methods = tcx.vtable_methods(trait_ref.with_self_ty(tcx, ty));
|
||||||
let methods = methods.iter().cloned().map(|opt_mth| {
|
let methods = methods.iter().cloned().map(|opt_mth| {
|
||||||
|
@ -106,11 +112,11 @@ pub fn get_vtable(
|
||||||
// /////////////////////////////////////////////////////////////////////////////////////////////
|
// /////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
let components: Vec<_> = [
|
let components: Vec<_> = [
|
||||||
callee::get_fn(cx, monomorphize::resolve_drop_in_place(cx.tcx, ty)),
|
callee::get_fn(cx, monomorphize::resolve_drop_in_place(cx.tcx, ty)),
|
||||||
C_usize(cx, size.bytes()),
|
CodegenCx::c_usize(cx, size.bytes()),
|
||||||
C_usize(cx, align.abi())
|
CodegenCx::c_usize(cx, align.abi())
|
||||||
].iter().cloned().chain(methods).collect();
|
].iter().cloned().chain(methods).collect();
|
||||||
|
|
||||||
let vtable_const = C_struct(cx, &components, false);
|
let vtable_const = CodegenCx::c_struct(cx, &components, false);
|
||||||
let align = cx.data_layout().pointer_align;
|
let align = cx.data_layout().pointer_align;
|
||||||
let vtable = consts::addr_of(cx, vtable_const, align, Some("vtable"));
|
let vtable = consts::addr_of(cx, vtable_const, align, Some("vtable"));
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,8 @@ use abi::{Abi, ArgType, ArgTypeExt, FnType, FnTypeExt, LlvmType, PassMode};
|
||||||
use base;
|
use base;
|
||||||
use callee;
|
use callee;
|
||||||
use builder::{Builder, MemFlags};
|
use builder::{Builder, MemFlags};
|
||||||
use common::{self, C_bool, C_str_slice, C_struct, C_u32, C_uint_big, C_undef, IntPredicate};
|
use common::{self, IntPredicate};
|
||||||
|
use context::CodegenCx;
|
||||||
use consts;
|
use consts;
|
||||||
use meth;
|
use meth;
|
||||||
use monomorphize;
|
use monomorphize;
|
||||||
|
@ -26,7 +27,7 @@ use type_of::LayoutLlvmExt;
|
||||||
use type_::Type;
|
use type_::Type;
|
||||||
use value::Value;
|
use value::Value;
|
||||||
|
|
||||||
use interfaces::BuilderMethods;
|
use interfaces::{BuilderMethods, CommonMethods};
|
||||||
|
|
||||||
use syntax::symbol::Symbol;
|
use syntax::symbol::Symbol;
|
||||||
use syntax_pos::Pos;
|
use syntax_pos::Pos;
|
||||||
|
@ -171,7 +172,7 @@ impl FunctionCx<'a, 'll, 'tcx, &'ll Value> {
|
||||||
slot.storage_dead(&bx);
|
slot.storage_dead(&bx);
|
||||||
|
|
||||||
if !bx.sess().target.target.options.custom_unwind_resume {
|
if !bx.sess().target.target.options.custom_unwind_resume {
|
||||||
let mut lp = C_undef(self.landing_pad_type());
|
let mut lp = CodegenCx::c_undef(self.landing_pad_type());
|
||||||
lp = bx.insert_value(lp, lp0, 0);
|
lp = bx.insert_value(lp, lp0, 0);
|
||||||
lp = bx.insert_value(lp, lp1, 1);
|
lp = bx.insert_value(lp, lp1, 1);
|
||||||
bx.resume(lp);
|
bx.resume(lp);
|
||||||
|
@ -209,7 +210,7 @@ impl FunctionCx<'a, 'll, 'tcx, &'ll Value> {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let switch_llty = bx.cx.layout_of(switch_ty).immediate_llvm_type(bx.cx);
|
let switch_llty = bx.cx.layout_of(switch_ty).immediate_llvm_type(bx.cx);
|
||||||
let llval = C_uint_big(switch_llty, values[0]);
|
let llval = CodegenCx::c_uint_big(switch_llty, values[0]);
|
||||||
let cmp = bx.icmp(IntPredicate::IntEQ, discr.immediate(), llval);
|
let cmp = bx.icmp(IntPredicate::IntEQ, discr.immediate(), llval);
|
||||||
bx.cond_br(cmp, lltrue, llfalse);
|
bx.cond_br(cmp, lltrue, llfalse);
|
||||||
}
|
}
|
||||||
|
@ -220,7 +221,7 @@ impl FunctionCx<'a, 'll, 'tcx, &'ll Value> {
|
||||||
values.len());
|
values.len());
|
||||||
let switch_llty = bx.cx.layout_of(switch_ty).immediate_llvm_type(bx.cx);
|
let switch_llty = bx.cx.layout_of(switch_ty).immediate_llvm_type(bx.cx);
|
||||||
for (&value, target) in values.iter().zip(targets) {
|
for (&value, target) in values.iter().zip(targets) {
|
||||||
let llval = C_uint_big(switch_llty, value);
|
let llval = CodegenCx::c_uint_big(switch_llty, value);
|
||||||
let llbb = llblock(self, *target);
|
let llbb = llblock(self, *target);
|
||||||
bx.add_case(switch, llval, llbb)
|
bx.add_case(switch, llval, llbb)
|
||||||
}
|
}
|
||||||
|
@ -323,7 +324,7 @@ impl FunctionCx<'a, 'll, 'tcx, &'ll Value> {
|
||||||
|
|
||||||
mir::TerminatorKind::Assert { ref cond, expected, ref msg, target, cleanup } => {
|
mir::TerminatorKind::Assert { ref cond, expected, ref msg, target, cleanup } => {
|
||||||
let cond = self.codegen_operand(&bx, cond).immediate();
|
let cond = self.codegen_operand(&bx, cond).immediate();
|
||||||
let mut const_cond = common::const_to_opt_u128(cond, false).map(|c| c == 1);
|
let mut const_cond = CodegenCx::const_to_opt_u128(cond, false).map(|c| c == 1);
|
||||||
|
|
||||||
// This case can currently arise only from functions marked
|
// This case can currently arise only from functions marked
|
||||||
// with #[rustc_inherit_overflow_checks] and inlined from
|
// with #[rustc_inherit_overflow_checks] and inlined from
|
||||||
|
@ -346,7 +347,7 @@ impl FunctionCx<'a, 'll, 'tcx, &'ll Value> {
|
||||||
|
|
||||||
// Pass the condition through llvm.expect for branch hinting.
|
// Pass the condition through llvm.expect for branch hinting.
|
||||||
let expect = bx.cx.get_intrinsic(&"llvm.expect.i1");
|
let expect = bx.cx.get_intrinsic(&"llvm.expect.i1");
|
||||||
let cond = bx.call(expect, &[cond, C_bool(bx.cx, expected)], None);
|
let cond = bx.call(expect, &[cond, CodegenCx::c_bool(bx.cx, expected)], None);
|
||||||
|
|
||||||
// Create the failure block and the conditional branch to it.
|
// Create the failure block and the conditional branch to it.
|
||||||
let lltarget = llblock(self, target);
|
let lltarget = llblock(self, target);
|
||||||
|
@ -364,9 +365,9 @@ impl FunctionCx<'a, 'll, 'tcx, &'ll Value> {
|
||||||
// Get the location information.
|
// Get the location information.
|
||||||
let loc = bx.sess().source_map().lookup_char_pos(span.lo());
|
let loc = bx.sess().source_map().lookup_char_pos(span.lo());
|
||||||
let filename = Symbol::intern(&loc.file.name.to_string()).as_str();
|
let filename = Symbol::intern(&loc.file.name.to_string()).as_str();
|
||||||
let filename = C_str_slice(bx.cx, filename);
|
let filename = CodegenCx::c_str_slice(bx.cx, filename);
|
||||||
let line = C_u32(bx.cx, loc.line as u32);
|
let line = CodegenCx::c_u32(bx.cx, loc.line as u32);
|
||||||
let col = C_u32(bx.cx, loc.col.to_usize() as u32 + 1);
|
let col = CodegenCx::c_u32(bx.cx, loc.col.to_usize() as u32 + 1);
|
||||||
let align = tcx.data_layout.aggregate_align
|
let align = tcx.data_layout.aggregate_align
|
||||||
.max(tcx.data_layout.i32_align)
|
.max(tcx.data_layout.i32_align)
|
||||||
.max(tcx.data_layout.pointer_align);
|
.max(tcx.data_layout.pointer_align);
|
||||||
|
@ -377,7 +378,8 @@ impl FunctionCx<'a, 'll, 'tcx, &'ll Value> {
|
||||||
let len = self.codegen_operand(&mut bx, len).immediate();
|
let len = self.codegen_operand(&mut bx, len).immediate();
|
||||||
let index = self.codegen_operand(&mut bx, index).immediate();
|
let index = self.codegen_operand(&mut bx, index).immediate();
|
||||||
|
|
||||||
let file_line_col = C_struct(bx.cx, &[filename, line, col], false);
|
let file_line_col = CodegenCx::c_struct(bx.cx,
|
||||||
|
&[filename, line, col], false);
|
||||||
let file_line_col = consts::addr_of(bx.cx,
|
let file_line_col = consts::addr_of(bx.cx,
|
||||||
file_line_col,
|
file_line_col,
|
||||||
align,
|
align,
|
||||||
|
@ -388,10 +390,12 @@ impl FunctionCx<'a, 'll, 'tcx, &'ll Value> {
|
||||||
_ => {
|
_ => {
|
||||||
let str = msg.description();
|
let str = msg.description();
|
||||||
let msg_str = Symbol::intern(str).as_str();
|
let msg_str = Symbol::intern(str).as_str();
|
||||||
let msg_str = C_str_slice(bx.cx, msg_str);
|
let msg_str = CodegenCx::c_str_slice(bx.cx, msg_str);
|
||||||
let msg_file_line_col = C_struct(bx.cx,
|
let msg_file_line_col = CodegenCx::c_struct(
|
||||||
&[msg_str, filename, line, col],
|
bx.cx,
|
||||||
false);
|
&[msg_str, filename, line, col],
|
||||||
|
false
|
||||||
|
);
|
||||||
let msg_file_line_col = consts::addr_of(bx.cx,
|
let msg_file_line_col = consts::addr_of(bx.cx,
|
||||||
msg_file_line_col,
|
msg_file_line_col,
|
||||||
align,
|
align,
|
||||||
|
@ -497,9 +501,9 @@ impl FunctionCx<'a, 'll, 'tcx, &'ll Value> {
|
||||||
{
|
{
|
||||||
let loc = bx.sess().source_map().lookup_char_pos(span.lo());
|
let loc = bx.sess().source_map().lookup_char_pos(span.lo());
|
||||||
let filename = Symbol::intern(&loc.file.name.to_string()).as_str();
|
let filename = Symbol::intern(&loc.file.name.to_string()).as_str();
|
||||||
let filename = C_str_slice(bx.cx, filename);
|
let filename = bx.cx.c_str_slice(filename);
|
||||||
let line = C_u32(bx.cx, loc.line as u32);
|
let line = bx.cx.c_u32(loc.line as u32);
|
||||||
let col = C_u32(bx.cx, loc.col.to_usize() as u32 + 1);
|
let col = bx.cx.c_u32(loc.col.to_usize() as u32 + 1);
|
||||||
let align = tcx.data_layout.aggregate_align
|
let align = tcx.data_layout.aggregate_align
|
||||||
.max(tcx.data_layout.i32_align)
|
.max(tcx.data_layout.i32_align)
|
||||||
.max(tcx.data_layout.pointer_align);
|
.max(tcx.data_layout.pointer_align);
|
||||||
|
@ -510,10 +514,11 @@ impl FunctionCx<'a, 'll, 'tcx, &'ll Value> {
|
||||||
if intrinsic == Some("init") { "zeroed" } else { "uninitialized" }
|
if intrinsic == Some("init") { "zeroed" } else { "uninitialized" }
|
||||||
);
|
);
|
||||||
let msg_str = Symbol::intern(&str).as_str();
|
let msg_str = Symbol::intern(&str).as_str();
|
||||||
let msg_str = C_str_slice(bx.cx, msg_str);
|
let msg_str = bx.cx.c_str_slice(msg_str);
|
||||||
let msg_file_line_col = C_struct(bx.cx,
|
let msg_file_line_col = bx.cx.c_struct(
|
||||||
&[msg_str, filename, line, col],
|
&[msg_str, filename, line, col],
|
||||||
false);
|
false,
|
||||||
|
);
|
||||||
let msg_file_line_col = consts::addr_of(bx.cx,
|
let msg_file_line_col = consts::addr_of(bx.cx,
|
||||||
msg_file_line_col,
|
msg_file_line_col,
|
||||||
align,
|
align,
|
||||||
|
@ -558,7 +563,7 @@ impl FunctionCx<'a, 'll, 'tcx, &'ll Value> {
|
||||||
let dest = match ret_dest {
|
let dest = match ret_dest {
|
||||||
_ if fn_ty.ret.is_indirect() => llargs[0],
|
_ if fn_ty.ret.is_indirect() => llargs[0],
|
||||||
ReturnDest::Nothing => {
|
ReturnDest::Nothing => {
|
||||||
C_undef(fn_ty.ret.memory_ty(bx.cx).ptr_to())
|
CodegenCx::c_undef(fn_ty.ret.memory_ty(bx.cx).ptr_to())
|
||||||
}
|
}
|
||||||
ReturnDest::IndirectOperand(dst, _) |
|
ReturnDest::IndirectOperand(dst, _) |
|
||||||
ReturnDest::Store(dst) => dst.llval,
|
ReturnDest::Store(dst) => dst.llval,
|
||||||
|
@ -739,7 +744,7 @@ impl FunctionCx<'a, 'll, 'tcx, &'ll Value> {
|
||||||
arg: &ArgType<'tcx, Ty<'tcx>>) {
|
arg: &ArgType<'tcx, Ty<'tcx>>) {
|
||||||
// Fill padding with undef value, where applicable.
|
// Fill padding with undef value, where applicable.
|
||||||
if let Some(ty) = arg.pad {
|
if let Some(ty) = arg.pad {
|
||||||
llargs.push(C_undef(ty.llvm_type(bx.cx)));
|
llargs.push(CodegenCx::c_undef(ty.llvm_type(bx.cx)));
|
||||||
}
|
}
|
||||||
|
|
||||||
if arg.is_ignore() {
|
if arg.is_ignore() {
|
||||||
|
|
|
@ -19,14 +19,13 @@ use rustc::ty::{self, Ty};
|
||||||
use rustc::ty::layout::{self, HasDataLayout, LayoutOf, Size};
|
use rustc::ty::layout::{self, HasDataLayout, LayoutOf, Size};
|
||||||
use builder::Builder;
|
use builder::Builder;
|
||||||
use common::{CodegenCx};
|
use common::{CodegenCx};
|
||||||
use common::{C_bytes, C_struct, C_uint_big, C_undef, C_usize};
|
|
||||||
use consts;
|
use consts;
|
||||||
use type_of::LayoutLlvmExt;
|
use type_of::LayoutLlvmExt;
|
||||||
use type_::Type;
|
use type_::Type;
|
||||||
use syntax::ast::Mutability;
|
use syntax::ast::Mutability;
|
||||||
use syntax::source_map::Span;
|
use syntax::source_map::Span;
|
||||||
use value::Value;
|
use value::Value;
|
||||||
use interfaces::BuilderMethods;
|
use interfaces::{BuilderMethods, CommonMethods};
|
||||||
|
|
||||||
use super::super::callee;
|
use super::super::callee;
|
||||||
use super::FunctionCx;
|
use super::FunctionCx;
|
||||||
|
@ -41,11 +40,11 @@ pub fn scalar_to_llvm(
|
||||||
match cv {
|
match cv {
|
||||||
Scalar::Bits { size: 0, .. } => {
|
Scalar::Bits { size: 0, .. } => {
|
||||||
assert_eq!(0, layout.value.size(cx).bytes());
|
assert_eq!(0, layout.value.size(cx).bytes());
|
||||||
C_undef(Type::ix(cx, 0))
|
CodegenCx::c_undef(Type::ix(cx, 0))
|
||||||
},
|
},
|
||||||
Scalar::Bits { bits, size } => {
|
Scalar::Bits { bits, size } => {
|
||||||
assert_eq!(size as u64, layout.value.size(cx).bytes());
|
assert_eq!(size as u64, layout.value.size(cx).bytes());
|
||||||
let llval = C_uint_big(Type::ix(cx, bitsize), bits);
|
let llval = CodegenCx::c_uint_big(Type::ix(cx, bitsize), bits);
|
||||||
if layout.value == layout::Pointer {
|
if layout.value == layout::Pointer {
|
||||||
unsafe { llvm::LLVMConstIntToPtr(llval, llty) }
|
unsafe { llvm::LLVMConstIntToPtr(llval, llty) }
|
||||||
} else {
|
} else {
|
||||||
|
@ -74,7 +73,7 @@ pub fn scalar_to_llvm(
|
||||||
};
|
};
|
||||||
let llval = unsafe { llvm::LLVMConstInBoundsGEP(
|
let llval = unsafe { llvm::LLVMConstInBoundsGEP(
|
||||||
consts::bitcast(base_addr, Type::i8p(cx)),
|
consts::bitcast(base_addr, Type::i8p(cx)),
|
||||||
&C_usize(cx, ptr.offset.bytes()),
|
&CodegenCx::c_usize(cx, ptr.offset.bytes()),
|
||||||
1,
|
1,
|
||||||
) };
|
) };
|
||||||
if layout.value != layout::Pointer {
|
if layout.value != layout::Pointer {
|
||||||
|
@ -97,7 +96,7 @@ pub fn const_alloc_to_llvm(cx: &CodegenCx<'ll, '_>, alloc: &Allocation) -> &'ll
|
||||||
assert_eq!(offset as usize as u64, offset);
|
assert_eq!(offset as usize as u64, offset);
|
||||||
let offset = offset as usize;
|
let offset = offset as usize;
|
||||||
if offset > next_offset {
|
if offset > next_offset {
|
||||||
llvals.push(C_bytes(cx, &alloc.bytes[next_offset..offset]));
|
llvals.push(CodegenCx::c_bytes(cx, &alloc.bytes[next_offset..offset]));
|
||||||
}
|
}
|
||||||
let ptr_offset = read_target_uint(
|
let ptr_offset = read_target_uint(
|
||||||
dl.endian,
|
dl.endian,
|
||||||
|
@ -115,10 +114,10 @@ pub fn const_alloc_to_llvm(cx: &CodegenCx<'ll, '_>, alloc: &Allocation) -> &'ll
|
||||||
next_offset = offset + pointer_size;
|
next_offset = offset + pointer_size;
|
||||||
}
|
}
|
||||||
if alloc.bytes.len() >= next_offset {
|
if alloc.bytes.len() >= next_offset {
|
||||||
llvals.push(C_bytes(cx, &alloc.bytes[next_offset ..]));
|
llvals.push(CodegenCx::c_bytes(cx, &alloc.bytes[next_offset ..]));
|
||||||
}
|
}
|
||||||
|
|
||||||
C_struct(cx, &llvals, true)
|
CodegenCx::c_struct(cx, &llvals, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn codegen_static_initializer(
|
pub fn codegen_static_initializer(
|
||||||
|
@ -208,7 +207,7 @@ impl FunctionCx<'a, 'll, 'tcx, &'ll Value> {
|
||||||
bug!("simd shuffle field {:?}", field)
|
bug!("simd shuffle field {:?}", field)
|
||||||
}
|
}
|
||||||
}).collect();
|
}).collect();
|
||||||
let llval = C_struct(bx.cx, &values?, false);
|
let llval = CodegenCx::c_struct(bx.cx, &values?, false);
|
||||||
Ok((llval, c.ty))
|
Ok((llval, c.ty))
|
||||||
})
|
})
|
||||||
.unwrap_or_else(|_| {
|
.unwrap_or_else(|_| {
|
||||||
|
@ -219,7 +218,7 @@ impl FunctionCx<'a, 'll, 'tcx, &'ll Value> {
|
||||||
// We've errored, so we don't have to produce working code.
|
// We've errored, so we don't have to produce working code.
|
||||||
let ty = self.monomorphize(&ty);
|
let ty = self.monomorphize(&ty);
|
||||||
let llty = bx.cx.layout_of(ty).llvm_type(bx.cx);
|
let llty = bx.cx.layout_of(ty).llvm_type(bx.cx);
|
||||||
(C_undef(llty), ty)
|
(CodegenCx::c_undef(llty), ty)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,6 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use common::{C_i32, C_null};
|
|
||||||
use libc::c_uint;
|
use libc::c_uint;
|
||||||
use llvm::{self, BasicBlock};
|
use llvm::{self, BasicBlock};
|
||||||
use llvm::debuginfo::DIScope;
|
use llvm::debuginfo::DIScope;
|
||||||
|
@ -26,7 +25,7 @@ use monomorphize::Instance;
|
||||||
use abi::{ArgTypeExt, FnType, FnTypeExt, PassMode};
|
use abi::{ArgTypeExt, FnType, FnTypeExt, PassMode};
|
||||||
use type_::Type;
|
use type_::Type;
|
||||||
use value::Value;
|
use value::Value;
|
||||||
use interfaces::BuilderMethods;
|
use interfaces::{BuilderMethods, CommonMethods};
|
||||||
|
|
||||||
use syntax_pos::{DUMMY_SP, NO_EXPANSION, BytePos, Span};
|
use syntax_pos::{DUMMY_SP, NO_EXPANSION, BytePos, Span};
|
||||||
use syntax::symbol::keywords;
|
use syntax::symbol::keywords;
|
||||||
|
@ -421,8 +420,8 @@ fn create_funclets(
|
||||||
// C++ personality function, but `catch (...)` has no type so
|
// C++ personality function, but `catch (...)` has no type so
|
||||||
// it's null. The 64 here is actually a bitfield which
|
// it's null. The 64 here is actually a bitfield which
|
||||||
// represents that this is a catch-all block.
|
// represents that this is a catch-all block.
|
||||||
let null = C_null(Type::i8p(bx.cx));
|
let null = CodegenCx::c_null(Type::i8p(bx.cx));
|
||||||
let sixty_four = C_i32(bx.cx, 64);
|
let sixty_four = CodegenCx::c_i32(bx.cx, 64);
|
||||||
cleanup = cp_bx.catch_pad(cs, &[null, sixty_four, null]);
|
cleanup = cp_bx.catch_pad(cs, &[null, sixty_four, null]);
|
||||||
cp_bx.br(llbb);
|
cp_bx.br(llbb);
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,14 +14,14 @@ use rustc::ty;
|
||||||
use rustc::ty::layout::{self, Align, LayoutOf, TyLayout};
|
use rustc::ty::layout::{self, Align, LayoutOf, TyLayout};
|
||||||
|
|
||||||
use base;
|
use base;
|
||||||
use common::{CodegenCx, C_undef, C_usize};
|
use common::CodegenCx;
|
||||||
use builder::{Builder, MemFlags};
|
use builder::{Builder, MemFlags};
|
||||||
use value::Value;
|
use value::Value;
|
||||||
use type_of::LayoutLlvmExt;
|
use type_of::LayoutLlvmExt;
|
||||||
use type_::Type;
|
use type_::Type;
|
||||||
use glue;
|
use glue;
|
||||||
|
|
||||||
use interfaces::BuilderMethods;
|
use interfaces::{BuilderMethods, CommonMethods};
|
||||||
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
|
@ -73,7 +73,7 @@ impl OperandRef<'tcx, &'ll Value> {
|
||||||
layout: TyLayout<'tcx>) -> OperandRef<'tcx, &'ll Value> {
|
layout: TyLayout<'tcx>) -> OperandRef<'tcx, &'ll Value> {
|
||||||
assert!(layout.is_zst());
|
assert!(layout.is_zst());
|
||||||
OperandRef {
|
OperandRef {
|
||||||
val: OperandValue::Immediate(C_undef(layout.immediate_llvm_type(cx))),
|
val: OperandValue::Immediate(CodegenCx::c_undef(layout.immediate_llvm_type(cx))),
|
||||||
layout
|
layout
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -167,7 +167,7 @@ impl OperandRef<'tcx, &'ll Value> {
|
||||||
debug!("Operand::immediate_or_packed_pair: packing {:?} into {:?}",
|
debug!("Operand::immediate_or_packed_pair: packing {:?} into {:?}",
|
||||||
self, llty);
|
self, llty);
|
||||||
// Reconstruct the immediate aggregate.
|
// Reconstruct the immediate aggregate.
|
||||||
let mut llpair = C_undef(llty);
|
let mut llpair = CodegenCx::c_undef(llty);
|
||||||
llpair = bx.insert_value(llpair, base::from_immediate(bx, a), 0);
|
llpair = bx.insert_value(llpair, base::from_immediate(bx, a), 0);
|
||||||
llpair = bx.insert_value(llpair, base::from_immediate(bx, b), 1);
|
llpair = bx.insert_value(llpair, base::from_immediate(bx, b), 1);
|
||||||
llpair
|
llpair
|
||||||
|
@ -232,7 +232,7 @@ impl OperandRef<'tcx, &'ll Value> {
|
||||||
// `#[repr(simd)]` types are also immediate.
|
// `#[repr(simd)]` types are also immediate.
|
||||||
(OperandValue::Immediate(llval), &layout::Abi::Vector { .. }) => {
|
(OperandValue::Immediate(llval), &layout::Abi::Vector { .. }) => {
|
||||||
OperandValue::Immediate(
|
OperandValue::Immediate(
|
||||||
bx.extract_element(llval, C_usize(bx.cx, i as u64)))
|
bx.extract_element(llval, CodegenCx::c_usize(bx.cx, i as u64)))
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => bug!("OperandRef::extract_field({:?}): not applicable", self)
|
_ => bug!("OperandRef::extract_field({:?}): not applicable", self)
|
||||||
|
@ -463,7 +463,7 @@ impl FunctionCx<'a, 'll, 'tcx, &'ll Value> {
|
||||||
// We've errored, so we don't have to produce working code.
|
// We've errored, so we don't have to produce working code.
|
||||||
let layout = bx.cx.layout_of(ty);
|
let layout = bx.cx.layout_of(ty);
|
||||||
PlaceRef::new_sized(
|
PlaceRef::new_sized(
|
||||||
C_undef(layout.llvm_type(bx.cx).ptr_to()),
|
CodegenCx::c_undef(layout.llvm_type(bx.cx).ptr_to()),
|
||||||
layout,
|
layout,
|
||||||
layout.align,
|
layout.align,
|
||||||
).load(bx)
|
).load(bx)
|
||||||
|
|
|
@ -15,7 +15,7 @@ use rustc::mir;
|
||||||
use rustc::mir::tcx::PlaceTy;
|
use rustc::mir::tcx::PlaceTy;
|
||||||
use base;
|
use base;
|
||||||
use builder::Builder;
|
use builder::Builder;
|
||||||
use common::{CodegenCx, C_undef, C_usize, C_u8, C_u32, C_uint, C_null, C_uint_big, IntPredicate};
|
use common::{CodegenCx, IntPredicate};
|
||||||
use consts;
|
use consts;
|
||||||
use type_of::LayoutLlvmExt;
|
use type_of::LayoutLlvmExt;
|
||||||
use type_::Type;
|
use type_::Type;
|
||||||
|
@ -23,7 +23,7 @@ use value::Value;
|
||||||
use glue;
|
use glue;
|
||||||
use mir::constant::const_alloc_to_llvm;
|
use mir::constant::const_alloc_to_llvm;
|
||||||
|
|
||||||
use interfaces::BuilderMethods;
|
use interfaces::{BuilderMethods, CommonMethods};
|
||||||
|
|
||||||
use super::{FunctionCx, LocalRef};
|
use super::{FunctionCx, LocalRef};
|
||||||
use super::operand::{OperandRef, OperandValue};
|
use super::operand::{OperandRef, OperandValue};
|
||||||
|
@ -69,7 +69,7 @@ impl PlaceRef<'tcx, &'ll Value> {
|
||||||
|
|
||||||
let llval = unsafe { LLVMConstInBoundsGEP(
|
let llval = unsafe { LLVMConstInBoundsGEP(
|
||||||
consts::bitcast(base_addr, Type::i8p(bx.cx)),
|
consts::bitcast(base_addr, Type::i8p(bx.cx)),
|
||||||
&C_usize(bx.cx, offset.bytes()),
|
&CodegenCx::c_usize(bx.cx, offset.bytes()),
|
||||||
1,
|
1,
|
||||||
)};
|
)};
|
||||||
let llval = consts::bitcast(llval, layout.llvm_type(bx.cx).ptr_to());
|
let llval = consts::bitcast(llval, layout.llvm_type(bx.cx).ptr_to());
|
||||||
|
@ -103,7 +103,7 @@ impl PlaceRef<'tcx, &'ll Value> {
|
||||||
assert_eq!(count, 0);
|
assert_eq!(count, 0);
|
||||||
self.llextra.unwrap()
|
self.llextra.unwrap()
|
||||||
} else {
|
} else {
|
||||||
C_usize(cx, count)
|
CodegenCx::c_usize(cx, count)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
bug!("unexpected layout `{:#?}` in PlaceRef::len", self.layout)
|
bug!("unexpected layout `{:#?}` in PlaceRef::len", self.layout)
|
||||||
|
@ -248,7 +248,7 @@ impl PlaceRef<'tcx, &'ll Value> {
|
||||||
|
|
||||||
let meta = self.llextra;
|
let meta = self.llextra;
|
||||||
|
|
||||||
let unaligned_offset = C_usize(cx, offset.bytes());
|
let unaligned_offset = CodegenCx::c_usize(cx, offset.bytes());
|
||||||
|
|
||||||
// Get the alignment of the field
|
// Get the alignment of the field
|
||||||
let (_, unsized_align) = glue::size_and_align_of_dst(bx, field.ty, meta);
|
let (_, unsized_align) = glue::size_and_align_of_dst(bx, field.ty, meta);
|
||||||
|
@ -259,7 +259,7 @@ impl PlaceRef<'tcx, &'ll Value> {
|
||||||
// (unaligned offset + (align - 1)) & -align
|
// (unaligned offset + (align - 1)) & -align
|
||||||
|
|
||||||
// Calculate offset
|
// Calculate offset
|
||||||
let align_sub_1 = bx.sub(unsized_align, C_usize(cx, 1u64));
|
let align_sub_1 = bx.sub(unsized_align, CodegenCx::c_usize(cx, 1u64));
|
||||||
let offset = bx.and(bx.add(unaligned_offset, align_sub_1),
|
let offset = bx.and(bx.add(unaligned_offset, align_sub_1),
|
||||||
bx.neg(unsized_align));
|
bx.neg(unsized_align));
|
||||||
|
|
||||||
|
@ -289,14 +289,14 @@ impl PlaceRef<'tcx, &'ll Value> {
|
||||||
) -> &'ll Value {
|
) -> &'ll Value {
|
||||||
let cast_to = bx.cx.layout_of(cast_to).immediate_llvm_type(bx.cx);
|
let cast_to = bx.cx.layout_of(cast_to).immediate_llvm_type(bx.cx);
|
||||||
if self.layout.abi.is_uninhabited() {
|
if self.layout.abi.is_uninhabited() {
|
||||||
return C_undef(cast_to);
|
return CodegenCx::c_undef(cast_to);
|
||||||
}
|
}
|
||||||
match self.layout.variants {
|
match self.layout.variants {
|
||||||
layout::Variants::Single { index } => {
|
layout::Variants::Single { index } => {
|
||||||
let discr_val = self.layout.ty.ty_adt_def().map_or(
|
let discr_val = self.layout.ty.ty_adt_def().map_or(
|
||||||
index.as_u32() as u128,
|
index.as_u32() as u128,
|
||||||
|def| def.discriminant_for_variant(bx.cx.tcx, index).val);
|
|def| def.discriminant_for_variant(bx.cx.tcx, index).val);
|
||||||
return C_uint_big(cast_to, discr_val);
|
return CodegenCx::c_uint_big(cast_to, discr_val);
|
||||||
}
|
}
|
||||||
layout::Variants::Tagged { .. } |
|
layout::Variants::Tagged { .. } |
|
||||||
layout::Variants::NicheFilling { .. } => {},
|
layout::Variants::NicheFilling { .. } => {},
|
||||||
|
@ -327,22 +327,23 @@ impl PlaceRef<'tcx, &'ll Value> {
|
||||||
if niche_variants.start() == niche_variants.end() {
|
if niche_variants.start() == niche_variants.end() {
|
||||||
// FIXME(eddyb) Check the actual primitive type here.
|
// FIXME(eddyb) Check the actual primitive type here.
|
||||||
let niche_llval = if niche_start == 0 {
|
let niche_llval = if niche_start == 0 {
|
||||||
// HACK(eddyb) Using `C_null` as it works on all types.
|
// HACK(eddyb) Using `c_null` as it works on all types.
|
||||||
C_null(niche_llty)
|
CodegenCx::c_null(niche_llty)
|
||||||
} else {
|
} else {
|
||||||
C_uint_big(niche_llty, niche_start)
|
CodegenCx::c_uint_big(niche_llty, niche_start)
|
||||||
};
|
};
|
||||||
bx.select(bx.icmp(IntPredicate::IntEQ, lldiscr, niche_llval),
|
bx.select(bx.icmp(IntPredicate::IntEQ, lldiscr, niche_llval),
|
||||||
C_uint(cast_to, niche_variants.start().as_u32() as u64),
|
CodegenCx::c_uint(cast_to, niche_variants.start().as_u32() as u64),
|
||||||
C_uint(cast_to, dataful_variant.as_u32() as u64))
|
CodegenCx::c_uint(cast_to, dataful_variant.as_u32() as u64))
|
||||||
} else {
|
} else {
|
||||||
// Rebase from niche values to discriminant values.
|
// Rebase from niche values to discriminant values.
|
||||||
let delta = niche_start.wrapping_sub(niche_variants.start().as_u32() as u128);
|
let delta = niche_start.wrapping_sub(niche_variants.start().as_u32() as u128);
|
||||||
let lldiscr = bx.sub(lldiscr, C_uint_big(niche_llty, delta));
|
let lldiscr = bx.sub(lldiscr, CodegenCx::c_uint_big(niche_llty, delta));
|
||||||
let lldiscr_max = C_uint(niche_llty, niche_variants.end().as_u32() as u64);
|
let lldiscr_max =
|
||||||
|
CodegenCx::c_uint(niche_llty, niche_variants.end().as_u32() as u64);
|
||||||
bx.select(bx.icmp(IntPredicate::IntULE, lldiscr, lldiscr_max),
|
bx.select(bx.icmp(IntPredicate::IntULE, lldiscr, lldiscr_max),
|
||||||
bx.intcast(lldiscr, cast_to, false),
|
bx.intcast(lldiscr, cast_to, false),
|
||||||
C_uint(cast_to, dataful_variant.as_u32() as u64))
|
CodegenCx::c_uint(cast_to, dataful_variant.as_u32() as u64))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -364,7 +365,7 @@ impl PlaceRef<'tcx, &'ll Value> {
|
||||||
.discriminant_for_variant(bx.tcx(), variant_index)
|
.discriminant_for_variant(bx.tcx(), variant_index)
|
||||||
.val;
|
.val;
|
||||||
bx.store(
|
bx.store(
|
||||||
C_uint_big(ptr.layout.llvm_type(bx.cx), to),
|
CodegenCx::c_uint_big(ptr.layout.llvm_type(bx.cx), to),
|
||||||
ptr.llval,
|
ptr.llval,
|
||||||
ptr.align);
|
ptr.align);
|
||||||
}
|
}
|
||||||
|
@ -380,10 +381,10 @@ impl PlaceRef<'tcx, &'ll Value> {
|
||||||
// Issue #34427: As workaround for LLVM bug on ARM,
|
// Issue #34427: As workaround for LLVM bug on ARM,
|
||||||
// use memset of 0 before assigning niche value.
|
// use memset of 0 before assigning niche value.
|
||||||
let llptr = bx.pointercast(self.llval, Type::i8(bx.cx).ptr_to());
|
let llptr = bx.pointercast(self.llval, Type::i8(bx.cx).ptr_to());
|
||||||
let fill_byte = C_u8(bx.cx, 0);
|
let fill_byte = CodegenCx::c_u8(bx.cx, 0);
|
||||||
let (size, align) = self.layout.size_and_align();
|
let (size, align) = self.layout.size_and_align();
|
||||||
let size = C_usize(bx.cx, size.bytes());
|
let size = CodegenCx::c_usize(bx.cx, size.bytes());
|
||||||
let align = C_u32(bx.cx, align.abi() as u32);
|
let align = CodegenCx::c_u32(bx.cx, align.abi() as u32);
|
||||||
base::call_memset(bx, llptr, fill_byte, size, align, false);
|
base::call_memset(bx, llptr, fill_byte, size, align, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -394,10 +395,10 @@ impl PlaceRef<'tcx, &'ll Value> {
|
||||||
.wrapping_add(niche_start);
|
.wrapping_add(niche_start);
|
||||||
// FIXME(eddyb) Check the actual primitive type here.
|
// FIXME(eddyb) Check the actual primitive type here.
|
||||||
let niche_llval = if niche_value == 0 {
|
let niche_llval = if niche_value == 0 {
|
||||||
// HACK(eddyb) Using `C_null` as it works on all types.
|
// HACK(eddyb) Using `c_null` as it works on all types.
|
||||||
C_null(niche_llty)
|
CodegenCx::c_null(niche_llty)
|
||||||
} else {
|
} else {
|
||||||
C_uint_big(niche_llty, niche_value)
|
CodegenCx::c_uint_big(niche_llty, niche_value)
|
||||||
};
|
};
|
||||||
OperandValue::Immediate(niche_llval).store(bx, niche);
|
OperandValue::Immediate(niche_llval).store(bx, niche);
|
||||||
}
|
}
|
||||||
|
@ -408,7 +409,7 @@ impl PlaceRef<'tcx, &'ll Value> {
|
||||||
pub fn project_index(&self, bx: &Builder<'a, 'll, 'tcx>, llindex: &'ll Value)
|
pub fn project_index(&self, bx: &Builder<'a, 'll, 'tcx>, llindex: &'ll Value)
|
||||||
-> PlaceRef<'tcx, &'ll Value> {
|
-> PlaceRef<'tcx, &'ll Value> {
|
||||||
PlaceRef {
|
PlaceRef {
|
||||||
llval: bx.inbounds_gep(self.llval, &[C_usize(bx.cx, 0), llindex]),
|
llval: bx.inbounds_gep(self.llval, &[CodegenCx::c_usize(bx.cx, 0), llindex]),
|
||||||
llextra: None,
|
llextra: None,
|
||||||
layout: self.layout.field(bx.cx, 0),
|
layout: self.layout.field(bx.cx, 0),
|
||||||
align: self.align
|
align: self.align
|
||||||
|
@ -483,7 +484,7 @@ impl FunctionCx<'a, 'll, 'tcx, &'ll Value> {
|
||||||
// so we generate an abort
|
// so we generate an abort
|
||||||
let fnname = bx.cx.get_intrinsic(&("llvm.trap"));
|
let fnname = bx.cx.get_intrinsic(&("llvm.trap"));
|
||||||
bx.call(fnname, &[], None);
|
bx.call(fnname, &[], None);
|
||||||
let llval = C_undef(layout.llvm_type(bx.cx).ptr_to());
|
let llval = CodegenCx::c_undef(layout.llvm_type(bx.cx).ptr_to());
|
||||||
PlaceRef::new_sized(llval, layout, layout.align)
|
PlaceRef::new_sized(llval, layout, layout.align)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -516,20 +517,20 @@ impl FunctionCx<'a, 'll, 'tcx, &'ll Value> {
|
||||||
mir::ProjectionElem::ConstantIndex { offset,
|
mir::ProjectionElem::ConstantIndex { offset,
|
||||||
from_end: false,
|
from_end: false,
|
||||||
min_length: _ } => {
|
min_length: _ } => {
|
||||||
let lloffset = C_usize(bx.cx, offset as u64);
|
let lloffset = CodegenCx::c_usize(bx.cx, offset as u64);
|
||||||
cg_base.project_index(bx, lloffset)
|
cg_base.project_index(bx, lloffset)
|
||||||
}
|
}
|
||||||
mir::ProjectionElem::ConstantIndex { offset,
|
mir::ProjectionElem::ConstantIndex { offset,
|
||||||
from_end: true,
|
from_end: true,
|
||||||
min_length: _ } => {
|
min_length: _ } => {
|
||||||
let lloffset = C_usize(bx.cx, offset as u64);
|
let lloffset = CodegenCx::c_usize(bx.cx, offset as u64);
|
||||||
let lllen = cg_base.len(bx.cx);
|
let lllen = cg_base.len(bx.cx);
|
||||||
let llindex = bx.sub(lllen, lloffset);
|
let llindex = bx.sub(lllen, lloffset);
|
||||||
cg_base.project_index(bx, llindex)
|
cg_base.project_index(bx, llindex)
|
||||||
}
|
}
|
||||||
mir::ProjectionElem::Subslice { from, to } => {
|
mir::ProjectionElem::Subslice { from, to } => {
|
||||||
let mut subslice = cg_base.project_index(bx,
|
let mut subslice = cg_base.project_index(bx,
|
||||||
C_usize(bx.cx, from as u64));
|
CodegenCx::c_usize(bx.cx, from as u64));
|
||||||
let projected_ty = PlaceTy::Ty { ty: cg_base.layout.ty }
|
let projected_ty = PlaceTy::Ty { ty: cg_base.layout.ty }
|
||||||
.projection_ty(tcx, &projection.elem)
|
.projection_ty(tcx, &projection.elem)
|
||||||
.to_ty(bx.tcx());
|
.to_ty(bx.tcx());
|
||||||
|
@ -537,7 +538,7 @@ impl FunctionCx<'a, 'll, 'tcx, &'ll Value> {
|
||||||
|
|
||||||
if subslice.layout.is_unsized() {
|
if subslice.layout.is_unsized() {
|
||||||
subslice.llextra = Some(bx.sub(cg_base.llextra.unwrap(),
|
subslice.llextra = Some(bx.sub(cg_base.llextra.unwrap(),
|
||||||
C_usize(bx.cx, (from as u64) + (to as u64))));
|
CodegenCx::c_usize(bx.cx, (from as u64) + (to as u64))));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cast the place pointer type to the new
|
// Cast the place pointer type to the new
|
||||||
|
|
|
@ -19,18 +19,15 @@ use std::{u128, i128};
|
||||||
use base;
|
use base;
|
||||||
use builder::Builder;
|
use builder::Builder;
|
||||||
use callee;
|
use callee;
|
||||||
use common::{self, val_ty};
|
use common::{self, IntPredicate, RealPredicate};
|
||||||
use common::{
|
use context::CodegenCx;
|
||||||
C_bool, C_u8, C_i32, C_u32, C_u64, C_undef, C_null, C_usize,
|
|
||||||
C_uint, C_uint_big, IntPredicate, RealPredicate
|
|
||||||
};
|
|
||||||
use consts;
|
use consts;
|
||||||
use monomorphize;
|
use monomorphize;
|
||||||
use type_::Type;
|
use type_::Type;
|
||||||
use type_of::LayoutLlvmExt;
|
use type_of::LayoutLlvmExt;
|
||||||
use value::Value;
|
use value::Value;
|
||||||
|
|
||||||
use interfaces::BuilderMethods;
|
use interfaces::{BuilderMethods, CommonMethods};
|
||||||
|
|
||||||
use super::{FunctionCx, LocalRef};
|
use super::{FunctionCx, LocalRef};
|
||||||
use super::operand::{OperandRef, OperandValue};
|
use super::operand::{OperandRef, OperandValue};
|
||||||
|
@ -106,28 +103,28 @@ impl FunctionCx<'a, 'll, 'tcx, &'ll Value> {
|
||||||
return bx;
|
return bx;
|
||||||
}
|
}
|
||||||
|
|
||||||
let start = dest.project_index(&bx, C_usize(bx.cx, 0)).llval;
|
let start = dest.project_index(&bx, CodegenCx::c_usize(bx.cx, 0)).llval;
|
||||||
|
|
||||||
if let OperandValue::Immediate(v) = cg_elem.val {
|
if let OperandValue::Immediate(v) = cg_elem.val {
|
||||||
let align = C_i32(bx.cx, dest.align.abi() as i32);
|
let align = CodegenCx::c_i32(bx.cx, dest.align.abi() as i32);
|
||||||
let size = C_usize(bx.cx, dest.layout.size.bytes());
|
let size = CodegenCx::c_usize(bx.cx, dest.layout.size.bytes());
|
||||||
|
|
||||||
// Use llvm.memset.p0i8.* to initialize all zero arrays
|
// Use llvm.memset.p0i8.* to initialize all zero arrays
|
||||||
if common::is_const_integral(v) && common::const_to_uint(v) == 0 {
|
if CodegenCx::is_const_integral(v) && CodegenCx::const_to_uint(v) == 0 {
|
||||||
let fill = C_u8(bx.cx, 0);
|
let fill = CodegenCx::c_u8(bx.cx, 0);
|
||||||
base::call_memset(&bx, start, fill, size, align, false);
|
base::call_memset(&bx, start, fill, size, align, false);
|
||||||
return bx;
|
return bx;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use llvm.memset.p0i8.* to initialize byte arrays
|
// Use llvm.memset.p0i8.* to initialize byte arrays
|
||||||
let v = base::from_immediate(&bx, v);
|
let v = base::from_immediate(&bx, v);
|
||||||
if common::val_ty(v) == Type::i8(bx.cx) {
|
if CodegenCx::val_ty(v) == Type::i8(bx.cx) {
|
||||||
base::call_memset(&bx, start, v, size, align, false);
|
base::call_memset(&bx, start, v, size, align, false);
|
||||||
return bx;
|
return bx;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let count = C_usize(bx.cx, count);
|
let count = CodegenCx::c_usize(bx.cx, count);
|
||||||
let end = dest.project_index(&bx, count).llval;
|
let end = dest.project_index(&bx, count).llval;
|
||||||
|
|
||||||
let header_bx = bx.build_sibling_block("repeat_loop_header");
|
let header_bx = bx.build_sibling_block("repeat_loop_header");
|
||||||
|
@ -135,7 +132,7 @@ impl FunctionCx<'a, 'll, 'tcx, &'ll Value> {
|
||||||
let next_bx = bx.build_sibling_block("repeat_loop_next");
|
let next_bx = bx.build_sibling_block("repeat_loop_next");
|
||||||
|
|
||||||
bx.br(header_bx.llbb());
|
bx.br(header_bx.llbb());
|
||||||
let current = header_bx.phi(common::val_ty(start), &[start], &[bx.llbb()]);
|
let current = header_bx.phi(CodegenCx::val_ty(start), &[start], &[bx.llbb()]);
|
||||||
|
|
||||||
let keep_going = header_bx.icmp(IntPredicate::IntNE, current, end);
|
let keep_going = header_bx.icmp(IntPredicate::IntNE, current, end);
|
||||||
header_bx.cond_br(keep_going, body_bx.llbb(), next_bx.llbb());
|
header_bx.cond_br(keep_going, body_bx.llbb(), next_bx.llbb());
|
||||||
|
@ -143,7 +140,7 @@ impl FunctionCx<'a, 'll, 'tcx, &'ll Value> {
|
||||||
cg_elem.val.store(&body_bx,
|
cg_elem.val.store(&body_bx,
|
||||||
PlaceRef::new_sized(current, cg_elem.layout, dest.align));
|
PlaceRef::new_sized(current, cg_elem.layout, dest.align));
|
||||||
|
|
||||||
let next = body_bx.inbounds_gep(current, &[C_usize(bx.cx, 1)]);
|
let next = body_bx.inbounds_gep(current, &[CodegenCx::c_usize(bx.cx, 1)]);
|
||||||
body_bx.br(header_bx.llbb());
|
body_bx.br(header_bx.llbb());
|
||||||
header_bx.add_incoming_to_phi(current, next, body_bx.llbb());
|
header_bx.add_incoming_to_phi(current, next, body_bx.llbb());
|
||||||
|
|
||||||
|
@ -296,7 +293,7 @@ impl FunctionCx<'a, 'll, 'tcx, &'ll Value> {
|
||||||
let ll_t_out = cast.immediate_llvm_type(bx.cx);
|
let ll_t_out = cast.immediate_llvm_type(bx.cx);
|
||||||
if operand.layout.abi.is_uninhabited() {
|
if operand.layout.abi.is_uninhabited() {
|
||||||
return (bx, OperandRef {
|
return (bx, OperandRef {
|
||||||
val: OperandValue::Immediate(C_undef(ll_t_out)),
|
val: OperandValue::Immediate(CodegenCx::c_undef(ll_t_out)),
|
||||||
layout: cast,
|
layout: cast,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -310,7 +307,7 @@ impl FunctionCx<'a, 'll, 'tcx, &'ll Value> {
|
||||||
let discr_val = def
|
let discr_val = def
|
||||||
.discriminant_for_variant(bx.cx.tcx, index)
|
.discriminant_for_variant(bx.cx.tcx, index)
|
||||||
.val;
|
.val;
|
||||||
let discr = C_uint_big(ll_t_out, discr_val);
|
let discr = CodegenCx::c_uint_big(ll_t_out, discr_val);
|
||||||
return (bx, OperandRef {
|
return (bx, OperandRef {
|
||||||
val: OperandValue::Immediate(discr),
|
val: OperandValue::Immediate(discr),
|
||||||
layout: cast,
|
layout: cast,
|
||||||
|
@ -341,7 +338,7 @@ impl FunctionCx<'a, 'll, 'tcx, &'ll Value> {
|
||||||
base::call_assume(&bx, bx.icmp(
|
base::call_assume(&bx, bx.icmp(
|
||||||
IntPredicate::IntULE,
|
IntPredicate::IntULE,
|
||||||
llval,
|
llval,
|
||||||
C_uint_big(ll_t_in, *scalar.valid_range.end())
|
CodegenCx::c_uint_big(ll_t_in, *scalar.valid_range.end())
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -492,7 +489,7 @@ impl FunctionCx<'a, 'll, 'tcx, &'ll Value> {
|
||||||
|
|
||||||
mir::Rvalue::NullaryOp(mir::NullOp::SizeOf, ty) => {
|
mir::Rvalue::NullaryOp(mir::NullOp::SizeOf, ty) => {
|
||||||
assert!(bx.cx.type_is_sized(ty));
|
assert!(bx.cx.type_is_sized(ty));
|
||||||
let val = C_usize(bx.cx, bx.cx.size_of(ty).bytes());
|
let val = CodegenCx::c_usize(bx.cx, bx.cx.size_of(ty).bytes());
|
||||||
let tcx = bx.tcx();
|
let tcx = bx.tcx();
|
||||||
(bx, OperandRef {
|
(bx, OperandRef {
|
||||||
val: OperandValue::Immediate(val),
|
val: OperandValue::Immediate(val),
|
||||||
|
@ -503,8 +500,8 @@ impl FunctionCx<'a, 'll, 'tcx, &'ll Value> {
|
||||||
mir::Rvalue::NullaryOp(mir::NullOp::Box, content_ty) => {
|
mir::Rvalue::NullaryOp(mir::NullOp::Box, content_ty) => {
|
||||||
let content_ty: Ty<'tcx> = self.monomorphize(&content_ty);
|
let content_ty: Ty<'tcx> = self.monomorphize(&content_ty);
|
||||||
let (size, align) = bx.cx.size_and_align_of(content_ty);
|
let (size, align) = bx.cx.size_and_align_of(content_ty);
|
||||||
let llsize = C_usize(bx.cx, size.bytes());
|
let llsize = CodegenCx::c_usize(bx.cx, size.bytes());
|
||||||
let llalign = C_usize(bx.cx, align.abi());
|
let llalign = CodegenCx::c_usize(bx.cx, align.abi());
|
||||||
let box_layout = bx.cx.layout_of(bx.tcx().mk_box(content_ty));
|
let box_layout = bx.cx.layout_of(bx.tcx().mk_box(content_ty));
|
||||||
let llty_ptr = box_layout.llvm_type(bx.cx);
|
let llty_ptr = box_layout.llvm_type(bx.cx);
|
||||||
|
|
||||||
|
@ -551,7 +548,7 @@ impl FunctionCx<'a, 'll, 'tcx, &'ll Value> {
|
||||||
if let LocalRef::Operand(Some(op)) = self.locals[index] {
|
if let LocalRef::Operand(Some(op)) = self.locals[index] {
|
||||||
if let ty::Array(_, n) = op.layout.ty.sty {
|
if let ty::Array(_, n) = op.layout.ty.sty {
|
||||||
let n = n.unwrap_usize(bx.cx.tcx);
|
let n = n.unwrap_usize(bx.cx.tcx);
|
||||||
return common::C_usize(bx.cx, n);
|
return CodegenCx::c_usize(bx.cx, n);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -609,7 +606,7 @@ impl FunctionCx<'a, 'll, 'tcx, &'ll Value> {
|
||||||
mir::BinOp::Shr => common::build_unchecked_rshift(bx, input_ty, lhs, rhs),
|
mir::BinOp::Shr => common::build_unchecked_rshift(bx, input_ty, lhs, rhs),
|
||||||
mir::BinOp::Ne | mir::BinOp::Lt | mir::BinOp::Gt |
|
mir::BinOp::Ne | mir::BinOp::Lt | mir::BinOp::Gt |
|
||||||
mir::BinOp::Eq | mir::BinOp::Le | mir::BinOp::Ge => if is_unit {
|
mir::BinOp::Eq | mir::BinOp::Le | mir::BinOp::Ge => if is_unit {
|
||||||
C_bool(bx.cx, match op {
|
CodegenCx::c_bool(bx.cx, match op {
|
||||||
mir::BinOp::Ne | mir::BinOp::Lt | mir::BinOp::Gt => false,
|
mir::BinOp::Ne | mir::BinOp::Lt | mir::BinOp::Gt => false,
|
||||||
mir::BinOp::Eq | mir::BinOp::Le | mir::BinOp::Ge => true,
|
mir::BinOp::Eq | mir::BinOp::Le | mir::BinOp::Ge => true,
|
||||||
_ => unreachable!()
|
_ => unreachable!()
|
||||||
|
@ -688,7 +685,7 @@ impl FunctionCx<'a, 'll, 'tcx, &'ll Value> {
|
||||||
// while the current crate doesn't use overflow checks.
|
// while the current crate doesn't use overflow checks.
|
||||||
if !bx.cx.check_overflow {
|
if !bx.cx.check_overflow {
|
||||||
let val = self.codegen_scalar_binop(bx, op, lhs, rhs, input_ty);
|
let val = self.codegen_scalar_binop(bx, op, lhs, rhs, input_ty);
|
||||||
return OperandValue::Pair(val, C_bool(bx.cx, false));
|
return OperandValue::Pair(val, CodegenCx::c_bool(bx.cx, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
let (val, of) = match op {
|
let (val, of) = match op {
|
||||||
|
@ -707,12 +704,12 @@ impl FunctionCx<'a, 'll, 'tcx, &'ll Value> {
|
||||||
bx.extract_value(res, 1))
|
bx.extract_value(res, 1))
|
||||||
}
|
}
|
||||||
mir::BinOp::Shl | mir::BinOp::Shr => {
|
mir::BinOp::Shl | mir::BinOp::Shr => {
|
||||||
let lhs_llty = val_ty(lhs);
|
let lhs_llty = CodegenCx::val_ty(lhs);
|
||||||
let rhs_llty = val_ty(rhs);
|
let rhs_llty = CodegenCx::val_ty(rhs);
|
||||||
let invert_mask = common::shift_mask_val(&bx, lhs_llty, rhs_llty, true);
|
let invert_mask = common::shift_mask_val(&bx, lhs_llty, rhs_llty, true);
|
||||||
let outer_bits = bx.and(rhs, invert_mask);
|
let outer_bits = bx.and(rhs, invert_mask);
|
||||||
|
|
||||||
let of = bx.icmp(IntPredicate::IntNE, outer_bits, C_null(rhs_llty));
|
let of = bx.icmp(IntPredicate::IntNE, outer_bits, CodegenCx::c_null(rhs_llty));
|
||||||
let val = self.codegen_scalar_binop(bx, op, lhs, rhs, input_ty);
|
let val = self.codegen_scalar_binop(bx, op, lhs, rhs, input_ty);
|
||||||
|
|
||||||
(val, of)
|
(val, of)
|
||||||
|
@ -839,9 +836,9 @@ fn cast_int_to_float(bx: &Builder<'_, 'll, '_>,
|
||||||
use rustc_apfloat::Float;
|
use rustc_apfloat::Float;
|
||||||
const MAX_F32_PLUS_HALF_ULP: u128 = ((1 << (Single::PRECISION + 1)) - 1)
|
const MAX_F32_PLUS_HALF_ULP: u128 = ((1 << (Single::PRECISION + 1)) - 1)
|
||||||
<< (Single::MAX_EXP - Single::PRECISION as i16);
|
<< (Single::MAX_EXP - Single::PRECISION as i16);
|
||||||
let max = C_uint_big(int_ty, MAX_F32_PLUS_HALF_ULP);
|
let max = CodegenCx::c_uint_big(int_ty, MAX_F32_PLUS_HALF_ULP);
|
||||||
let overflow = bx.icmp(IntPredicate::IntUGE, x, max);
|
let overflow = bx.icmp(IntPredicate::IntUGE, x, max);
|
||||||
let infinity_bits = C_u32(bx.cx, ieee::Single::INFINITY.to_bits() as u32);
|
let infinity_bits = CodegenCx::c_u32(bx.cx, ieee::Single::INFINITY.to_bits() as u32);
|
||||||
let infinity = consts::bitcast(infinity_bits, float_ty);
|
let infinity = consts::bitcast(infinity_bits, float_ty);
|
||||||
bx.select(overflow, infinity, bx.uitofp(x, float_ty))
|
bx.select(overflow, infinity, bx.uitofp(x, float_ty))
|
||||||
} else {
|
} else {
|
||||||
|
@ -910,8 +907,8 @@ fn cast_float_to_int(bx: &Builder<'_, 'll, '_>,
|
||||||
}
|
}
|
||||||
let float_bits_to_llval = |bits| {
|
let float_bits_to_llval = |bits| {
|
||||||
let bits_llval = match float_ty.float_width() {
|
let bits_llval = match float_ty.float_width() {
|
||||||
32 => C_u32(bx.cx, bits as u32),
|
32 => CodegenCx::c_u32(bx.cx, bits as u32),
|
||||||
64 => C_u64(bx.cx, bits as u64),
|
64 => CodegenCx::c_u64(bx.cx, bits as u64),
|
||||||
n => bug!("unsupported float width {}", n),
|
n => bug!("unsupported float width {}", n),
|
||||||
};
|
};
|
||||||
consts::bitcast(bits_llval, float_ty)
|
consts::bitcast(bits_llval, float_ty)
|
||||||
|
@ -966,8 +963,8 @@ fn cast_float_to_int(bx: &Builder<'_, 'll, '_>,
|
||||||
// performed is ultimately up to the backend, but at least x86 does perform them.
|
// performed is ultimately up to the backend, but at least x86 does perform them.
|
||||||
let less_or_nan = bx.fcmp(RealPredicate::RealULT, x, f_min);
|
let less_or_nan = bx.fcmp(RealPredicate::RealULT, x, f_min);
|
||||||
let greater = bx.fcmp(RealPredicate::RealOGT, x, f_max);
|
let greater = bx.fcmp(RealPredicate::RealOGT, x, f_max);
|
||||||
let int_max = C_uint_big(int_ty, int_max(signed, int_ty));
|
let int_max = CodegenCx::c_uint_big(int_ty, int_max(signed, int_ty));
|
||||||
let int_min = C_uint_big(int_ty, int_min(signed, int_ty) as u128);
|
let int_min = CodegenCx::c_uint_big(int_ty, int_min(signed, int_ty) as u128);
|
||||||
let s0 = bx.select(less_or_nan, int_min, fptosui_result);
|
let s0 = bx.select(less_or_nan, int_min, fptosui_result);
|
||||||
let s1 = bx.select(greater, int_max, s0);
|
let s1 = bx.select(greater, int_max, s0);
|
||||||
|
|
||||||
|
@ -976,7 +973,7 @@ fn cast_float_to_int(bx: &Builder<'_, 'll, '_>,
|
||||||
// Therefore we only need to execute this step for signed integer types.
|
// Therefore we only need to execute this step for signed integer types.
|
||||||
if signed {
|
if signed {
|
||||||
// LLVM has no isNaN predicate, so we use (x == x) instead
|
// LLVM has no isNaN predicate, so we use (x == x) instead
|
||||||
bx.select(bx.fcmp(RealPredicate::RealOEQ, x, x), s1, C_uint(int_ty, 0))
|
bx.select(bx.fcmp(RealPredicate::RealOEQ, x, x), s1, CodegenCx::c_uint(int_ty, 0))
|
||||||
} else {
|
} else {
|
||||||
s1
|
s1
|
||||||
}
|
}
|
||||||
|
|
|
@ -324,7 +324,7 @@ impl Type {
|
||||||
TypeKind::Float => 32,
|
TypeKind::Float => 32,
|
||||||
TypeKind::Double => 64,
|
TypeKind::Double => 64,
|
||||||
TypeKind::X86_FP80 => 80,
|
TypeKind::X86_FP80 => 80,
|
||||||
TypeKind::FP128 | TypeKind::PPC_FP128 => 128,
|
TypeKind::FP128 | TypeKind::PPc_FP128 => 128,
|
||||||
_ => bug!("llvm_float_width called on a non-float type")
|
_ => bug!("llvm_float_width called on a non-float type")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue