cg_llvm: remove pointee types and pointercast/bitcast-of-ptr
This commit is contained in:
parent
4c96822796
commit
b6540777fe
17 changed files with 118 additions and 283 deletions
|
@ -216,9 +216,7 @@ impl<'ll, 'tcx> ArgAbiExt<'ll, 'tcx> for ArgAbi<'tcx, Ty<'tcx>> {
|
|||
// uses it for i16 -> {i8, i8}, but not for i24 -> {i8, i8, i8}.
|
||||
let can_store_through_cast_ptr = false;
|
||||
if can_store_through_cast_ptr {
|
||||
let cast_ptr_llty = bx.type_ptr_to(cast.llvm_type(bx));
|
||||
let cast_dst = bx.pointercast(dst.llval, cast_ptr_llty);
|
||||
bx.store(val, cast_dst, self.layout.align.abi);
|
||||
bx.store(val, dst.llval, self.layout.align.abi);
|
||||
} else {
|
||||
// The actual return type is a struct, but the ABI
|
||||
// adaptation code has cast it into some scalar type. The
|
||||
|
@ -336,7 +334,7 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
|
|||
PassMode::Direct(_) | PassMode::Pair(..) => self.ret.layout.immediate_llvm_type(cx),
|
||||
PassMode::Cast(cast, _) => cast.llvm_type(cx),
|
||||
PassMode::Indirect { .. } => {
|
||||
llargument_tys.push(cx.type_ptr_to(self.ret.memory_ty(cx)));
|
||||
llargument_tys.push(cx.type_ptr());
|
||||
cx.type_void()
|
||||
}
|
||||
};
|
||||
|
@ -364,9 +362,7 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
|
|||
}
|
||||
cast.llvm_type(cx)
|
||||
}
|
||||
PassMode::Indirect { attrs: _, extra_attrs: None, on_stack: _ } => {
|
||||
cx.type_ptr_to(arg.memory_ty(cx))
|
||||
}
|
||||
PassMode::Indirect { attrs: _, extra_attrs: None, on_stack: _ } => cx.type_ptr(),
|
||||
};
|
||||
llargument_tys.push(llarg_ty);
|
||||
}
|
||||
|
@ -379,12 +375,7 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
|
|||
}
|
||||
|
||||
fn ptr_to_llvm_type(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type {
|
||||
unsafe {
|
||||
llvm::LLVMPointerType(
|
||||
self.llvm_type(cx),
|
||||
cx.data_layout().instruction_address_space.0 as c_uint,
|
||||
)
|
||||
}
|
||||
cx.type_ptr_ext(cx.data_layout().instruction_address_space)
|
||||
}
|
||||
|
||||
fn llvm_cconv(&self) -> llvm::CallConv {
|
||||
|
|
|
@ -28,7 +28,7 @@ pub(crate) unsafe fn codegen(
|
|||
tws => bug!("Unsupported target word size for int: {}", tws),
|
||||
};
|
||||
let i8 = llvm::LLVMInt8TypeInContext(llcx);
|
||||
let i8p = llvm::LLVMPointerType(i8, 0);
|
||||
let i8p = llvm::LLVMPointerTypeInContext(llcx, 0);
|
||||
let void = llvm::LLVMVoidTypeInContext(llcx);
|
||||
|
||||
if kind == AllocatorKind::Default {
|
||||
|
|
|
@ -4,7 +4,6 @@ use crate::back::profiling::{
|
|||
};
|
||||
use crate::base;
|
||||
use crate::common;
|
||||
use crate::consts;
|
||||
use crate::errors::{
|
||||
CopyBitcode, FromLlvmDiag, FromLlvmOptimizationDiag, LlvmError, WithLlvmError, WriteBytecode,
|
||||
};
|
||||
|
@ -992,7 +991,7 @@ fn create_msvc_imps(
|
|||
let prefix = if cgcx.target_arch == "x86" { "\x01__imp__" } else { "\x01__imp_" };
|
||||
|
||||
unsafe {
|
||||
let i8p_ty = Type::i8p_llcx(llcx);
|
||||
let ptr_ty = Type::ptr_llcx(llcx);
|
||||
let globals = base::iter_globals(llmod)
|
||||
.filter(|&val| {
|
||||
llvm::LLVMRustGetLinkage(val) == llvm::Linkage::ExternalLinkage
|
||||
|
@ -1012,8 +1011,8 @@ fn create_msvc_imps(
|
|||
.collect::<Vec<_>>();
|
||||
|
||||
for (imp_name, val) in globals {
|
||||
let imp = llvm::LLVMAddGlobal(llmod, i8p_ty, imp_name.as_ptr().cast());
|
||||
llvm::LLVMSetInitializer(imp, consts::ptrcast(val, i8p_ty));
|
||||
let imp = llvm::LLVMAddGlobal(llmod, ptr_ty, imp_name.as_ptr().cast());
|
||||
llvm::LLVMSetInitializer(imp, val);
|
||||
llvm::LLVMRustSetLinkage(imp, llvm::Linkage::ExternalLinkage);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -123,8 +123,7 @@ pub fn compile_codegen_unit(tcx: TyCtxt<'_>, cgu_name: Symbol) -> (ModuleCodegen
|
|||
// happen after the llvm.used variables are created.
|
||||
for &(old_g, new_g) in cx.statics_to_rauw().borrow().iter() {
|
||||
unsafe {
|
||||
let bitcast = llvm::LLVMConstPointerCast(new_g, cx.val_ty(old_g));
|
||||
llvm::LLVMReplaceAllUsesWith(old_g, bitcast);
|
||||
llvm::LLVMReplaceAllUsesWith(old_g, new_g);
|
||||
llvm::LLVMDeleteGlobal(old_g);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -652,7 +652,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
|
|||
flags: MemFlags,
|
||||
) -> &'ll Value {
|
||||
debug!("Store {:?} -> {:?} ({:?})", val, ptr, flags);
|
||||
let ptr = self.check_store(val, ptr);
|
||||
let ptr = self.check_store(ptr);
|
||||
unsafe {
|
||||
let store = llvm::LLVMBuildStore(self.llbuilder, val, ptr);
|
||||
let align =
|
||||
|
@ -682,7 +682,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
|
|||
size: Size,
|
||||
) {
|
||||
debug!("Store {:?} -> {:?}", val, ptr);
|
||||
let ptr = self.check_store(val, ptr);
|
||||
let ptr = self.check_store(ptr);
|
||||
unsafe {
|
||||
let store = llvm::LLVMRustBuildAtomicStore(
|
||||
self.llbuilder,
|
||||
|
@ -873,8 +873,6 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
|
|||
assert!(!flags.contains(MemFlags::NONTEMPORAL), "non-temporal memcpy not supported");
|
||||
let size = self.intcast(size, self.type_isize(), false);
|
||||
let is_volatile = flags.contains(MemFlags::VOLATILE);
|
||||
let dst = self.pointercast(dst, self.type_i8p());
|
||||
let src = self.pointercast(src, self.type_i8p());
|
||||
unsafe {
|
||||
llvm::LLVMRustBuildMemCpy(
|
||||
self.llbuilder,
|
||||
|
@ -900,8 +898,6 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
|
|||
assert!(!flags.contains(MemFlags::NONTEMPORAL), "non-temporal memmove not supported");
|
||||
let size = self.intcast(size, self.type_isize(), false);
|
||||
let is_volatile = flags.contains(MemFlags::VOLATILE);
|
||||
let dst = self.pointercast(dst, self.type_i8p());
|
||||
let src = self.pointercast(src, self.type_i8p());
|
||||
unsafe {
|
||||
llvm::LLVMRustBuildMemMove(
|
||||
self.llbuilder,
|
||||
|
@ -924,7 +920,6 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
|
|||
flags: MemFlags,
|
||||
) {
|
||||
let is_volatile = flags.contains(MemFlags::VOLATILE);
|
||||
let ptr = self.pointercast(ptr, self.type_i8p());
|
||||
unsafe {
|
||||
llvm::LLVMRustBuildMemSet(
|
||||
self.llbuilder,
|
||||
|
@ -981,7 +976,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
|
|||
}
|
||||
|
||||
fn cleanup_landing_pad(&mut self, pers_fn: &'ll Value) -> (&'ll Value, &'ll Value) {
|
||||
let ty = self.type_struct(&[self.type_i8p(), self.type_i32()], false);
|
||||
let ty = self.type_struct(&[self.type_ptr(), self.type_i32()], false);
|
||||
let landing_pad = self.landing_pad(ty, pers_fn, 0);
|
||||
unsafe {
|
||||
llvm::LLVMSetCleanup(landing_pad, llvm::True);
|
||||
|
@ -990,14 +985,14 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
|
|||
}
|
||||
|
||||
fn filter_landing_pad(&mut self, pers_fn: &'ll Value) -> (&'ll Value, &'ll Value) {
|
||||
let ty = self.type_struct(&[self.type_i8p(), self.type_i32()], false);
|
||||
let ty = self.type_struct(&[self.type_ptr(), self.type_i32()], false);
|
||||
let landing_pad = self.landing_pad(ty, pers_fn, 1);
|
||||
self.add_clause(landing_pad, self.const_array(self.type_i8p(), &[]));
|
||||
self.add_clause(landing_pad, self.const_array(self.type_ptr(), &[]));
|
||||
(self.extract_value(landing_pad, 0), self.extract_value(landing_pad, 1))
|
||||
}
|
||||
|
||||
fn resume(&mut self, exn0: &'ll Value, exn1: &'ll Value) {
|
||||
let ty = self.type_struct(&[self.type_i8p(), self.type_i32()], false);
|
||||
let ty = self.type_struct(&[self.type_ptr(), self.type_i32()], false);
|
||||
let mut exn = self.const_poison(ty);
|
||||
exn = self.insert_value(exn, exn0, 0);
|
||||
exn = self.insert_value(exn, exn1, 1);
|
||||
|
@ -1161,7 +1156,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
|
|||
|
||||
let llfn = unsafe { llvm::LLVMRustGetInstrProfIncrementIntrinsic(self.cx().llmod) };
|
||||
let llty = self.cx.type_func(
|
||||
&[self.cx.type_i8p(), self.cx.type_i64(), self.cx.type_i32(), self.cx.type_i32()],
|
||||
&[self.cx.type_ptr(), self.cx.type_i64(), self.cx.type_i32(), self.cx.type_i32()],
|
||||
self.cx.type_void(),
|
||||
);
|
||||
let args = &[fn_name, hash, num_counters, index];
|
||||
|
@ -1387,23 +1382,12 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
|
|||
ret.expect("LLVM does not have support for catchret")
|
||||
}
|
||||
|
||||
fn check_store(&mut self, val: &'ll Value, ptr: &'ll Value) -> &'ll Value {
|
||||
fn check_store(&mut self, ptr: &'ll Value) -> &'ll Value {
|
||||
let dest_ptr_ty = self.cx.val_ty(ptr);
|
||||
let stored_ty = self.cx.val_ty(val);
|
||||
let stored_ptr_ty = self.cx.type_ptr_to(stored_ty);
|
||||
|
||||
assert_eq!(self.cx.type_kind(dest_ptr_ty), TypeKind::Pointer);
|
||||
|
||||
if dest_ptr_ty == stored_ptr_ty {
|
||||
ptr
|
||||
} else {
|
||||
debug!(
|
||||
"type mismatch in store. \
|
||||
Expected {:?}, got {:?}; inserting bitcast",
|
||||
dest_ptr_ty, stored_ptr_ty
|
||||
);
|
||||
self.bitcast(ptr, stored_ptr_ty)
|
||||
}
|
||||
ptr
|
||||
}
|
||||
|
||||
fn check_call<'b>(
|
||||
|
@ -1468,7 +1452,6 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
|
|||
return;
|
||||
}
|
||||
|
||||
let ptr = self.pointercast(ptr, self.cx.type_i8p());
|
||||
self.call_intrinsic(intrinsic, &[self.cx.const_u64(size), ptr]);
|
||||
}
|
||||
|
||||
|
|
|
@ -4,13 +4,11 @@
|
|||
//! and methods are represented as just a fn ptr and not a full
|
||||
//! closure.
|
||||
|
||||
use crate::abi::FnAbiLlvmExt;
|
||||
use crate::attributes;
|
||||
use crate::common;
|
||||
use crate::context::CodegenCx;
|
||||
use crate::llvm;
|
||||
use crate::value::Value;
|
||||
use rustc_codegen_ssa::traits::*;
|
||||
|
||||
use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt};
|
||||
use rustc_middle::ty::{self, Instance, TypeVisitableExt};
|
||||
|
@ -45,39 +43,7 @@ pub fn get_fn<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'tcx>) ->
|
|||
let fn_abi = cx.fn_abi_of_instance(instance, ty::List::empty());
|
||||
|
||||
let llfn = if let Some(llfn) = cx.get_declared_value(sym) {
|
||||
// Create a fn pointer with the new signature.
|
||||
let llptrty = fn_abi.ptr_to_llvm_type(cx);
|
||||
|
||||
// This is subtle and surprising, but sometimes we have to bitcast
|
||||
// the resulting fn pointer. The reason has to do with external
|
||||
// functions. If you have two crates that both bind the same C
|
||||
// library, they may not use precisely the same types: for
|
||||
// example, they will probably each declare their own structs,
|
||||
// which are distinct types from LLVM's point of view (nominal
|
||||
// types).
|
||||
//
|
||||
// Now, if those two crates are linked into an application, and
|
||||
// they contain inlined code, you can wind up with a situation
|
||||
// where both of those functions wind up being loaded into this
|
||||
// application simultaneously. In that case, the same function
|
||||
// (from LLVM's point of view) requires two types. But of course
|
||||
// LLVM won't allow one function to have two types.
|
||||
//
|
||||
// What we currently do, therefore, is declare the function with
|
||||
// one of the two types (whichever happens to come first) and then
|
||||
// bitcast as needed when the function is referenced to make sure
|
||||
// it has the type we expect.
|
||||
//
|
||||
// This can occur on either a crate-local or crate-external
|
||||
// reference. It also occurs when testing libcore and in some
|
||||
// other weird situations. Annoying.
|
||||
if cx.val_ty(llfn) != llptrty {
|
||||
debug!("get_fn: casting {:?} to {:?}", llfn, llptrty);
|
||||
cx.const_ptrcast(llfn, llptrty)
|
||||
} else {
|
||||
debug!("get_fn: not casting pointer!");
|
||||
llfn
|
||||
}
|
||||
llfn
|
||||
} else {
|
||||
let instance_def_id = instance.def_id();
|
||||
let llfn = if tcx.sess.target.arch == "x86" &&
|
||||
|
|
|
@ -4,7 +4,6 @@ use crate::consts::{self, const_alloc_to_llvm};
|
|||
pub use crate::context::CodegenCx;
|
||||
use crate::llvm::{self, BasicBlock, Bool, ConstantInt, False, OperandBundleDef, True};
|
||||
use crate::type_::Type;
|
||||
use crate::type_of::LayoutLlvmExt;
|
||||
use crate::value::Value;
|
||||
|
||||
use rustc_ast::Mutability;
|
||||
|
@ -13,7 +12,6 @@ use rustc_data_structures::stable_hasher::{Hash128, HashStable, StableHasher};
|
|||
use rustc_hir::def_id::DefId;
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::mir::interpret::{ConstAllocation, GlobalAlloc, Scalar};
|
||||
use rustc_middle::ty::layout::LayoutOf;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_session::cstore::{DllCallingConvention, DllImport, PeImportNameType};
|
||||
use rustc_target::abi::{self, AddressSpace, HasDataLayout, Pointer};
|
||||
|
@ -211,11 +209,7 @@ impl<'ll, 'tcx> ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> {
|
|||
})
|
||||
.1;
|
||||
let len = s.len();
|
||||
let cs = consts::ptrcast(
|
||||
str_global,
|
||||
self.type_ptr_to(self.layout_of(self.tcx.types.str_).llvm_type(self)),
|
||||
);
|
||||
(cs, self.const_usize(len as u64))
|
||||
(str_global, self.const_usize(len as u64))
|
||||
}
|
||||
|
||||
fn const_struct(&self, elts: &[&'ll Value], packed: bool) -> &'ll Value {
|
||||
|
@ -292,7 +286,7 @@ impl<'ll, 'tcx> ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> {
|
|||
let llval = unsafe {
|
||||
llvm::LLVMConstInBoundsGEP2(
|
||||
self.type_i8(),
|
||||
self.const_bitcast(base_addr, self.type_i8p_ext(base_addr_space)),
|
||||
self.const_bitcast(base_addr, self.type_ptr_ext(base_addr_space)),
|
||||
&self.const_usize(offset.bytes()),
|
||||
1,
|
||||
)
|
||||
|
@ -322,7 +316,7 @@ impl<'ll, 'tcx> ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> {
|
|||
unsafe {
|
||||
llvm::LLVMConstInBoundsGEP2(
|
||||
self.type_i8(),
|
||||
self.const_bitcast(base_addr, self.type_i8p()),
|
||||
base_addr,
|
||||
&self.const_usize(offset.bytes()),
|
||||
1,
|
||||
)
|
||||
|
|
|
@ -103,7 +103,7 @@ pub fn const_alloc_to_llvm<'ll>(cx: &CodegenCx<'ll, '_>, alloc: ConstAllocation<
|
|||
value: Primitive::Pointer(address_space),
|
||||
valid_range: WrappingRange::full(dl.pointer_size),
|
||||
},
|
||||
cx.type_i8p_ext(address_space),
|
||||
cx.type_ptr_ext(address_space),
|
||||
));
|
||||
next_offset = offset + pointer_size;
|
||||
}
|
||||
|
@ -179,7 +179,7 @@ fn check_and_apply_linkage<'ll, 'tcx>(
|
|||
})
|
||||
});
|
||||
llvm::LLVMRustSetLinkage(g2, llvm::Linkage::InternalLinkage);
|
||||
llvm::LLVMSetInitializer(g2, cx.const_ptrcast(g1, llty));
|
||||
llvm::LLVMSetInitializer(g2, g1);
|
||||
g2
|
||||
}
|
||||
} else if cx.tcx.sess.target.arch == "x86" &&
|
||||
|
@ -251,7 +251,7 @@ impl<'ll> CodegenCx<'ll, '_> {
|
|||
let g = if def_id.is_local() && !self.tcx.is_foreign_item(def_id) {
|
||||
let llty = self.layout_of(ty).llvm_type(self);
|
||||
if let Some(g) = self.get_declared_value(sym) {
|
||||
if self.val_ty(g) != self.type_ptr_to(llty) {
|
||||
if self.val_ty(g) != self.type_ptr() {
|
||||
span_bug!(self.tcx.def_span(def_id), "Conflicting types for static");
|
||||
}
|
||||
}
|
||||
|
@ -552,16 +552,14 @@ impl<'ll> StaticMethods for CodegenCx<'ll, '_> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Add a global value to a list to be stored in the `llvm.used` variable, an array of i8*.
|
||||
/// Add a global value to a list to be stored in the `llvm.used` variable, an array of ptr.
|
||||
fn add_used_global(&self, global: &'ll Value) {
|
||||
let cast = unsafe { llvm::LLVMConstPointerCast(global, self.type_i8p()) };
|
||||
self.used_statics.borrow_mut().push(cast);
|
||||
self.used_statics.borrow_mut().push(global);
|
||||
}
|
||||
|
||||
/// Add a global value to a list to be stored in the `llvm.compiler.used` variable,
|
||||
/// an array of i8*.
|
||||
/// an array of ptr.
|
||||
fn add_compiler_used_global(&self, global: &'ll Value) {
|
||||
let cast = unsafe { llvm::LLVMConstPointerCast(global, self.type_i8p()) };
|
||||
self.compiler_used_statics.borrow_mut().push(cast);
|
||||
self.compiler_used_statics.borrow_mut().push(global);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -59,17 +59,6 @@ pub struct CodegenCx<'ll, 'tcx> {
|
|||
/// Cache of constant strings,
|
||||
pub const_str_cache: RefCell<FxHashMap<String, &'ll Value>>,
|
||||
|
||||
/// Reverse-direction for const ptrs cast from globals.
|
||||
///
|
||||
/// Key is a Value holding a `*T`,
|
||||
/// Val is a Value holding a `*[T]`.
|
||||
///
|
||||
/// Needed because LLVM loses pointer->pointee association
|
||||
/// when we ptrcast, and we have to ptrcast during codegen
|
||||
/// of a `[T]` const because we form a slice, a `(*T,usize)` pair, not
|
||||
/// a pointer to an LLVM array type. Similar for trait objects.
|
||||
pub const_unsized: RefCell<FxHashMap<&'ll Value, &'ll Value>>,
|
||||
|
||||
/// Cache of emitted const globals (value -> global)
|
||||
pub const_globals: RefCell<FxHashMap<&'ll Value, &'ll Value>>,
|
||||
|
||||
|
@ -464,7 +453,6 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
|
|||
instances: Default::default(),
|
||||
vtables: Default::default(),
|
||||
const_str_cache: Default::default(),
|
||||
const_unsized: Default::default(),
|
||||
const_globals: Default::default(),
|
||||
statics_to_rauw: RefCell::new(Vec::new()),
|
||||
used_statics: RefCell::new(Vec::new()),
|
||||
|
@ -495,7 +483,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
|
|||
|
||||
pub(crate) fn create_used_variable_impl(&self, name: &'static CStr, values: &[&'ll Value]) {
|
||||
let section = cstr!("llvm.metadata");
|
||||
let array = self.const_array(self.type_ptr_to(self.type_i8()), values);
|
||||
let array = self.const_array(self.type_ptr(), values);
|
||||
|
||||
unsafe {
|
||||
let g = llvm::LLVMAddGlobal(self.llmod, self.val_ty(array), name.as_ptr());
|
||||
|
@ -673,7 +661,7 @@ impl<'ll> CodegenCx<'ll, '_> {
|
|||
($($field_ty:expr),*) => (self.type_struct( &[$($field_ty),*], false))
|
||||
}
|
||||
|
||||
let i8p = self.type_i8p();
|
||||
let ptr = self.type_ptr();
|
||||
let void = self.type_void();
|
||||
let i1 = self.type_i1();
|
||||
let t_i8 = self.type_i8();
|
||||
|
@ -687,7 +675,7 @@ impl<'ll> CodegenCx<'ll, '_> {
|
|||
let t_metadata = self.type_metadata();
|
||||
let t_token = self.type_token();
|
||||
|
||||
ifn!("llvm.wasm.get.exception", fn(t_token) -> i8p);
|
||||
ifn!("llvm.wasm.get.exception", fn(t_token) -> ptr);
|
||||
ifn!("llvm.wasm.get.ehselector", fn(t_token) -> t_i32);
|
||||
|
||||
ifn!("llvm.wasm.trunc.unsigned.i32.f32", fn(t_f32) -> t_i32);
|
||||
|
@ -723,7 +711,7 @@ impl<'ll> CodegenCx<'ll, '_> {
|
|||
|
||||
ifn!("llvm.trap", fn() -> void);
|
||||
ifn!("llvm.debugtrap", fn() -> void);
|
||||
ifn!("llvm.frameaddress", fn(t_i32) -> i8p);
|
||||
ifn!("llvm.frameaddress", fn(t_i32) -> ptr);
|
||||
|
||||
ifn!("llvm.powi.f32", fn(t_f32, t_i32) -> t_f32);
|
||||
ifn!("llvm.powi.f64", fn(t_f64, t_i32) -> t_f64);
|
||||
|
@ -890,43 +878,43 @@ impl<'ll> CodegenCx<'ll, '_> {
|
|||
ifn!("llvm.usub.sat.i64", fn(t_i64, t_i64) -> t_i64);
|
||||
ifn!("llvm.usub.sat.i128", fn(t_i128, t_i128) -> t_i128);
|
||||
|
||||
ifn!("llvm.lifetime.start.p0i8", fn(t_i64, i8p) -> void);
|
||||
ifn!("llvm.lifetime.end.p0i8", fn(t_i64, i8p) -> void);
|
||||
ifn!("llvm.lifetime.start.p0i8", fn(t_i64, ptr) -> void);
|
||||
ifn!("llvm.lifetime.end.p0i8", fn(t_i64, ptr) -> void);
|
||||
|
||||
ifn!("llvm.expect.i1", fn(i1, i1) -> i1);
|
||||
ifn!("llvm.eh.typeid.for", fn(i8p) -> t_i32);
|
||||
ifn!("llvm.eh.typeid.for", fn(ptr) -> t_i32);
|
||||
ifn!("llvm.localescape", fn(...) -> void);
|
||||
ifn!("llvm.localrecover", fn(i8p, i8p, t_i32) -> i8p);
|
||||
ifn!("llvm.x86.seh.recoverfp", fn(i8p, i8p) -> i8p);
|
||||
ifn!("llvm.localrecover", fn(ptr, ptr, t_i32) -> ptr);
|
||||
ifn!("llvm.x86.seh.recoverfp", fn(ptr, ptr) -> ptr);
|
||||
|
||||
ifn!("llvm.assume", fn(i1) -> void);
|
||||
ifn!("llvm.prefetch", fn(i8p, t_i32, t_i32, t_i32) -> void);
|
||||
ifn!("llvm.prefetch", fn(ptr, t_i32, t_i32, t_i32) -> void);
|
||||
|
||||
// This isn't an "LLVM intrinsic", but LLVM's optimization passes
|
||||
// recognize it like one and we assume it exists in `core::slice::cmp`
|
||||
match self.sess().target.arch.as_ref() {
|
||||
"avr" | "msp430" => ifn!("memcmp", fn(i8p, i8p, t_isize) -> t_i16),
|
||||
_ => ifn!("memcmp", fn(i8p, i8p, t_isize) -> t_i32),
|
||||
"avr" | "msp430" => ifn!("memcmp", fn(ptr, ptr, t_isize) -> t_i16),
|
||||
_ => ifn!("memcmp", fn(ptr, ptr, t_isize) -> t_i32),
|
||||
}
|
||||
|
||||
// variadic intrinsics
|
||||
ifn!("llvm.va_start", fn(i8p) -> void);
|
||||
ifn!("llvm.va_end", fn(i8p) -> void);
|
||||
ifn!("llvm.va_copy", fn(i8p, i8p) -> void);
|
||||
ifn!("llvm.va_start", fn(ptr) -> void);
|
||||
ifn!("llvm.va_end", fn(ptr) -> void);
|
||||
ifn!("llvm.va_copy", fn(ptr, ptr) -> void);
|
||||
|
||||
if self.sess().instrument_coverage() {
|
||||
ifn!("llvm.instrprof.increment", fn(i8p, t_i64, t_i32, t_i32) -> void);
|
||||
ifn!("llvm.instrprof.increment", fn(ptr, t_i64, t_i32, t_i32) -> void);
|
||||
}
|
||||
|
||||
ifn!("llvm.type.test", fn(i8p, t_metadata) -> i1);
|
||||
ifn!("llvm.type.checked.load", fn(i8p, t_i32, t_metadata) -> mk_struct! {i8p, i1});
|
||||
ifn!("llvm.type.test", fn(ptr, t_metadata) -> i1);
|
||||
ifn!("llvm.type.checked.load", fn(ptr, t_i32, t_metadata) -> mk_struct! {ptr, i1});
|
||||
|
||||
if self.sess().opts.debuginfo != DebugInfo::None {
|
||||
ifn!("llvm.dbg.declare", fn(t_metadata, t_metadata) -> void);
|
||||
ifn!("llvm.dbg.value", fn(t_metadata, t_i64, t_metadata) -> void);
|
||||
}
|
||||
|
||||
ifn!("llvm.ptrmask", fn(i8p, t_isize) -> i8p);
|
||||
ifn!("llvm.ptrmask", fn(ptr, t_isize) -> ptr);
|
||||
|
||||
None
|
||||
}
|
||||
|
@ -940,12 +928,10 @@ impl<'ll> CodegenCx<'ll, '_> {
|
|||
let eh_catch_typeinfo = match tcx.lang_items().eh_catch_typeinfo() {
|
||||
Some(def_id) => self.get_static(def_id),
|
||||
_ => {
|
||||
let ty = self
|
||||
.type_struct(&[self.type_ptr_to(self.type_isize()), self.type_i8p()], false);
|
||||
let ty = self.type_struct(&[self.type_ptr(), self.type_ptr()], false);
|
||||
self.declare_global("rust_eh_catch_typeinfo", ty)
|
||||
}
|
||||
};
|
||||
let eh_catch_typeinfo = self.const_bitcast(eh_catch_typeinfo, self.type_i8p());
|
||||
self.eh_catch_typeinfo.set(Some(eh_catch_typeinfo));
|
||||
eh_catch_typeinfo
|
||||
}
|
||||
|
|
|
@ -17,8 +17,7 @@ use rustc_span::symbol::sym;
|
|||
/// .debug_gdb_scripts global is referenced, so it isn't removed by the linker.
|
||||
pub fn insert_reference_to_gdb_debug_scripts_section_global(bx: &mut Builder<'_, '_, '_>) {
|
||||
if needs_gdb_debug_scripts_section(bx) {
|
||||
let gdb_debug_scripts_section =
|
||||
bx.const_bitcast(get_or_insert_gdb_debug_scripts_section_global(bx), bx.type_i8p());
|
||||
let gdb_debug_scripts_section = get_or_insert_gdb_debug_scripts_section_global(bx);
|
||||
// Load just the first byte as that's all that's necessary to force
|
||||
// LLVM to keep around the reference to the global.
|
||||
let volatile_load_instruction = bx.volatile_load(bx.type_i8(), gdb_debug_scripts_section);
|
||||
|
|
|
@ -167,7 +167,6 @@ impl<'ll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'_, 'll, 'tcx> {
|
|||
let ptr = args[0].immediate();
|
||||
let load = if let PassMode::Cast(ty, _) = &fn_abi.ret.mode {
|
||||
let llty = ty.llvm_type(self);
|
||||
let ptr = self.pointercast(ptr, self.type_ptr_to(llty));
|
||||
self.volatile_load(llty, ptr)
|
||||
} else {
|
||||
self.volatile_load(self.layout_of(tp_ty).llvm_type(self), ptr)
|
||||
|
@ -317,18 +316,12 @@ impl<'ll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'_, 'll, 'tcx> {
|
|||
self.const_bool(true)
|
||||
} else if use_integer_compare {
|
||||
let integer_ty = self.type_ix(layout.size().bits());
|
||||
let ptr_ty = self.type_ptr_to(integer_ty);
|
||||
let a_ptr = self.bitcast(a, ptr_ty);
|
||||
let a_val = self.load(integer_ty, a_ptr, layout.align().abi);
|
||||
let b_ptr = self.bitcast(b, ptr_ty);
|
||||
let b_val = self.load(integer_ty, b_ptr, layout.align().abi);
|
||||
let a_val = self.load(integer_ty, a, layout.align().abi);
|
||||
let b_val = self.load(integer_ty, b, layout.align().abi);
|
||||
self.icmp(IntPredicate::IntEQ, a_val, b_val)
|
||||
} else {
|
||||
let i8p_ty = self.type_i8p();
|
||||
let a_ptr = self.bitcast(a, i8p_ty);
|
||||
let b_ptr = self.bitcast(b, i8p_ty);
|
||||
let n = self.const_usize(layout.size().bytes());
|
||||
let cmp = self.call_intrinsic("memcmp", &[a_ptr, b_ptr, n]);
|
||||
let cmp = self.call_intrinsic("memcmp", &[a, b, n]);
|
||||
match self.cx.sess().target.arch.as_ref() {
|
||||
"avr" | "msp430" => self.icmp(IntPredicate::IntEQ, cmp, self.const_i16(0)),
|
||||
_ => self.icmp(IntPredicate::IntEQ, cmp, self.const_i32(0)),
|
||||
|
@ -383,10 +376,8 @@ impl<'ll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'_, 'll, 'tcx> {
|
|||
};
|
||||
|
||||
if !fn_abi.ret.is_ignore() {
|
||||
if let PassMode::Cast(ty, _) = &fn_abi.ret.mode {
|
||||
let ptr_llty = self.type_ptr_to(ty.llvm_type(self));
|
||||
let ptr = self.pointercast(result.llval, ptr_llty);
|
||||
self.store(llval, ptr, result.align);
|
||||
if let PassMode::Cast(_, _) = &fn_abi.ret.mode {
|
||||
self.store(llval, result.llval, result.align);
|
||||
} else {
|
||||
OperandRef::from_immediate_or_packed_pair(self, llval, result.layout)
|
||||
.val
|
||||
|
@ -410,9 +401,7 @@ impl<'ll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'_, 'll, 'tcx> {
|
|||
fn type_test(&mut self, pointer: Self::Value, typeid: Self::Value) -> Self::Value {
|
||||
// Test the called operand using llvm.type.test intrinsic. The LowerTypeTests link-time
|
||||
// optimization pass replaces calls to this intrinsic with code to test type membership.
|
||||
let i8p_ty = self.type_i8p();
|
||||
let bitcast = self.bitcast(pointer, i8p_ty);
|
||||
self.call_intrinsic("llvm.type.test", &[bitcast, typeid])
|
||||
self.call_intrinsic("llvm.type.test", &[pointer, typeid])
|
||||
}
|
||||
|
||||
fn type_checked_load(
|
||||
|
@ -444,7 +433,7 @@ fn try_intrinsic<'ll>(
|
|||
dest: &'ll Value,
|
||||
) {
|
||||
if bx.sess().panic_strategy() == PanicStrategy::Abort {
|
||||
let try_func_ty = bx.type_func(&[bx.type_i8p()], bx.type_void());
|
||||
let try_func_ty = bx.type_func(&[bx.type_ptr()], bx.type_void());
|
||||
bx.call(try_func_ty, None, None, try_func, &[data], None);
|
||||
// Return 0 unconditionally from the intrinsic call;
|
||||
// we can never unwind.
|
||||
|
@ -544,8 +533,8 @@ fn codegen_msvc_try<'ll>(
|
|||
//
|
||||
// More information can be found in libstd's seh.rs implementation.
|
||||
let ptr_align = bx.tcx().data_layout.pointer_align.abi;
|
||||
let slot = bx.alloca(bx.type_i8p(), ptr_align);
|
||||
let try_func_ty = bx.type_func(&[bx.type_i8p()], bx.type_void());
|
||||
let slot = bx.alloca(bx.type_ptr(), ptr_align);
|
||||
let try_func_ty = bx.type_func(&[bx.type_ptr()], bx.type_void());
|
||||
bx.invoke(try_func_ty, None, None, try_func, &[data], normal, catchswitch, None);
|
||||
|
||||
bx.switch_to_block(normal);
|
||||
|
@ -568,10 +557,10 @@ fn codegen_msvc_try<'ll>(
|
|||
//
|
||||
// When modifying, make sure that the type_name string exactly matches
|
||||
// the one used in library/panic_unwind/src/seh.rs.
|
||||
let type_info_vtable = bx.declare_global("??_7type_info@@6B@", bx.type_i8p());
|
||||
let type_info_vtable = bx.declare_global("??_7type_info@@6B@", bx.type_ptr());
|
||||
let type_name = bx.const_bytes(b"rust_panic\0");
|
||||
let type_info =
|
||||
bx.const_struct(&[type_info_vtable, bx.const_null(bx.type_i8p()), type_name], false);
|
||||
bx.const_struct(&[type_info_vtable, bx.const_null(bx.type_ptr()), type_name], false);
|
||||
let tydesc = bx.declare_global("__rust_panic_type_info", bx.val_ty(type_info));
|
||||
unsafe {
|
||||
llvm::LLVMRustSetLinkage(tydesc, llvm::Linkage::LinkOnceODRLinkage);
|
||||
|
@ -588,15 +577,15 @@ fn codegen_msvc_try<'ll>(
|
|||
bx.switch_to_block(catchpad_rust);
|
||||
let flags = bx.const_i32(8);
|
||||
let funclet = bx.catch_pad(cs, &[tydesc, flags, slot]);
|
||||
let ptr = bx.load(bx.type_i8p(), slot, ptr_align);
|
||||
let catch_ty = bx.type_func(&[bx.type_i8p(), bx.type_i8p()], bx.type_void());
|
||||
let ptr = bx.load(bx.type_ptr(), slot, ptr_align);
|
||||
let catch_ty = bx.type_func(&[bx.type_ptr(), bx.type_ptr()], bx.type_void());
|
||||
bx.call(catch_ty, None, None, catch_func, &[data, ptr], Some(&funclet));
|
||||
bx.catch_ret(&funclet, caught);
|
||||
|
||||
// The flag value of 64 indicates a "catch-all".
|
||||
bx.switch_to_block(catchpad_foreign);
|
||||
let flags = bx.const_i32(64);
|
||||
let null = bx.const_null(bx.type_i8p());
|
||||
let null = bx.const_null(bx.type_ptr());
|
||||
let funclet = bx.catch_pad(cs, &[null, flags, null]);
|
||||
bx.call(catch_ty, None, None, catch_func, &[data, null], Some(&funclet));
|
||||
bx.catch_ret(&funclet, caught);
|
||||
|
@ -655,7 +644,7 @@ fn codegen_wasm_try<'ll>(
|
|||
// ret i32 1
|
||||
// }
|
||||
//
|
||||
let try_func_ty = bx.type_func(&[bx.type_i8p()], bx.type_void());
|
||||
let try_func_ty = bx.type_func(&[bx.type_ptr()], bx.type_void());
|
||||
bx.invoke(try_func_ty, None, None, try_func, &[data], normal, catchswitch, None);
|
||||
|
||||
bx.switch_to_block(normal);
|
||||
|
@ -665,13 +654,13 @@ fn codegen_wasm_try<'ll>(
|
|||
let cs = bx.catch_switch(None, None, &[catchpad]);
|
||||
|
||||
bx.switch_to_block(catchpad);
|
||||
let null = bx.const_null(bx.type_i8p());
|
||||
let null = bx.const_null(bx.type_ptr());
|
||||
let funclet = bx.catch_pad(cs, &[null]);
|
||||
|
||||
let ptr = bx.call_intrinsic("llvm.wasm.get.exception", &[funclet.cleanuppad()]);
|
||||
let _sel = bx.call_intrinsic("llvm.wasm.get.ehselector", &[funclet.cleanuppad()]);
|
||||
|
||||
let catch_ty = bx.type_func(&[bx.type_i8p(), bx.type_i8p()], bx.type_void());
|
||||
let catch_ty = bx.type_func(&[bx.type_ptr(), bx.type_ptr()], bx.type_void());
|
||||
bx.call(catch_ty, None, None, catch_func, &[data, ptr], Some(&funclet));
|
||||
bx.catch_ret(&funclet, caught);
|
||||
|
||||
|
@ -723,7 +712,7 @@ fn codegen_gnu_try<'ll>(
|
|||
let try_func = llvm::get_param(bx.llfn(), 0);
|
||||
let data = llvm::get_param(bx.llfn(), 1);
|
||||
let catch_func = llvm::get_param(bx.llfn(), 2);
|
||||
let try_func_ty = bx.type_func(&[bx.type_i8p()], bx.type_void());
|
||||
let try_func_ty = bx.type_func(&[bx.type_ptr()], bx.type_void());
|
||||
bx.invoke(try_func_ty, None, None, try_func, &[data], then, catch, None);
|
||||
|
||||
bx.switch_to_block(then);
|
||||
|
@ -736,12 +725,12 @@ fn codegen_gnu_try<'ll>(
|
|||
// the landing pad clauses the exception's type had been matched to.
|
||||
// rust_try ignores the selector.
|
||||
bx.switch_to_block(catch);
|
||||
let lpad_ty = bx.type_struct(&[bx.type_i8p(), bx.type_i32()], false);
|
||||
let lpad_ty = bx.type_struct(&[bx.type_ptr(), bx.type_i32()], false);
|
||||
let vals = bx.landing_pad(lpad_ty, bx.eh_personality(), 1);
|
||||
let tydesc = bx.const_null(bx.type_i8p());
|
||||
let tydesc = bx.const_null(bx.type_ptr());
|
||||
bx.add_clause(vals, tydesc);
|
||||
let ptr = bx.extract_value(vals, 0);
|
||||
let catch_ty = bx.type_func(&[bx.type_i8p(), bx.type_i8p()], bx.type_void());
|
||||
let catch_ty = bx.type_func(&[bx.type_ptr(), bx.type_ptr()], bx.type_void());
|
||||
bx.call(catch_ty, None, None, catch_func, &[data, ptr], None);
|
||||
bx.ret(bx.const_i32(1));
|
||||
});
|
||||
|
@ -787,7 +776,7 @@ fn codegen_emcc_try<'ll>(
|
|||
let try_func = llvm::get_param(bx.llfn(), 0);
|
||||
let data = llvm::get_param(bx.llfn(), 1);
|
||||
let catch_func = llvm::get_param(bx.llfn(), 2);
|
||||
let try_func_ty = bx.type_func(&[bx.type_i8p()], bx.type_void());
|
||||
let try_func_ty = bx.type_func(&[bx.type_ptr()], bx.type_void());
|
||||
bx.invoke(try_func_ty, None, None, try_func, &[data], then, catch, None);
|
||||
|
||||
bx.switch_to_block(then);
|
||||
|
@ -800,10 +789,10 @@ fn codegen_emcc_try<'ll>(
|
|||
// the landing pad clauses the exception's type had been matched to.
|
||||
bx.switch_to_block(catch);
|
||||
let tydesc = bx.eh_catch_typeinfo();
|
||||
let lpad_ty = bx.type_struct(&[bx.type_i8p(), bx.type_i32()], false);
|
||||
let lpad_ty = bx.type_struct(&[bx.type_ptr(), bx.type_i32()], false);
|
||||
let vals = bx.landing_pad(lpad_ty, bx.eh_personality(), 2);
|
||||
bx.add_clause(vals, tydesc);
|
||||
bx.add_clause(vals, bx.const_null(bx.type_i8p()));
|
||||
bx.add_clause(vals, bx.const_null(bx.type_ptr()));
|
||||
let ptr = bx.extract_value(vals, 0);
|
||||
let selector = bx.extract_value(vals, 1);
|
||||
|
||||
|
@ -816,7 +805,7 @@ fn codegen_emcc_try<'ll>(
|
|||
// create an alloca and pass a pointer to that.
|
||||
let ptr_align = bx.tcx().data_layout.pointer_align.abi;
|
||||
let i8_align = bx.tcx().data_layout.i8_align.abi;
|
||||
let catch_data_type = bx.type_struct(&[bx.type_i8p(), bx.type_bool()], false);
|
||||
let catch_data_type = bx.type_struct(&[bx.type_ptr(), bx.type_bool()], false);
|
||||
let catch_data = bx.alloca(catch_data_type, ptr_align);
|
||||
let catch_data_0 =
|
||||
bx.inbounds_gep(catch_data_type, catch_data, &[bx.const_usize(0), bx.const_usize(0)]);
|
||||
|
@ -824,9 +813,8 @@ fn codegen_emcc_try<'ll>(
|
|||
let catch_data_1 =
|
||||
bx.inbounds_gep(catch_data_type, catch_data, &[bx.const_usize(0), bx.const_usize(1)]);
|
||||
bx.store(is_rust_panic, catch_data_1, i8_align);
|
||||
let catch_data = bx.bitcast(catch_data, bx.type_i8p());
|
||||
|
||||
let catch_ty = bx.type_func(&[bx.type_i8p(), bx.type_i8p()], bx.type_void());
|
||||
let catch_ty = bx.type_func(&[bx.type_ptr(), bx.type_ptr()], bx.type_void());
|
||||
bx.call(catch_ty, None, None, catch_func, &[data, catch_data], None);
|
||||
bx.ret(bx.const_i32(1));
|
||||
});
|
||||
|
@ -967,8 +955,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
|||
let place = PlaceRef::alloca(bx, args[0].layout);
|
||||
args[0].val.store(bx, place);
|
||||
let int_ty = bx.type_ix(expected_bytes * 8);
|
||||
let ptr = bx.pointercast(place.llval, bx.cx.type_ptr_to(int_ty));
|
||||
bx.load(int_ty, ptr, Align::ONE)
|
||||
bx.load(int_ty, place.llval, Align::ONE)
|
||||
}
|
||||
_ => return_error!(InvalidMonomorphization::InvalidBitmask {
|
||||
span,
|
||||
|
@ -1217,7 +1204,6 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
|||
let ptr = bx.alloca(bx.type_ix(expected_bytes * 8), Align::ONE);
|
||||
bx.store(ze, ptr, Align::ONE);
|
||||
let array_ty = bx.type_array(bx.type_i8(), expected_bytes);
|
||||
let ptr = bx.pointercast(ptr, bx.cx.type_ptr_to(array_ty));
|
||||
return Ok(bx.load(array_ty, ptr, Align::ONE));
|
||||
}
|
||||
_ => return_error!(InvalidMonomorphization::CannotReturn {
|
||||
|
@ -1352,7 +1338,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
|||
cx: &CodegenCx<'ll, '_>,
|
||||
elem_ty: Ty<'_>,
|
||||
vec_len: u64,
|
||||
mut no_pointers: usize,
|
||||
no_pointers: usize,
|
||||
) -> &'ll Type {
|
||||
// FIXME: use cx.layout_of(ty).llvm_type() ?
|
||||
let mut elem_ty = match *elem_ty.kind() {
|
||||
|
@ -1361,9 +1347,8 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
|||
ty::Float(v) => cx.type_float_from_ty(v),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
while no_pointers > 0 {
|
||||
elem_ty = cx.type_ptr_to(elem_ty);
|
||||
no_pointers -= 1;
|
||||
if no_pointers > 0 {
|
||||
elem_ty = cx.type_ptr();
|
||||
}
|
||||
cx.type_vector(elem_ty, vec_len)
|
||||
}
|
||||
|
@ -1857,11 +1842,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
|||
}
|
||||
}
|
||||
|
||||
if in_elem == out_elem {
|
||||
return Ok(args[0].immediate());
|
||||
} else {
|
||||
return Ok(bx.pointercast(args[0].immediate(), llret_ty));
|
||||
}
|
||||
return Ok(args[0].immediate());
|
||||
}
|
||||
|
||||
if name == sym::simd_expose_addr {
|
||||
|
|
|
@ -1073,7 +1073,7 @@ extern "C" {
|
|||
|
||||
// Operations on array, pointer, and vector types (sequence types)
|
||||
pub fn LLVMRustArrayType(ElementType: &Type, ElementCount: u64) -> &Type;
|
||||
pub fn LLVMPointerType(ElementType: &Type, AddressSpace: c_uint) -> &Type;
|
||||
pub fn LLVMPointerTypeInContext(C: &Context, AddressSpace: c_uint) -> &Type;
|
||||
pub fn LLVMVectorType(ElementType: &Type, ElementCount: c_uint) -> &Type;
|
||||
|
||||
pub fn LLVMGetElementType(Ty: &Type) -> &Type;
|
||||
|
|
|
@ -69,6 +69,14 @@ impl<'ll> CodegenCx<'ll, '_> {
|
|||
unsafe { llvm::LLVMVectorType(ty, len as c_uint) }
|
||||
}
|
||||
|
||||
pub(crate) fn type_ptr(&self) -> &'ll Type {
|
||||
self.type_ptr_ext(AddressSpace::DATA)
|
||||
}
|
||||
|
||||
pub(crate) fn type_ptr_ext(&self, address_space: AddressSpace) -> &'ll Type {
|
||||
unsafe { llvm::LLVMPointerTypeInContext(self.llcx, address_space.0) }
|
||||
}
|
||||
|
||||
pub(crate) fn func_params_types(&self, ty: &'ll Type) -> Vec<&'ll Type> {
|
||||
unsafe {
|
||||
let n_args = llvm::LLVMCountParamTypes(ty) as usize;
|
||||
|
@ -112,12 +120,6 @@ impl<'ll> CodegenCx<'ll, '_> {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn type_pointee_for_align(&self, align: Align) -> &'ll Type {
|
||||
// FIXME(eddyb) We could find a better approximation if ity.align < align.
|
||||
let ity = Integer::approximate_align(self, align);
|
||||
self.type_from_integer(ity)
|
||||
}
|
||||
|
||||
/// Return a LLVM type that has at most the required alignment,
|
||||
/// and exactly the required size, as a best-effort padding array.
|
||||
pub(crate) fn type_padding_filler(&self, size: Size, align: Align) -> &'ll Type {
|
||||
|
@ -189,17 +191,12 @@ impl<'ll, 'tcx> BaseTypeMethods<'tcx> for CodegenCx<'ll, 'tcx> {
|
|||
unsafe { llvm::LLVMRustGetTypeKind(ty).to_generic() }
|
||||
}
|
||||
|
||||
fn type_ptr_to(&self, ty: &'ll Type) -> &'ll Type {
|
||||
assert_ne!(
|
||||
self.type_kind(ty),
|
||||
TypeKind::Function,
|
||||
"don't call ptr_to on function types, use ptr_to_llvm_type on FnAbi instead or explicitly specify an address space if it makes sense"
|
||||
);
|
||||
ty.ptr_to(AddressSpace::DATA)
|
||||
fn type_ptr_to(&self, _ty: &'ll Type) -> &'ll Type {
|
||||
self.type_ptr()
|
||||
}
|
||||
|
||||
fn type_ptr_to_ext(&self, ty: &'ll Type, address_space: AddressSpace) -> &'ll Type {
|
||||
ty.ptr_to(address_space)
|
||||
fn type_ptr_to_ext(&self, _ty: &'ll Type, address_space: AddressSpace) -> &'ll Type {
|
||||
self.type_ptr_ext(address_space)
|
||||
}
|
||||
|
||||
fn element_type(&self, ty: &'ll Type) -> &'ll Type {
|
||||
|
@ -247,12 +244,8 @@ impl Type {
|
|||
unsafe { llvm::LLVMIntTypeInContext(llcx, num_bits as c_uint) }
|
||||
}
|
||||
|
||||
pub fn i8p_llcx(llcx: &llvm::Context) -> &Type {
|
||||
Type::i8_llcx(llcx).ptr_to(AddressSpace::DATA)
|
||||
}
|
||||
|
||||
fn ptr_to(&self, address_space: AddressSpace) -> &Type {
|
||||
unsafe { llvm::LLVMPointerType(self, address_space.0) }
|
||||
pub fn ptr_llcx(llcx: &llvm::Context) -> &Type {
|
||||
unsafe { llvm::LLVMPointerTypeInContext(llcx, AddressSpace::DATA.0) }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ fn uncached_llvm_type<'a, 'tcx>(
|
|||
match layout.abi {
|
||||
Abi::Scalar(_) => bug!("handled elsewhere"),
|
||||
Abi::Vector { element, count } => {
|
||||
let element = layout.scalar_llvm_type_at(cx, element, Size::ZERO);
|
||||
let element = layout.scalar_llvm_type_at(cx, element);
|
||||
return cx.type_vector(element, count);
|
||||
}
|
||||
Abi::ScalarPair(..) => {
|
||||
|
@ -179,12 +179,7 @@ pub trait LayoutLlvmExt<'tcx> {
|
|||
fn is_llvm_scalar_pair(&self) -> bool;
|
||||
fn llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> &'a Type;
|
||||
fn immediate_llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> &'a Type;
|
||||
fn scalar_llvm_type_at<'a>(
|
||||
&self,
|
||||
cx: &CodegenCx<'a, 'tcx>,
|
||||
scalar: Scalar,
|
||||
offset: Size,
|
||||
) -> &'a Type;
|
||||
fn scalar_llvm_type_at<'a>(&self, cx: &CodegenCx<'a, 'tcx>, scalar: Scalar) -> &'a Type;
|
||||
fn scalar_pair_element_llvm_type<'a>(
|
||||
&self,
|
||||
cx: &CodegenCx<'a, 'tcx>,
|
||||
|
@ -230,16 +225,12 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> {
|
|||
return llty;
|
||||
}
|
||||
let llty = match *self.ty.kind() {
|
||||
ty::Ref(_, ty, _) | ty::RawPtr(ty::TypeAndMut { ty, .. }) => {
|
||||
cx.type_ptr_to(cx.layout_of(ty).llvm_type(cx))
|
||||
}
|
||||
ty::Adt(def, _) if def.is_box() => {
|
||||
cx.type_ptr_to(cx.layout_of(self.ty.boxed_ty()).llvm_type(cx))
|
||||
}
|
||||
ty::Ref(..) | ty::RawPtr(ty::TypeAndMut { .. }) => cx.type_ptr(),
|
||||
ty::Adt(def, _) if def.is_box() => cx.type_ptr(),
|
||||
ty::FnPtr(sig) => {
|
||||
cx.fn_ptr_backend_type(cx.fn_abi_of_fn_ptr(sig, ty::List::empty()))
|
||||
}
|
||||
_ => self.scalar_llvm_type_at(cx, scalar, Size::ZERO),
|
||||
_ => self.scalar_llvm_type_at(cx, scalar),
|
||||
};
|
||||
cx.scalar_lltypes.borrow_mut().insert(self.ty, llty);
|
||||
return llty;
|
||||
|
@ -300,25 +291,12 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> {
|
|||
self.llvm_type(cx)
|
||||
}
|
||||
|
||||
fn scalar_llvm_type_at<'a>(
|
||||
&self,
|
||||
cx: &CodegenCx<'a, 'tcx>,
|
||||
scalar: Scalar,
|
||||
offset: Size,
|
||||
) -> &'a Type {
|
||||
fn scalar_llvm_type_at<'a>(&self, cx: &CodegenCx<'a, 'tcx>, scalar: Scalar) -> &'a Type {
|
||||
match scalar.primitive() {
|
||||
Int(i, _) => cx.type_from_integer(i),
|
||||
F32 => cx.type_f32(),
|
||||
F64 => cx.type_f64(),
|
||||
Pointer(address_space) => {
|
||||
// If we know the alignment, pick something better than i8.
|
||||
let pointee = if let Some(pointee) = self.pointee_info_at(cx, offset) {
|
||||
cx.type_pointee_for_align(pointee.align)
|
||||
} else {
|
||||
cx.type_i8()
|
||||
};
|
||||
cx.type_ptr_to_ext(pointee, address_space)
|
||||
}
|
||||
Pointer(address_space) => cx.type_ptr_ext(address_space),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -364,8 +342,7 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> {
|
|||
return cx.type_i1();
|
||||
}
|
||||
|
||||
let offset = if index == 0 { Size::ZERO } else { a.size(cx).align_to(b.align(cx).abi) };
|
||||
self.scalar_llvm_type_at(cx, scalar, offset)
|
||||
self.scalar_llvm_type_at(cx, scalar)
|
||||
}
|
||||
|
||||
fn llvm_field_index<'a>(&self, cx: &CodegenCx<'a, 'tcx>, index: usize) -> u64 {
|
||||
|
|
|
@ -5,7 +5,7 @@ use crate::value::Value;
|
|||
use rustc_codegen_ssa::mir::operand::OperandRef;
|
||||
use rustc_codegen_ssa::{
|
||||
common::IntPredicate,
|
||||
traits::{BaseTypeMethods, BuilderMethods, ConstMethods, DerivedTypeMethods},
|
||||
traits::{BaseTypeMethods, BuilderMethods, ConstMethods},
|
||||
};
|
||||
use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf};
|
||||
use rustc_middle::ty::Ty;
|
||||
|
@ -26,24 +26,18 @@ fn round_pointer_up_to_alignment<'ll>(
|
|||
fn emit_direct_ptr_va_arg<'ll, 'tcx>(
|
||||
bx: &mut Builder<'_, 'll, 'tcx>,
|
||||
list: OperandRef<'tcx, &'ll Value>,
|
||||
llty: &'ll Type,
|
||||
size: Size,
|
||||
align: Align,
|
||||
slot_size: Align,
|
||||
allow_higher_align: bool,
|
||||
) -> (&'ll Value, Align) {
|
||||
let va_list_ty = bx.type_i8p();
|
||||
let va_list_ptr_ty = bx.type_ptr_to(va_list_ty);
|
||||
let va_list_addr = if list.layout.llvm_type(bx.cx) != va_list_ptr_ty {
|
||||
bx.bitcast(list.immediate(), va_list_ptr_ty)
|
||||
} else {
|
||||
list.immediate()
|
||||
};
|
||||
let va_list_ty = bx.type_ptr();
|
||||
let va_list_addr = list.immediate();
|
||||
|
||||
let ptr = bx.load(va_list_ty, va_list_addr, bx.tcx().data_layout.pointer_align.abi);
|
||||
|
||||
let (addr, addr_align) = if allow_higher_align && align > slot_size {
|
||||
(round_pointer_up_to_alignment(bx, ptr, align, bx.cx().type_i8p()), align)
|
||||
(round_pointer_up_to_alignment(bx, ptr, align, bx.type_ptr()), align)
|
||||
} else {
|
||||
(ptr, slot_size)
|
||||
};
|
||||
|
@ -56,9 +50,9 @@ fn emit_direct_ptr_va_arg<'ll, 'tcx>(
|
|||
if size.bytes() < slot_size.bytes() && bx.tcx().sess.target.endian == Endian::Big {
|
||||
let adjusted_size = bx.cx().const_i32((slot_size.bytes() - size.bytes()) as i32);
|
||||
let adjusted = bx.inbounds_gep(bx.type_i8(), addr, &[adjusted_size]);
|
||||
(bx.bitcast(adjusted, bx.cx().type_ptr_to(llty)), addr_align)
|
||||
(adjusted, addr_align)
|
||||
} else {
|
||||
(bx.bitcast(addr, bx.cx().type_ptr_to(llty)), addr_align)
|
||||
(addr, addr_align)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -81,7 +75,7 @@ fn emit_ptr_va_arg<'ll, 'tcx>(
|
|||
(layout.llvm_type(bx.cx), layout.size, layout.align)
|
||||
};
|
||||
let (addr, addr_align) =
|
||||
emit_direct_ptr_va_arg(bx, list, llty, size, align.abi, slot_size, allow_higher_align);
|
||||
emit_direct_ptr_va_arg(bx, list, size, align.abi, slot_size, allow_higher_align);
|
||||
if indirect {
|
||||
let tmp_ret = bx.load(llty, addr, addr_align);
|
||||
bx.load(bx.cx.layout_of(target_ty).llvm_type(bx.cx), tmp_ret, align.abi)
|
||||
|
@ -146,7 +140,7 @@ fn emit_aapcs_va_arg<'ll, 'tcx>(
|
|||
bx.cond_br(use_stack, on_stack, in_reg);
|
||||
|
||||
bx.switch_to_block(in_reg);
|
||||
let top_type = bx.type_i8p();
|
||||
let top_type = bx.type_ptr();
|
||||
let top = bx.struct_gep(va_list_ty, va_list_addr, reg_top_index);
|
||||
let top = bx.load(top_type, top, bx.tcx().data_layout.pointer_align.abi);
|
||||
|
||||
|
@ -158,7 +152,6 @@ fn emit_aapcs_va_arg<'ll, 'tcx>(
|
|||
reg_addr = bx.gep(bx.type_i8(), reg_addr, &[offset]);
|
||||
}
|
||||
let reg_type = layout.llvm_type(bx);
|
||||
let reg_addr = bx.bitcast(reg_addr, bx.cx.type_ptr_to(reg_type));
|
||||
let reg_value = bx.load(reg_type, reg_addr, layout.align.abi);
|
||||
bx.br(end);
|
||||
|
||||
|
@ -218,7 +211,7 @@ fn emit_s390x_va_arg<'ll, 'tcx>(
|
|||
// Work out the address of the value in the register save area.
|
||||
let reg_ptr =
|
||||
bx.struct_gep(va_list_ty, va_list_addr, va_list_layout.llvm_field_index(bx.cx, 3));
|
||||
let reg_ptr_v = bx.load(bx.type_i8p(), reg_ptr, bx.tcx().data_layout.pointer_align.abi);
|
||||
let reg_ptr_v = bx.load(bx.type_ptr(), reg_ptr, bx.tcx().data_layout.pointer_align.abi);
|
||||
let scaled_reg_count = bx.mul(reg_count_v, bx.const_u64(8));
|
||||
let reg_off = bx.add(scaled_reg_count, bx.const_u64(reg_save_index * 8 + reg_padding));
|
||||
let reg_addr = bx.gep(bx.type_i8(), reg_ptr_v, &[reg_off]);
|
||||
|
@ -234,7 +227,7 @@ fn emit_s390x_va_arg<'ll, 'tcx>(
|
|||
// Work out the address of the value in the argument overflow area.
|
||||
let arg_ptr =
|
||||
bx.struct_gep(va_list_ty, va_list_addr, va_list_layout.llvm_field_index(bx.cx, 2));
|
||||
let arg_ptr_v = bx.load(bx.type_i8p(), arg_ptr, bx.tcx().data_layout.pointer_align.abi);
|
||||
let arg_ptr_v = bx.load(bx.type_ptr(), arg_ptr, bx.tcx().data_layout.pointer_align.abi);
|
||||
let arg_off = bx.const_u64(padding);
|
||||
let mem_addr = bx.gep(bx.type_i8(), arg_ptr_v, &[arg_off]);
|
||||
|
||||
|
@ -246,14 +239,12 @@ fn emit_s390x_va_arg<'ll, 'tcx>(
|
|||
|
||||
// Return the appropriate result.
|
||||
bx.switch_to_block(end);
|
||||
let val_addr = bx.phi(bx.type_i8p(), &[reg_addr, mem_addr], &[in_reg, in_mem]);
|
||||
let val_addr = bx.phi(bx.type_ptr(), &[reg_addr, mem_addr], &[in_reg, in_mem]);
|
||||
let val_type = layout.llvm_type(bx);
|
||||
let val_addr = if indirect {
|
||||
let ptr_type = bx.cx.type_ptr_to(val_type);
|
||||
let ptr_addr = bx.bitcast(val_addr, bx.cx.type_ptr_to(ptr_type));
|
||||
bx.load(ptr_type, ptr_addr, bx.tcx().data_layout.pointer_align.abi)
|
||||
bx.load(bx.cx.type_ptr(), val_addr, bx.tcx().data_layout.pointer_align.abi)
|
||||
} else {
|
||||
bx.bitcast(val_addr, bx.cx.type_ptr_to(val_type))
|
||||
val_addr
|
||||
};
|
||||
bx.load(val_type, val_addr, layout.align.abi)
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue