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}.
|
// uses it for i16 -> {i8, i8}, but not for i24 -> {i8, i8, i8}.
|
||||||
let can_store_through_cast_ptr = false;
|
let can_store_through_cast_ptr = false;
|
||||||
if can_store_through_cast_ptr {
|
if can_store_through_cast_ptr {
|
||||||
let cast_ptr_llty = bx.type_ptr_to(cast.llvm_type(bx));
|
bx.store(val, dst.llval, self.layout.align.abi);
|
||||||
let cast_dst = bx.pointercast(dst.llval, cast_ptr_llty);
|
|
||||||
bx.store(val, cast_dst, self.layout.align.abi);
|
|
||||||
} else {
|
} else {
|
||||||
// The actual return type is a struct, but the ABI
|
// The actual return type is a struct, but the ABI
|
||||||
// adaptation code has cast it into some scalar type. The
|
// 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::Direct(_) | PassMode::Pair(..) => self.ret.layout.immediate_llvm_type(cx),
|
||||||
PassMode::Cast(cast, _) => cast.llvm_type(cx),
|
PassMode::Cast(cast, _) => cast.llvm_type(cx),
|
||||||
PassMode::Indirect { .. } => {
|
PassMode::Indirect { .. } => {
|
||||||
llargument_tys.push(cx.type_ptr_to(self.ret.memory_ty(cx)));
|
llargument_tys.push(cx.type_ptr());
|
||||||
cx.type_void()
|
cx.type_void()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -364,9 +362,7 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
|
||||||
}
|
}
|
||||||
cast.llvm_type(cx)
|
cast.llvm_type(cx)
|
||||||
}
|
}
|
||||||
PassMode::Indirect { attrs: _, extra_attrs: None, on_stack: _ } => {
|
PassMode::Indirect { attrs: _, extra_attrs: None, on_stack: _ } => cx.type_ptr(),
|
||||||
cx.type_ptr_to(arg.memory_ty(cx))
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
llargument_tys.push(llarg_ty);
|
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 {
|
fn ptr_to_llvm_type(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type {
|
||||||
unsafe {
|
cx.type_ptr_ext(cx.data_layout().instruction_address_space)
|
||||||
llvm::LLVMPointerType(
|
|
||||||
self.llvm_type(cx),
|
|
||||||
cx.data_layout().instruction_address_space.0 as c_uint,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn llvm_cconv(&self) -> llvm::CallConv {
|
fn llvm_cconv(&self) -> llvm::CallConv {
|
||||||
|
|
|
@ -28,7 +28,7 @@ pub(crate) unsafe fn codegen(
|
||||||
tws => bug!("Unsupported target word size for int: {}", tws),
|
tws => bug!("Unsupported target word size for int: {}", tws),
|
||||||
};
|
};
|
||||||
let i8 = llvm::LLVMInt8TypeInContext(llcx);
|
let i8 = llvm::LLVMInt8TypeInContext(llcx);
|
||||||
let i8p = llvm::LLVMPointerType(i8, 0);
|
let i8p = llvm::LLVMPointerTypeInContext(llcx, 0);
|
||||||
let void = llvm::LLVMVoidTypeInContext(llcx);
|
let void = llvm::LLVMVoidTypeInContext(llcx);
|
||||||
|
|
||||||
if kind == AllocatorKind::Default {
|
if kind == AllocatorKind::Default {
|
||||||
|
|
|
@ -4,7 +4,6 @@ use crate::back::profiling::{
|
||||||
};
|
};
|
||||||
use crate::base;
|
use crate::base;
|
||||||
use crate::common;
|
use crate::common;
|
||||||
use crate::consts;
|
|
||||||
use crate::errors::{
|
use crate::errors::{
|
||||||
CopyBitcode, FromLlvmDiag, FromLlvmOptimizationDiag, LlvmError, WithLlvmError, WriteBytecode,
|
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_" };
|
let prefix = if cgcx.target_arch == "x86" { "\x01__imp__" } else { "\x01__imp_" };
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let i8p_ty = Type::i8p_llcx(llcx);
|
let ptr_ty = Type::ptr_llcx(llcx);
|
||||||
let globals = base::iter_globals(llmod)
|
let globals = base::iter_globals(llmod)
|
||||||
.filter(|&val| {
|
.filter(|&val| {
|
||||||
llvm::LLVMRustGetLinkage(val) == llvm::Linkage::ExternalLinkage
|
llvm::LLVMRustGetLinkage(val) == llvm::Linkage::ExternalLinkage
|
||||||
|
@ -1012,8 +1011,8 @@ fn create_msvc_imps(
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
for (imp_name, val) in globals {
|
for (imp_name, val) in globals {
|
||||||
let imp = llvm::LLVMAddGlobal(llmod, i8p_ty, imp_name.as_ptr().cast());
|
let imp = llvm::LLVMAddGlobal(llmod, ptr_ty, imp_name.as_ptr().cast());
|
||||||
llvm::LLVMSetInitializer(imp, consts::ptrcast(val, i8p_ty));
|
llvm::LLVMSetInitializer(imp, val);
|
||||||
llvm::LLVMRustSetLinkage(imp, llvm::Linkage::ExternalLinkage);
|
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.
|
// happen after the llvm.used variables are created.
|
||||||
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, cx.val_ty(old_g));
|
llvm::LLVMReplaceAllUsesWith(old_g, new_g);
|
||||||
llvm::LLVMReplaceAllUsesWith(old_g, bitcast);
|
|
||||||
llvm::LLVMDeleteGlobal(old_g);
|
llvm::LLVMDeleteGlobal(old_g);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -652,7 +652,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
|
||||||
flags: MemFlags,
|
flags: MemFlags,
|
||||||
) -> &'ll Value {
|
) -> &'ll Value {
|
||||||
debug!("Store {:?} -> {:?} ({:?})", val, ptr, flags);
|
debug!("Store {:?} -> {:?} ({:?})", val, ptr, flags);
|
||||||
let ptr = self.check_store(val, ptr);
|
let ptr = self.check_store(ptr);
|
||||||
unsafe {
|
unsafe {
|
||||||
let store = llvm::LLVMBuildStore(self.llbuilder, val, ptr);
|
let store = llvm::LLVMBuildStore(self.llbuilder, val, ptr);
|
||||||
let align =
|
let align =
|
||||||
|
@ -682,7 +682,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
|
||||||
size: Size,
|
size: Size,
|
||||||
) {
|
) {
|
||||||
debug!("Store {:?} -> {:?}", val, ptr);
|
debug!("Store {:?} -> {:?}", val, ptr);
|
||||||
let ptr = self.check_store(val, ptr);
|
let ptr = self.check_store(ptr);
|
||||||
unsafe {
|
unsafe {
|
||||||
let store = llvm::LLVMRustBuildAtomicStore(
|
let store = llvm::LLVMRustBuildAtomicStore(
|
||||||
self.llbuilder,
|
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");
|
assert!(!flags.contains(MemFlags::NONTEMPORAL), "non-temporal memcpy not supported");
|
||||||
let size = self.intcast(size, self.type_isize(), false);
|
let size = self.intcast(size, self.type_isize(), false);
|
||||||
let is_volatile = flags.contains(MemFlags::VOLATILE);
|
let is_volatile = flags.contains(MemFlags::VOLATILE);
|
||||||
let dst = self.pointercast(dst, self.type_i8p());
|
|
||||||
let src = self.pointercast(src, self.type_i8p());
|
|
||||||
unsafe {
|
unsafe {
|
||||||
llvm::LLVMRustBuildMemCpy(
|
llvm::LLVMRustBuildMemCpy(
|
||||||
self.llbuilder,
|
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");
|
assert!(!flags.contains(MemFlags::NONTEMPORAL), "non-temporal memmove not supported");
|
||||||
let size = self.intcast(size, self.type_isize(), false);
|
let size = self.intcast(size, self.type_isize(), false);
|
||||||
let is_volatile = flags.contains(MemFlags::VOLATILE);
|
let is_volatile = flags.contains(MemFlags::VOLATILE);
|
||||||
let dst = self.pointercast(dst, self.type_i8p());
|
|
||||||
let src = self.pointercast(src, self.type_i8p());
|
|
||||||
unsafe {
|
unsafe {
|
||||||
llvm::LLVMRustBuildMemMove(
|
llvm::LLVMRustBuildMemMove(
|
||||||
self.llbuilder,
|
self.llbuilder,
|
||||||
|
@ -924,7 +920,6 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
|
||||||
flags: MemFlags,
|
flags: MemFlags,
|
||||||
) {
|
) {
|
||||||
let is_volatile = flags.contains(MemFlags::VOLATILE);
|
let is_volatile = flags.contains(MemFlags::VOLATILE);
|
||||||
let ptr = self.pointercast(ptr, self.type_i8p());
|
|
||||||
unsafe {
|
unsafe {
|
||||||
llvm::LLVMRustBuildMemSet(
|
llvm::LLVMRustBuildMemSet(
|
||||||
self.llbuilder,
|
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) {
|
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);
|
let landing_pad = self.landing_pad(ty, pers_fn, 0);
|
||||||
unsafe {
|
unsafe {
|
||||||
llvm::LLVMSetCleanup(landing_pad, llvm::True);
|
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) {
|
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);
|
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))
|
(self.extract_value(landing_pad, 0), self.extract_value(landing_pad, 1))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resume(&mut self, exn0: &'ll Value, exn1: &'ll Value) {
|
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);
|
let mut exn = self.const_poison(ty);
|
||||||
exn = self.insert_value(exn, exn0, 0);
|
exn = self.insert_value(exn, exn0, 0);
|
||||||
exn = self.insert_value(exn, exn1, 1);
|
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 llfn = unsafe { llvm::LLVMRustGetInstrProfIncrementIntrinsic(self.cx().llmod) };
|
||||||
let llty = self.cx.type_func(
|
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(),
|
self.cx.type_void(),
|
||||||
);
|
);
|
||||||
let args = &[fn_name, hash, num_counters, index];
|
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")
|
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 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);
|
assert_eq!(self.cx.type_kind(dest_ptr_ty), TypeKind::Pointer);
|
||||||
|
|
||||||
if dest_ptr_ty == stored_ptr_ty {
|
|
||||||
ptr
|
ptr
|
||||||
} else {
|
|
||||||
debug!(
|
|
||||||
"type mismatch in store. \
|
|
||||||
Expected {:?}, got {:?}; inserting bitcast",
|
|
||||||
dest_ptr_ty, stored_ptr_ty
|
|
||||||
);
|
|
||||||
self.bitcast(ptr, stored_ptr_ty)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_call<'b>(
|
fn check_call<'b>(
|
||||||
|
@ -1468,7 +1452,6 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let ptr = self.pointercast(ptr, self.cx.type_i8p());
|
|
||||||
self.call_intrinsic(intrinsic, &[self.cx.const_u64(size), ptr]);
|
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
|
//! and methods are represented as just a fn ptr and not a full
|
||||||
//! closure.
|
//! closure.
|
||||||
|
|
||||||
use crate::abi::FnAbiLlvmExt;
|
|
||||||
use crate::attributes;
|
use crate::attributes;
|
||||||
use crate::common;
|
use crate::common;
|
||||||
use crate::context::CodegenCx;
|
use crate::context::CodegenCx;
|
||||||
use crate::llvm;
|
use crate::llvm;
|
||||||
use crate::value::Value;
|
use crate::value::Value;
|
||||||
use rustc_codegen_ssa::traits::*;
|
|
||||||
|
|
||||||
use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt};
|
use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt};
|
||||||
use rustc_middle::ty::{self, Instance, TypeVisitableExt};
|
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 fn_abi = cx.fn_abi_of_instance(instance, ty::List::empty());
|
||||||
|
|
||||||
let llfn = if let Some(llfn) = cx.get_declared_value(sym) {
|
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 {
|
} else {
|
||||||
let instance_def_id = instance.def_id();
|
let instance_def_id = instance.def_id();
|
||||||
let llfn = if tcx.sess.target.arch == "x86" &&
|
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;
|
pub use crate::context::CodegenCx;
|
||||||
use crate::llvm::{self, BasicBlock, Bool, ConstantInt, False, OperandBundleDef, True};
|
use crate::llvm::{self, BasicBlock, Bool, ConstantInt, False, OperandBundleDef, True};
|
||||||
use crate::type_::Type;
|
use crate::type_::Type;
|
||||||
use crate::type_of::LayoutLlvmExt;
|
|
||||||
use crate::value::Value;
|
use crate::value::Value;
|
||||||
|
|
||||||
use rustc_ast::Mutability;
|
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_hir::def_id::DefId;
|
||||||
use rustc_middle::bug;
|
use rustc_middle::bug;
|
||||||
use rustc_middle::mir::interpret::{ConstAllocation, GlobalAlloc, Scalar};
|
use rustc_middle::mir::interpret::{ConstAllocation, GlobalAlloc, Scalar};
|
||||||
use rustc_middle::ty::layout::LayoutOf;
|
|
||||||
use rustc_middle::ty::TyCtxt;
|
use rustc_middle::ty::TyCtxt;
|
||||||
use rustc_session::cstore::{DllCallingConvention, DllImport, PeImportNameType};
|
use rustc_session::cstore::{DllCallingConvention, DllImport, PeImportNameType};
|
||||||
use rustc_target::abi::{self, AddressSpace, HasDataLayout, Pointer};
|
use rustc_target::abi::{self, AddressSpace, HasDataLayout, Pointer};
|
||||||
|
@ -211,11 +209,7 @@ impl<'ll, 'tcx> ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> {
|
||||||
})
|
})
|
||||||
.1;
|
.1;
|
||||||
let len = s.len();
|
let len = s.len();
|
||||||
let cs = consts::ptrcast(
|
(str_global, self.const_usize(len as u64))
|
||||||
str_global,
|
|
||||||
self.type_ptr_to(self.layout_of(self.tcx.types.str_).llvm_type(self)),
|
|
||||||
);
|
|
||||||
(cs, self.const_usize(len as u64))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn const_struct(&self, elts: &[&'ll Value], packed: bool) -> &'ll Value {
|
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 {
|
let llval = unsafe {
|
||||||
llvm::LLVMConstInBoundsGEP2(
|
llvm::LLVMConstInBoundsGEP2(
|
||||||
self.type_i8(),
|
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()),
|
&self.const_usize(offset.bytes()),
|
||||||
1,
|
1,
|
||||||
)
|
)
|
||||||
|
@ -322,7 +316,7 @@ impl<'ll, 'tcx> ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> {
|
||||||
unsafe {
|
unsafe {
|
||||||
llvm::LLVMConstInBoundsGEP2(
|
llvm::LLVMConstInBoundsGEP2(
|
||||||
self.type_i8(),
|
self.type_i8(),
|
||||||
self.const_bitcast(base_addr, self.type_i8p()),
|
base_addr,
|
||||||
&self.const_usize(offset.bytes()),
|
&self.const_usize(offset.bytes()),
|
||||||
1,
|
1,
|
||||||
)
|
)
|
||||||
|
|
|
@ -103,7 +103,7 @@ pub fn const_alloc_to_llvm<'ll>(cx: &CodegenCx<'ll, '_>, alloc: ConstAllocation<
|
||||||
value: Primitive::Pointer(address_space),
|
value: Primitive::Pointer(address_space),
|
||||||
valid_range: WrappingRange::full(dl.pointer_size),
|
valid_range: WrappingRange::full(dl.pointer_size),
|
||||||
},
|
},
|
||||||
cx.type_i8p_ext(address_space),
|
cx.type_ptr_ext(address_space),
|
||||||
));
|
));
|
||||||
next_offset = offset + pointer_size;
|
next_offset = offset + pointer_size;
|
||||||
}
|
}
|
||||||
|
@ -179,7 +179,7 @@ fn check_and_apply_linkage<'ll, 'tcx>(
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
llvm::LLVMRustSetLinkage(g2, llvm::Linkage::InternalLinkage);
|
llvm::LLVMRustSetLinkage(g2, llvm::Linkage::InternalLinkage);
|
||||||
llvm::LLVMSetInitializer(g2, cx.const_ptrcast(g1, llty));
|
llvm::LLVMSetInitializer(g2, g1);
|
||||||
g2
|
g2
|
||||||
}
|
}
|
||||||
} else if cx.tcx.sess.target.arch == "x86" &&
|
} 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 g = if def_id.is_local() && !self.tcx.is_foreign_item(def_id) {
|
||||||
let llty = self.layout_of(ty).llvm_type(self);
|
let llty = self.layout_of(ty).llvm_type(self);
|
||||||
if let Some(g) = self.get_declared_value(sym) {
|
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");
|
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) {
|
fn add_used_global(&self, global: &'ll Value) {
|
||||||
let cast = unsafe { llvm::LLVMConstPointerCast(global, self.type_i8p()) };
|
self.used_statics.borrow_mut().push(global);
|
||||||
self.used_statics.borrow_mut().push(cast);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add a global value to a list to be stored in the `llvm.compiler.used` variable,
|
/// 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) {
|
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(global);
|
||||||
self.compiler_used_statics.borrow_mut().push(cast);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,17 +59,6 @@ pub struct CodegenCx<'ll, 'tcx> {
|
||||||
/// Cache of constant strings,
|
/// Cache of constant strings,
|
||||||
pub const_str_cache: RefCell<FxHashMap<String, &'ll Value>>,
|
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)
|
/// Cache of emitted const globals (value -> global)
|
||||||
pub const_globals: RefCell<FxHashMap<&'ll Value, &'ll Value>>,
|
pub const_globals: RefCell<FxHashMap<&'ll Value, &'ll Value>>,
|
||||||
|
|
||||||
|
@ -464,7 +453,6 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
|
||||||
instances: Default::default(),
|
instances: Default::default(),
|
||||||
vtables: Default::default(),
|
vtables: Default::default(),
|
||||||
const_str_cache: Default::default(),
|
const_str_cache: Default::default(),
|
||||||
const_unsized: Default::default(),
|
|
||||||
const_globals: Default::default(),
|
const_globals: Default::default(),
|
||||||
statics_to_rauw: RefCell::new(Vec::new()),
|
statics_to_rauw: RefCell::new(Vec::new()),
|
||||||
used_statics: 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]) {
|
pub(crate) fn create_used_variable_impl(&self, name: &'static CStr, values: &[&'ll Value]) {
|
||||||
let section = cstr!("llvm.metadata");
|
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 {
|
unsafe {
|
||||||
let g = llvm::LLVMAddGlobal(self.llmod, self.val_ty(array), name.as_ptr());
|
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))
|
($($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 void = self.type_void();
|
||||||
let i1 = self.type_i1();
|
let i1 = self.type_i1();
|
||||||
let t_i8 = self.type_i8();
|
let t_i8 = self.type_i8();
|
||||||
|
@ -687,7 +675,7 @@ impl<'ll> CodegenCx<'ll, '_> {
|
||||||
let t_metadata = self.type_metadata();
|
let t_metadata = self.type_metadata();
|
||||||
let t_token = self.type_token();
|
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.get.ehselector", fn(t_token) -> t_i32);
|
||||||
|
|
||||||
ifn!("llvm.wasm.trunc.unsigned.i32.f32", fn(t_f32) -> 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.trap", fn() -> void);
|
||||||
ifn!("llvm.debugtrap", 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.f32", fn(t_f32, t_i32) -> t_f32);
|
||||||
ifn!("llvm.powi.f64", fn(t_f64, t_i32) -> t_f64);
|
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.i64", fn(t_i64, t_i64) -> t_i64);
|
||||||
ifn!("llvm.usub.sat.i128", fn(t_i128, t_i128) -> t_i128);
|
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.start.p0i8", fn(t_i64, ptr) -> void);
|
||||||
ifn!("llvm.lifetime.end.p0i8", fn(t_i64, i8p) -> void);
|
ifn!("llvm.lifetime.end.p0i8", fn(t_i64, ptr) -> void);
|
||||||
|
|
||||||
ifn!("llvm.expect.i1", fn(i1, i1) -> i1);
|
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.localescape", fn(...) -> void);
|
||||||
ifn!("llvm.localrecover", fn(i8p, i8p, t_i32) -> i8p);
|
ifn!("llvm.localrecover", fn(ptr, ptr, t_i32) -> ptr);
|
||||||
ifn!("llvm.x86.seh.recoverfp", fn(i8p, i8p) -> i8p);
|
ifn!("llvm.x86.seh.recoverfp", fn(ptr, ptr) -> ptr);
|
||||||
|
|
||||||
ifn!("llvm.assume", fn(i1) -> void);
|
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
|
// This isn't an "LLVM intrinsic", but LLVM's optimization passes
|
||||||
// recognize it like one and we assume it exists in `core::slice::cmp`
|
// recognize it like one and we assume it exists in `core::slice::cmp`
|
||||||
match self.sess().target.arch.as_ref() {
|
match self.sess().target.arch.as_ref() {
|
||||||
"avr" | "msp430" => ifn!("memcmp", fn(i8p, i8p, t_isize) -> t_i16),
|
"avr" | "msp430" => ifn!("memcmp", fn(ptr, ptr, t_isize) -> t_i16),
|
||||||
_ => ifn!("memcmp", fn(i8p, i8p, t_isize) -> t_i32),
|
_ => ifn!("memcmp", fn(ptr, ptr, t_isize) -> t_i32),
|
||||||
}
|
}
|
||||||
|
|
||||||
// variadic intrinsics
|
// variadic intrinsics
|
||||||
ifn!("llvm.va_start", fn(i8p) -> void);
|
ifn!("llvm.va_start", fn(ptr) -> void);
|
||||||
ifn!("llvm.va_end", fn(i8p) -> void);
|
ifn!("llvm.va_end", fn(ptr) -> void);
|
||||||
ifn!("llvm.va_copy", fn(i8p, i8p) -> void);
|
ifn!("llvm.va_copy", fn(ptr, ptr) -> void);
|
||||||
|
|
||||||
if self.sess().instrument_coverage() {
|
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.test", fn(ptr, t_metadata) -> i1);
|
||||||
ifn!("llvm.type.checked.load", fn(i8p, t_i32, t_metadata) -> mk_struct! {i8p, i1});
|
ifn!("llvm.type.checked.load", fn(ptr, t_i32, t_metadata) -> mk_struct! {ptr, i1});
|
||||||
|
|
||||||
if self.sess().opts.debuginfo != DebugInfo::None {
|
if self.sess().opts.debuginfo != DebugInfo::None {
|
||||||
ifn!("llvm.dbg.declare", fn(t_metadata, t_metadata) -> void);
|
ifn!("llvm.dbg.declare", fn(t_metadata, t_metadata) -> void);
|
||||||
ifn!("llvm.dbg.value", fn(t_metadata, t_i64, 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
|
None
|
||||||
}
|
}
|
||||||
|
@ -940,12 +928,10 @@ impl<'ll> CodegenCx<'ll, '_> {
|
||||||
let eh_catch_typeinfo = match tcx.lang_items().eh_catch_typeinfo() {
|
let eh_catch_typeinfo = match tcx.lang_items().eh_catch_typeinfo() {
|
||||||
Some(def_id) => self.get_static(def_id),
|
Some(def_id) => self.get_static(def_id),
|
||||||
_ => {
|
_ => {
|
||||||
let ty = self
|
let ty = self.type_struct(&[self.type_ptr(), self.type_ptr()], false);
|
||||||
.type_struct(&[self.type_ptr_to(self.type_isize()), self.type_i8p()], false);
|
|
||||||
self.declare_global("rust_eh_catch_typeinfo", ty)
|
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));
|
self.eh_catch_typeinfo.set(Some(eh_catch_typeinfo));
|
||||||
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.
|
/// .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<'_, '_, '_>) {
|
pub fn insert_reference_to_gdb_debug_scripts_section_global(bx: &mut Builder<'_, '_, '_>) {
|
||||||
if needs_gdb_debug_scripts_section(bx) {
|
if needs_gdb_debug_scripts_section(bx) {
|
||||||
let gdb_debug_scripts_section =
|
let gdb_debug_scripts_section = get_or_insert_gdb_debug_scripts_section_global(bx);
|
||||||
bx.const_bitcast(get_or_insert_gdb_debug_scripts_section_global(bx), bx.type_i8p());
|
|
||||||
// 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 volatile_load_instruction = bx.volatile_load(bx.type_i8(), gdb_debug_scripts_section);
|
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 ptr = args[0].immediate();
|
||||||
let load = if let PassMode::Cast(ty, _) = &fn_abi.ret.mode {
|
let load = if let PassMode::Cast(ty, _) = &fn_abi.ret.mode {
|
||||||
let llty = ty.llvm_type(self);
|
let llty = ty.llvm_type(self);
|
||||||
let ptr = self.pointercast(ptr, self.type_ptr_to(llty));
|
|
||||||
self.volatile_load(llty, ptr)
|
self.volatile_load(llty, ptr)
|
||||||
} else {
|
} else {
|
||||||
self.volatile_load(self.layout_of(tp_ty).llvm_type(self), ptr)
|
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)
|
self.const_bool(true)
|
||||||
} else if use_integer_compare {
|
} else if use_integer_compare {
|
||||||
let integer_ty = self.type_ix(layout.size().bits());
|
let integer_ty = self.type_ix(layout.size().bits());
|
||||||
let ptr_ty = self.type_ptr_to(integer_ty);
|
let a_val = self.load(integer_ty, a, layout.align().abi);
|
||||||
let a_ptr = self.bitcast(a, ptr_ty);
|
let b_val = self.load(integer_ty, b, layout.align().abi);
|
||||||
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);
|
|
||||||
self.icmp(IntPredicate::IntEQ, a_val, b_val)
|
self.icmp(IntPredicate::IntEQ, a_val, b_val)
|
||||||
} else {
|
} 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 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() {
|
match self.cx.sess().target.arch.as_ref() {
|
||||||
"avr" | "msp430" => self.icmp(IntPredicate::IntEQ, cmp, self.const_i16(0)),
|
"avr" | "msp430" => self.icmp(IntPredicate::IntEQ, cmp, self.const_i16(0)),
|
||||||
_ => self.icmp(IntPredicate::IntEQ, cmp, self.const_i32(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 !fn_abi.ret.is_ignore() {
|
||||||
if let PassMode::Cast(ty, _) = &fn_abi.ret.mode {
|
if let PassMode::Cast(_, _) = &fn_abi.ret.mode {
|
||||||
let ptr_llty = self.type_ptr_to(ty.llvm_type(self));
|
self.store(llval, result.llval, result.align);
|
||||||
let ptr = self.pointercast(result.llval, ptr_llty);
|
|
||||||
self.store(llval, ptr, result.align);
|
|
||||||
} else {
|
} else {
|
||||||
OperandRef::from_immediate_or_packed_pair(self, llval, result.layout)
|
OperandRef::from_immediate_or_packed_pair(self, llval, result.layout)
|
||||||
.val
|
.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 {
|
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
|
// 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.
|
// optimization pass replaces calls to this intrinsic with code to test type membership.
|
||||||
let i8p_ty = self.type_i8p();
|
self.call_intrinsic("llvm.type.test", &[pointer, typeid])
|
||||||
let bitcast = self.bitcast(pointer, i8p_ty);
|
|
||||||
self.call_intrinsic("llvm.type.test", &[bitcast, typeid])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn type_checked_load(
|
fn type_checked_load(
|
||||||
|
@ -444,7 +433,7 @@ fn try_intrinsic<'ll>(
|
||||||
dest: &'ll Value,
|
dest: &'ll Value,
|
||||||
) {
|
) {
|
||||||
if bx.sess().panic_strategy() == PanicStrategy::Abort {
|
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);
|
bx.call(try_func_ty, None, None, try_func, &[data], None);
|
||||||
// Return 0 unconditionally from the intrinsic call;
|
// Return 0 unconditionally from the intrinsic call;
|
||||||
// we can never unwind.
|
// we can never unwind.
|
||||||
|
@ -544,8 +533,8 @@ fn codegen_msvc_try<'ll>(
|
||||||
//
|
//
|
||||||
// More information can be found in libstd's seh.rs implementation.
|
// More information can be found in libstd's seh.rs implementation.
|
||||||
let ptr_align = bx.tcx().data_layout.pointer_align.abi;
|
let ptr_align = bx.tcx().data_layout.pointer_align.abi;
|
||||||
let slot = bx.alloca(bx.type_i8p(), ptr_align);
|
let slot = bx.alloca(bx.type_ptr(), ptr_align);
|
||||||
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.invoke(try_func_ty, None, None, try_func, &[data], normal, catchswitch, None);
|
||||||
|
|
||||||
bx.switch_to_block(normal);
|
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
|
// When modifying, make sure that the type_name string exactly matches
|
||||||
// the one used in library/panic_unwind/src/seh.rs.
|
// 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_name = bx.const_bytes(b"rust_panic\0");
|
||||||
let type_info =
|
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));
|
let tydesc = bx.declare_global("__rust_panic_type_info", bx.val_ty(type_info));
|
||||||
unsafe {
|
unsafe {
|
||||||
llvm::LLVMRustSetLinkage(tydesc, llvm::Linkage::LinkOnceODRLinkage);
|
llvm::LLVMRustSetLinkage(tydesc, llvm::Linkage::LinkOnceODRLinkage);
|
||||||
|
@ -588,15 +577,15 @@ fn codegen_msvc_try<'ll>(
|
||||||
bx.switch_to_block(catchpad_rust);
|
bx.switch_to_block(catchpad_rust);
|
||||||
let flags = bx.const_i32(8);
|
let flags = bx.const_i32(8);
|
||||||
let funclet = bx.catch_pad(cs, &[tydesc, flags, slot]);
|
let funclet = bx.catch_pad(cs, &[tydesc, flags, slot]);
|
||||||
let ptr = bx.load(bx.type_i8p(), slot, ptr_align);
|
let ptr = bx.load(bx.type_ptr(), slot, ptr_align);
|
||||||
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.call(catch_ty, None, None, catch_func, &[data, ptr], Some(&funclet));
|
||||||
bx.catch_ret(&funclet, caught);
|
bx.catch_ret(&funclet, caught);
|
||||||
|
|
||||||
// The flag value of 64 indicates a "catch-all".
|
// The flag value of 64 indicates a "catch-all".
|
||||||
bx.switch_to_block(catchpad_foreign);
|
bx.switch_to_block(catchpad_foreign);
|
||||||
let flags = bx.const_i32(64);
|
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]);
|
let funclet = bx.catch_pad(cs, &[null, flags, null]);
|
||||||
bx.call(catch_ty, None, None, catch_func, &[data, null], Some(&funclet));
|
bx.call(catch_ty, None, None, catch_func, &[data, null], Some(&funclet));
|
||||||
bx.catch_ret(&funclet, caught);
|
bx.catch_ret(&funclet, caught);
|
||||||
|
@ -655,7 +644,7 @@ fn codegen_wasm_try<'ll>(
|
||||||
// ret i32 1
|
// 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.invoke(try_func_ty, None, None, try_func, &[data], normal, catchswitch, None);
|
||||||
|
|
||||||
bx.switch_to_block(normal);
|
bx.switch_to_block(normal);
|
||||||
|
@ -665,13 +654,13 @@ fn codegen_wasm_try<'ll>(
|
||||||
let cs = bx.catch_switch(None, None, &[catchpad]);
|
let cs = bx.catch_switch(None, None, &[catchpad]);
|
||||||
|
|
||||||
bx.switch_to_block(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 funclet = bx.catch_pad(cs, &[null]);
|
||||||
|
|
||||||
let ptr = bx.call_intrinsic("llvm.wasm.get.exception", &[funclet.cleanuppad()]);
|
let ptr = bx.call_intrinsic("llvm.wasm.get.exception", &[funclet.cleanuppad()]);
|
||||||
let _sel = bx.call_intrinsic("llvm.wasm.get.ehselector", &[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.call(catch_ty, None, None, catch_func, &[data, ptr], Some(&funclet));
|
||||||
bx.catch_ret(&funclet, caught);
|
bx.catch_ret(&funclet, caught);
|
||||||
|
|
||||||
|
@ -723,7 +712,7 @@ fn codegen_gnu_try<'ll>(
|
||||||
let try_func = llvm::get_param(bx.llfn(), 0);
|
let try_func = llvm::get_param(bx.llfn(), 0);
|
||||||
let data = llvm::get_param(bx.llfn(), 1);
|
let data = llvm::get_param(bx.llfn(), 1);
|
||||||
let catch_func = llvm::get_param(bx.llfn(), 2);
|
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.invoke(try_func_ty, None, None, try_func, &[data], then, catch, None);
|
||||||
|
|
||||||
bx.switch_to_block(then);
|
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.
|
// the landing pad clauses the exception's type had been matched to.
|
||||||
// rust_try ignores the selector.
|
// rust_try ignores the selector.
|
||||||
bx.switch_to_block(catch);
|
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 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);
|
bx.add_clause(vals, tydesc);
|
||||||
let ptr = bx.extract_value(vals, 0);
|
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.call(catch_ty, None, None, catch_func, &[data, ptr], None);
|
||||||
bx.ret(bx.const_i32(1));
|
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 try_func = llvm::get_param(bx.llfn(), 0);
|
||||||
let data = llvm::get_param(bx.llfn(), 1);
|
let data = llvm::get_param(bx.llfn(), 1);
|
||||||
let catch_func = llvm::get_param(bx.llfn(), 2);
|
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.invoke(try_func_ty, None, None, try_func, &[data], then, catch, None);
|
||||||
|
|
||||||
bx.switch_to_block(then);
|
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.
|
// the landing pad clauses the exception's type had been matched to.
|
||||||
bx.switch_to_block(catch);
|
bx.switch_to_block(catch);
|
||||||
let tydesc = bx.eh_catch_typeinfo();
|
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);
|
let vals = bx.landing_pad(lpad_ty, bx.eh_personality(), 2);
|
||||||
bx.add_clause(vals, tydesc);
|
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 ptr = bx.extract_value(vals, 0);
|
||||||
let selector = bx.extract_value(vals, 1);
|
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.
|
// create an alloca and pass a pointer to that.
|
||||||
let ptr_align = bx.tcx().data_layout.pointer_align.abi;
|
let ptr_align = bx.tcx().data_layout.pointer_align.abi;
|
||||||
let i8_align = bx.tcx().data_layout.i8_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 = bx.alloca(catch_data_type, ptr_align);
|
||||||
let catch_data_0 =
|
let catch_data_0 =
|
||||||
bx.inbounds_gep(catch_data_type, catch_data, &[bx.const_usize(0), bx.const_usize(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 =
|
let catch_data_1 =
|
||||||
bx.inbounds_gep(catch_data_type, catch_data, &[bx.const_usize(0), bx.const_usize(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);
|
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.call(catch_ty, None, None, catch_func, &[data, catch_data], None);
|
||||||
bx.ret(bx.const_i32(1));
|
bx.ret(bx.const_i32(1));
|
||||||
});
|
});
|
||||||
|
@ -967,8 +955,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
||||||
let place = PlaceRef::alloca(bx, args[0].layout);
|
let place = PlaceRef::alloca(bx, args[0].layout);
|
||||||
args[0].val.store(bx, place);
|
args[0].val.store(bx, place);
|
||||||
let int_ty = bx.type_ix(expected_bytes * 8);
|
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, place.llval, Align::ONE)
|
||||||
bx.load(int_ty, ptr, Align::ONE)
|
|
||||||
}
|
}
|
||||||
_ => return_error!(InvalidMonomorphization::InvalidBitmask {
|
_ => return_error!(InvalidMonomorphization::InvalidBitmask {
|
||||||
span,
|
span,
|
||||||
|
@ -1217,7 +1204,6 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
||||||
let ptr = bx.alloca(bx.type_ix(expected_bytes * 8), Align::ONE);
|
let ptr = bx.alloca(bx.type_ix(expected_bytes * 8), Align::ONE);
|
||||||
bx.store(ze, ptr, Align::ONE);
|
bx.store(ze, ptr, Align::ONE);
|
||||||
let array_ty = bx.type_array(bx.type_i8(), expected_bytes);
|
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 Ok(bx.load(array_ty, ptr, Align::ONE));
|
||||||
}
|
}
|
||||||
_ => return_error!(InvalidMonomorphization::CannotReturn {
|
_ => return_error!(InvalidMonomorphization::CannotReturn {
|
||||||
|
@ -1352,7 +1338,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
||||||
cx: &CodegenCx<'ll, '_>,
|
cx: &CodegenCx<'ll, '_>,
|
||||||
elem_ty: Ty<'_>,
|
elem_ty: Ty<'_>,
|
||||||
vec_len: u64,
|
vec_len: u64,
|
||||||
mut no_pointers: usize,
|
no_pointers: usize,
|
||||||
) -> &'ll Type {
|
) -> &'ll Type {
|
||||||
// FIXME: use cx.layout_of(ty).llvm_type() ?
|
// FIXME: use cx.layout_of(ty).llvm_type() ?
|
||||||
let mut elem_ty = match *elem_ty.kind() {
|
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),
|
ty::Float(v) => cx.type_float_from_ty(v),
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
while no_pointers > 0 {
|
if no_pointers > 0 {
|
||||||
elem_ty = cx.type_ptr_to(elem_ty);
|
elem_ty = cx.type_ptr();
|
||||||
no_pointers -= 1;
|
|
||||||
}
|
}
|
||||||
cx.type_vector(elem_ty, vec_len)
|
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());
|
return Ok(args[0].immediate());
|
||||||
} else {
|
|
||||||
return Ok(bx.pointercast(args[0].immediate(), llret_ty));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if name == sym::simd_expose_addr {
|
if name == sym::simd_expose_addr {
|
||||||
|
|
|
@ -1073,7 +1073,7 @@ extern "C" {
|
||||||
|
|
||||||
// Operations on array, pointer, and vector types (sequence types)
|
// Operations on array, pointer, and vector types (sequence types)
|
||||||
pub fn LLVMRustArrayType(ElementType: &Type, ElementCount: u64) -> &Type;
|
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 LLVMVectorType(ElementType: &Type, ElementCount: c_uint) -> &Type;
|
||||||
|
|
||||||
pub fn LLVMGetElementType(Ty: &Type) -> &Type;
|
pub fn LLVMGetElementType(Ty: &Type) -> &Type;
|
||||||
|
|
|
@ -69,6 +69,14 @@ impl<'ll> CodegenCx<'ll, '_> {
|
||||||
unsafe { llvm::LLVMVectorType(ty, len as c_uint) }
|
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> {
|
pub(crate) fn func_params_types(&self, ty: &'ll Type) -> Vec<&'ll Type> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let n_args = llvm::LLVMCountParamTypes(ty) as usize;
|
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,
|
/// Return a LLVM type that has at most the required alignment,
|
||||||
/// and exactly the required size, as a best-effort padding array.
|
/// and exactly the required size, as a best-effort padding array.
|
||||||
pub(crate) fn type_padding_filler(&self, size: Size, align: Align) -> &'ll Type {
|
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() }
|
unsafe { llvm::LLVMRustGetTypeKind(ty).to_generic() }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn type_ptr_to(&self, ty: &'ll Type) -> &'ll Type {
|
fn type_ptr_to(&self, _ty: &'ll Type) -> &'ll Type {
|
||||||
assert_ne!(
|
self.type_ptr()
|
||||||
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_ext(&self, ty: &'ll Type, address_space: AddressSpace) -> &'ll Type {
|
fn type_ptr_to_ext(&self, _ty: &'ll Type, address_space: AddressSpace) -> &'ll Type {
|
||||||
ty.ptr_to(address_space)
|
self.type_ptr_ext(address_space)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn element_type(&self, ty: &'ll Type) -> &'ll Type {
|
fn element_type(&self, ty: &'ll Type) -> &'ll Type {
|
||||||
|
@ -247,12 +244,8 @@ impl Type {
|
||||||
unsafe { llvm::LLVMIntTypeInContext(llcx, num_bits as c_uint) }
|
unsafe { llvm::LLVMIntTypeInContext(llcx, num_bits as c_uint) }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn i8p_llcx(llcx: &llvm::Context) -> &Type {
|
pub fn ptr_llcx(llcx: &llvm::Context) -> &Type {
|
||||||
Type::i8_llcx(llcx).ptr_to(AddressSpace::DATA)
|
unsafe { llvm::LLVMPointerTypeInContext(llcx, AddressSpace::DATA.0) }
|
||||||
}
|
|
||||||
|
|
||||||
fn ptr_to(&self, address_space: AddressSpace) -> &Type {
|
|
||||||
unsafe { llvm::LLVMPointerType(self, address_space.0) }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,7 @@ fn uncached_llvm_type<'a, 'tcx>(
|
||||||
match layout.abi {
|
match layout.abi {
|
||||||
Abi::Scalar(_) => bug!("handled elsewhere"),
|
Abi::Scalar(_) => bug!("handled elsewhere"),
|
||||||
Abi::Vector { element, count } => {
|
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);
|
return cx.type_vector(element, count);
|
||||||
}
|
}
|
||||||
Abi::ScalarPair(..) => {
|
Abi::ScalarPair(..) => {
|
||||||
|
@ -179,12 +179,7 @@ pub trait LayoutLlvmExt<'tcx> {
|
||||||
fn is_llvm_scalar_pair(&self) -> bool;
|
fn is_llvm_scalar_pair(&self) -> bool;
|
||||||
fn llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> &'a Type;
|
fn llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> &'a Type;
|
||||||
fn immediate_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>(
|
fn scalar_llvm_type_at<'a>(&self, cx: &CodegenCx<'a, 'tcx>, scalar: Scalar) -> &'a Type;
|
||||||
&self,
|
|
||||||
cx: &CodegenCx<'a, 'tcx>,
|
|
||||||
scalar: Scalar,
|
|
||||||
offset: Size,
|
|
||||||
) -> &'a Type;
|
|
||||||
fn scalar_pair_element_llvm_type<'a>(
|
fn scalar_pair_element_llvm_type<'a>(
|
||||||
&self,
|
&self,
|
||||||
cx: &CodegenCx<'a, 'tcx>,
|
cx: &CodegenCx<'a, 'tcx>,
|
||||||
|
@ -230,16 +225,12 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> {
|
||||||
return llty;
|
return llty;
|
||||||
}
|
}
|
||||||
let llty = match *self.ty.kind() {
|
let llty = match *self.ty.kind() {
|
||||||
ty::Ref(_, ty, _) | ty::RawPtr(ty::TypeAndMut { ty, .. }) => {
|
ty::Ref(..) | ty::RawPtr(ty::TypeAndMut { .. }) => cx.type_ptr(),
|
||||||
cx.type_ptr_to(cx.layout_of(ty).llvm_type(cx))
|
ty::Adt(def, _) if def.is_box() => cx.type_ptr(),
|
||||||
}
|
|
||||||
ty::Adt(def, _) if def.is_box() => {
|
|
||||||
cx.type_ptr_to(cx.layout_of(self.ty.boxed_ty()).llvm_type(cx))
|
|
||||||
}
|
|
||||||
ty::FnPtr(sig) => {
|
ty::FnPtr(sig) => {
|
||||||
cx.fn_ptr_backend_type(cx.fn_abi_of_fn_ptr(sig, ty::List::empty()))
|
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);
|
cx.scalar_lltypes.borrow_mut().insert(self.ty, llty);
|
||||||
return llty;
|
return llty;
|
||||||
|
@ -300,25 +291,12 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> {
|
||||||
self.llvm_type(cx)
|
self.llvm_type(cx)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn scalar_llvm_type_at<'a>(
|
fn scalar_llvm_type_at<'a>(&self, cx: &CodegenCx<'a, 'tcx>, scalar: Scalar) -> &'a Type {
|
||||||
&self,
|
|
||||||
cx: &CodegenCx<'a, 'tcx>,
|
|
||||||
scalar: Scalar,
|
|
||||||
offset: Size,
|
|
||||||
) -> &'a Type {
|
|
||||||
match scalar.primitive() {
|
match scalar.primitive() {
|
||||||
Int(i, _) => cx.type_from_integer(i),
|
Int(i, _) => cx.type_from_integer(i),
|
||||||
F32 => cx.type_f32(),
|
F32 => cx.type_f32(),
|
||||||
F64 => cx.type_f64(),
|
F64 => cx.type_f64(),
|
||||||
Pointer(address_space) => {
|
Pointer(address_space) => cx.type_ptr_ext(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)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -364,8 +342,7 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> {
|
||||||
return cx.type_i1();
|
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)
|
||||||
self.scalar_llvm_type_at(cx, scalar, offset)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn llvm_field_index<'a>(&self, cx: &CodegenCx<'a, 'tcx>, index: usize) -> u64 {
|
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::mir::operand::OperandRef;
|
||||||
use rustc_codegen_ssa::{
|
use rustc_codegen_ssa::{
|
||||||
common::IntPredicate,
|
common::IntPredicate,
|
||||||
traits::{BaseTypeMethods, BuilderMethods, ConstMethods, DerivedTypeMethods},
|
traits::{BaseTypeMethods, BuilderMethods, ConstMethods},
|
||||||
};
|
};
|
||||||
use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf};
|
use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf};
|
||||||
use rustc_middle::ty::Ty;
|
use rustc_middle::ty::Ty;
|
||||||
|
@ -26,24 +26,18 @@ fn round_pointer_up_to_alignment<'ll>(
|
||||||
fn emit_direct_ptr_va_arg<'ll, 'tcx>(
|
fn emit_direct_ptr_va_arg<'ll, 'tcx>(
|
||||||
bx: &mut Builder<'_, 'll, 'tcx>,
|
bx: &mut Builder<'_, 'll, 'tcx>,
|
||||||
list: OperandRef<'tcx, &'ll Value>,
|
list: OperandRef<'tcx, &'ll Value>,
|
||||||
llty: &'ll Type,
|
|
||||||
size: Size,
|
size: Size,
|
||||||
align: Align,
|
align: Align,
|
||||||
slot_size: Align,
|
slot_size: Align,
|
||||||
allow_higher_align: bool,
|
allow_higher_align: bool,
|
||||||
) -> (&'ll Value, Align) {
|
) -> (&'ll Value, Align) {
|
||||||
let va_list_ty = bx.type_i8p();
|
let va_list_ty = bx.type_ptr();
|
||||||
let va_list_ptr_ty = bx.type_ptr_to(va_list_ty);
|
let va_list_addr = list.immediate();
|
||||||
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 ptr = bx.load(va_list_ty, va_list_addr, bx.tcx().data_layout.pointer_align.abi);
|
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 {
|
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 {
|
} else {
|
||||||
(ptr, slot_size)
|
(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 {
|
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_size = bx.cx().const_i32((slot_size.bytes() - size.bytes()) as i32);
|
||||||
let adjusted = bx.inbounds_gep(bx.type_i8(), addr, &[adjusted_size]);
|
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 {
|
} 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)
|
(layout.llvm_type(bx.cx), layout.size, layout.align)
|
||||||
};
|
};
|
||||||
let (addr, addr_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 {
|
if indirect {
|
||||||
let tmp_ret = bx.load(llty, addr, addr_align);
|
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)
|
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.cond_br(use_stack, on_stack, in_reg);
|
||||||
|
|
||||||
bx.switch_to_block(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.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);
|
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]);
|
reg_addr = bx.gep(bx.type_i8(), reg_addr, &[offset]);
|
||||||
}
|
}
|
||||||
let reg_type = layout.llvm_type(bx);
|
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);
|
let reg_value = bx.load(reg_type, reg_addr, layout.align.abi);
|
||||||
bx.br(end);
|
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.
|
// Work out the address of the value in the register save area.
|
||||||
let reg_ptr =
|
let reg_ptr =
|
||||||
bx.struct_gep(va_list_ty, va_list_addr, va_list_layout.llvm_field_index(bx.cx, 3));
|
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 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_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]);
|
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.
|
// Work out the address of the value in the argument overflow area.
|
||||||
let arg_ptr =
|
let arg_ptr =
|
||||||
bx.struct_gep(va_list_ty, va_list_addr, va_list_layout.llvm_field_index(bx.cx, 2));
|
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 arg_off = bx.const_u64(padding);
|
||||||
let mem_addr = bx.gep(bx.type_i8(), arg_ptr_v, &[arg_off]);
|
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.
|
// Return the appropriate result.
|
||||||
bx.switch_to_block(end);
|
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_type = layout.llvm_type(bx);
|
||||||
let val_addr = if indirect {
|
let val_addr = if indirect {
|
||||||
let ptr_type = bx.cx.type_ptr_to(val_type);
|
bx.load(bx.cx.type_ptr(), val_addr, bx.tcx().data_layout.pointer_align.abi)
|
||||||
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)
|
|
||||||
} else {
|
} else {
|
||||||
bx.bitcast(val_addr, bx.cx.type_ptr_to(val_type))
|
val_addr
|
||||||
};
|
};
|
||||||
bx.load(val_type, val_addr, layout.align.abi)
|
bx.load(val_type, val_addr, layout.align.abi)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,23 +0,0 @@
|
||||||
// run-pass
|
|
||||||
// compile-flags: -Copt-level=0 -Cllvm-args=-opaque-pointers=0
|
|
||||||
|
|
||||||
// (the ability to disable opaque pointers has been removed in LLVM 17)
|
|
||||||
// ignore-llvm-version: 17 - 99
|
|
||||||
|
|
||||||
// This test can be removed once non-opaque pointers are gone from LLVM, maybe.
|
|
||||||
|
|
||||||
#![feature(dyn_star, pointer_like_trait)]
|
|
||||||
#![allow(incomplete_features)]
|
|
||||||
|
|
||||||
use std::fmt::Debug;
|
|
||||||
use std::marker::PointerLike;
|
|
||||||
|
|
||||||
fn make_dyn_star<'a>(t: impl PointerLike + Debug + 'a) -> dyn* Debug + 'a {
|
|
||||||
t as _
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
println!("{:?}", make_dyn_star(Box::new(1i32)));
|
|
||||||
println!("{:?}", make_dyn_star(2usize));
|
|
||||||
println!("{:?}", make_dyn_star((3usize,)));
|
|
||||||
}
|
|
|
@ -1,4 +1,5 @@
|
||||||
error: values of the type `[&usize; usize::MAX]` are too big for the current architecture
|
error: values of the type `[&usize; usize::MAX]` are too big for the current architecture
|
||||||
|
--> $SRC_DIR/alloc/src/boxed.rs:LL:COL
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue