Prepare inbounds_gep for opaque pointers
Implement inbounds_gep using LLVMBuildInBoundsGEP2 which takes an explicit type argument instead of deriving it from a pointer type.
This commit is contained in:
parent
4013e094f5
commit
77e5e17231
11 changed files with 61 additions and 22 deletions
|
@ -544,7 +544,11 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
|
||||||
.val
|
.val
|
||||||
.store(&mut body_bx, PlaceRef::new_sized_aligned(current, cg_elem.layout, align));
|
.store(&mut body_bx, PlaceRef::new_sized_aligned(current, cg_elem.layout, align));
|
||||||
|
|
||||||
let next = body_bx.inbounds_gep(current, &[self.const_usize(1)]);
|
let next = body_bx.inbounds_gep(
|
||||||
|
self.backend_type(cg_elem.layout),
|
||||||
|
current,
|
||||||
|
&[self.const_usize(1)],
|
||||||
|
);
|
||||||
body_bx.br(header_bx.llbb());
|
body_bx.br(header_bx.llbb());
|
||||||
header_bx.add_incoming_to_phi(current, next, body_bx.llbb());
|
header_bx.add_incoming_to_phi(current, next, body_bx.llbb());
|
||||||
|
|
||||||
|
@ -653,10 +657,16 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn inbounds_gep(&mut self, ptr: &'ll Value, indices: &[&'ll Value]) -> &'ll Value {
|
fn inbounds_gep(
|
||||||
|
&mut self,
|
||||||
|
ty: &'ll Type,
|
||||||
|
ptr: &'ll Value,
|
||||||
|
indices: &[&'ll Value],
|
||||||
|
) -> &'ll Value {
|
||||||
unsafe {
|
unsafe {
|
||||||
llvm::LLVMBuildInBoundsGEP(
|
llvm::LLVMBuildInBoundsGEP2(
|
||||||
self.llbuilder,
|
self.llbuilder,
|
||||||
|
ty,
|
||||||
ptr,
|
ptr,
|
||||||
indices.as_ptr(),
|
indices.as_ptr(),
|
||||||
indices.len() as c_uint,
|
indices.len() as c_uint,
|
||||||
|
|
|
@ -15,12 +15,11 @@ 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 = get_or_insert_gdb_debug_scripts_section_global(bx);
|
let gdb_debug_scripts_section =
|
||||||
|
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 indices = [bx.const_i32(0), bx.const_i32(0)];
|
let volative_load_instruction = bx.volatile_load(bx.type_i8(), gdb_debug_scripts_section);
|
||||||
let element = bx.inbounds_gep(gdb_debug_scripts_section, &indices);
|
|
||||||
let volative_load_instruction = bx.volatile_load(bx.type_i8(), element);
|
|
||||||
unsafe {
|
unsafe {
|
||||||
llvm::LLVMSetAlignment(volative_load_instruction, 1);
|
llvm::LLVMSetAlignment(volative_load_instruction, 1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -686,11 +686,19 @@ fn codegen_emcc_try(
|
||||||
// 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 =
|
let catch_data_type = bx.type_struct(&[bx.type_i8p(), bx.type_bool()], false);
|
||||||
catch.alloca(bx.type_struct(&[bx.type_i8p(), bx.type_bool()], false), ptr_align);
|
let catch_data = catch.alloca(catch_data_type, ptr_align);
|
||||||
let catch_data_0 = catch.inbounds_gep(catch_data, &[bx.const_usize(0), bx.const_usize(0)]);
|
let catch_data_0 = catch.inbounds_gep(
|
||||||
|
catch_data_type,
|
||||||
|
catch_data,
|
||||||
|
&[bx.const_usize(0), bx.const_usize(0)],
|
||||||
|
);
|
||||||
catch.store(ptr, catch_data_0, ptr_align);
|
catch.store(ptr, catch_data_0, ptr_align);
|
||||||
let catch_data_1 = catch.inbounds_gep(catch_data, &[bx.const_usize(0), bx.const_usize(1)]);
|
let catch_data_1 = catch.inbounds_gep(
|
||||||
|
catch_data_type,
|
||||||
|
catch_data,
|
||||||
|
&[bx.const_usize(0), bx.const_usize(1)],
|
||||||
|
);
|
||||||
catch.store(is_rust_panic, catch_data_1, i8_align);
|
catch.store(is_rust_panic, catch_data_1, i8_align);
|
||||||
let catch_data = catch.bitcast(catch_data, bx.type_i8p());
|
let catch_data = catch.bitcast(catch_data, bx.type_i8p());
|
||||||
|
|
||||||
|
|
|
@ -1402,8 +1402,9 @@ extern "C" {
|
||||||
NumIndices: c_uint,
|
NumIndices: c_uint,
|
||||||
Name: *const c_char,
|
Name: *const c_char,
|
||||||
) -> &'a Value;
|
) -> &'a Value;
|
||||||
pub fn LLVMBuildInBoundsGEP(
|
pub fn LLVMBuildInBoundsGEP2(
|
||||||
B: &Builder<'a>,
|
B: &Builder<'a>,
|
||||||
|
Ty: &'a Type,
|
||||||
Pointer: &'a Value,
|
Pointer: &'a Value,
|
||||||
Indices: *const &'a Value,
|
Indices: *const &'a Value,
|
||||||
NumIndices: c_uint,
|
NumIndices: c_uint,
|
||||||
|
|
|
@ -50,12 +50,12 @@ fn emit_direct_ptr_va_arg(
|
||||||
|
|
||||||
let aligned_size = size.align_to(slot_size).bytes() as i32;
|
let aligned_size = size.align_to(slot_size).bytes() as i32;
|
||||||
let full_direct_size = bx.cx().const_i32(aligned_size);
|
let full_direct_size = bx.cx().const_i32(aligned_size);
|
||||||
let next = bx.inbounds_gep(addr, &[full_direct_size]);
|
let next = bx.inbounds_gep(bx.type_i8(), addr, &[full_direct_size]);
|
||||||
bx.store(next, va_list_addr, bx.tcx().data_layout.pointer_align.abi);
|
bx.store(next, va_list_addr, bx.tcx().data_layout.pointer_align.abi);
|
||||||
|
|
||||||
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(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)
|
(bx.bitcast(adjusted, bx.cx().type_ptr_to(llty)), addr_align)
|
||||||
} else {
|
} else {
|
||||||
(bx.bitcast(addr, bx.cx().type_ptr_to(llty)), addr_align)
|
(bx.bitcast(addr, bx.cx().type_ptr_to(llty)), addr_align)
|
||||||
|
|
|
@ -168,8 +168,11 @@ pub fn unsized_info<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
||||||
let ptr_ty = cx.type_i8p();
|
let ptr_ty = cx.type_i8p();
|
||||||
let ptr_align = cx.tcx().data_layout.pointer_align.abi;
|
let ptr_align = cx.tcx().data_layout.pointer_align.abi;
|
||||||
let llvtable = bx.pointercast(old_info, bx.type_ptr_to(ptr_ty));
|
let llvtable = bx.pointercast(old_info, bx.type_ptr_to(ptr_ty));
|
||||||
let gep =
|
let gep = bx.inbounds_gep(
|
||||||
bx.inbounds_gep(llvtable, &[bx.const_usize(u64::try_from(entry_idx).unwrap())]);
|
ptr_ty,
|
||||||
|
llvtable,
|
||||||
|
&[bx.const_usize(u64::try_from(entry_idx).unwrap())],
|
||||||
|
);
|
||||||
let new_vptr = bx.load(ptr_ty, gep, ptr_align);
|
let new_vptr = bx.load(ptr_ty, gep, ptr_align);
|
||||||
bx.nonnull_metadata(new_vptr);
|
bx.nonnull_metadata(new_vptr);
|
||||||
// Vtable loads are invariant.
|
// Vtable loads are invariant.
|
||||||
|
|
|
@ -23,7 +23,7 @@ impl<'a, 'tcx> VirtualIndex {
|
||||||
let llty = bx.fn_ptr_backend_type(fn_abi);
|
let llty = bx.fn_ptr_backend_type(fn_abi);
|
||||||
let llvtable = bx.pointercast(llvtable, bx.type_ptr_to(llty));
|
let llvtable = bx.pointercast(llvtable, bx.type_ptr_to(llty));
|
||||||
let ptr_align = bx.tcx().data_layout.pointer_align.abi;
|
let ptr_align = bx.tcx().data_layout.pointer_align.abi;
|
||||||
let gep = bx.inbounds_gep(llvtable, &[bx.const_usize(self.0)]);
|
let gep = bx.inbounds_gep(llty, llvtable, &[bx.const_usize(self.0)]);
|
||||||
let ptr = bx.load(llty, gep, ptr_align);
|
let ptr = bx.load(llty, gep, ptr_align);
|
||||||
bx.nonnull_metadata(ptr);
|
bx.nonnull_metadata(ptr);
|
||||||
// Vtable loads are invariant.
|
// Vtable loads are invariant.
|
||||||
|
@ -42,7 +42,7 @@ impl<'a, 'tcx> VirtualIndex {
|
||||||
let llty = bx.type_isize();
|
let llty = bx.type_isize();
|
||||||
let llvtable = bx.pointercast(llvtable, bx.type_ptr_to(llty));
|
let llvtable = bx.pointercast(llvtable, bx.type_ptr_to(llty));
|
||||||
let usize_align = bx.tcx().data_layout.pointer_align.abi;
|
let usize_align = bx.tcx().data_layout.pointer_align.abi;
|
||||||
let gep = bx.inbounds_gep(llvtable, &[bx.const_usize(self.0)]);
|
let gep = bx.inbounds_gep(llty, llvtable, &[bx.const_usize(self.0)]);
|
||||||
let ptr = bx.load(llty, gep, usize_align);
|
let ptr = bx.load(llty, gep, usize_align);
|
||||||
// Vtable loads are invariant.
|
// Vtable loads are invariant.
|
||||||
bx.set_invariant_load(ptr);
|
bx.set_invariant_load(ptr);
|
||||||
|
|
|
@ -116,9 +116,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||||
OperandRef::from_const(bx, value, ret_ty).immediate_or_packed_pair(bx)
|
OperandRef::from_const(bx, value, ret_ty).immediate_or_packed_pair(bx)
|
||||||
}
|
}
|
||||||
sym::offset => {
|
sym::offset => {
|
||||||
|
let ty = substs.type_at(0);
|
||||||
|
let layout = bx.layout_of(ty);
|
||||||
let ptr = args[0].immediate();
|
let ptr = args[0].immediate();
|
||||||
let offset = args[1].immediate();
|
let offset = args[1].immediate();
|
||||||
bx.inbounds_gep(ptr, &[offset])
|
bx.inbounds_gep(bx.backend_type(layout), ptr, &[offset])
|
||||||
}
|
}
|
||||||
sym::arith_offset => {
|
sym::arith_offset => {
|
||||||
let ty = substs.type_at(0);
|
let ty = substs.type_at(0);
|
||||||
|
|
|
@ -384,7 +384,11 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
|
||||||
};
|
};
|
||||||
|
|
||||||
PlaceRef {
|
PlaceRef {
|
||||||
llval: bx.inbounds_gep(self.llval, &[bx.cx().const_usize(0), llindex]),
|
llval: bx.inbounds_gep(
|
||||||
|
bx.cx().backend_type(self.layout),
|
||||||
|
self.llval,
|
||||||
|
&[bx.cx().const_usize(0), llindex],
|
||||||
|
),
|
||||||
llextra: None,
|
llextra: None,
|
||||||
layout,
|
layout,
|
||||||
align: self.align.restrict_for_offset(offset),
|
align: self.align.restrict_for_offset(offset),
|
||||||
|
|
|
@ -636,7 +636,14 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||||
mir::BinOp::BitOr => bx.or(lhs, rhs),
|
mir::BinOp::BitOr => bx.or(lhs, rhs),
|
||||||
mir::BinOp::BitAnd => bx.and(lhs, rhs),
|
mir::BinOp::BitAnd => bx.and(lhs, rhs),
|
||||||
mir::BinOp::BitXor => bx.xor(lhs, rhs),
|
mir::BinOp::BitXor => bx.xor(lhs, rhs),
|
||||||
mir::BinOp::Offset => bx.inbounds_gep(lhs, &[rhs]),
|
mir::BinOp::Offset => {
|
||||||
|
let pointee_type = input_ty
|
||||||
|
.builtin_deref(true)
|
||||||
|
.unwrap_or_else(|| bug!("deref of non-pointer {:?}", input_ty))
|
||||||
|
.ty;
|
||||||
|
let llty = bx.cx().backend_type(bx.cx().layout_of(pointee_type));
|
||||||
|
bx.inbounds_gep(llty, lhs, &[rhs])
|
||||||
|
}
|
||||||
mir::BinOp::Shl => common::build_unchecked_lshift(bx, lhs, rhs),
|
mir::BinOp::Shl => common::build_unchecked_lshift(bx, lhs, rhs),
|
||||||
mir::BinOp::Shr => common::build_unchecked_rshift(bx, input_ty, lhs, rhs),
|
mir::BinOp::Shr => common::build_unchecked_rshift(bx, input_ty, lhs, rhs),
|
||||||
mir::BinOp::Ne
|
mir::BinOp::Ne
|
||||||
|
|
|
@ -177,7 +177,12 @@ pub trait BuilderMethods<'a, 'tcx>:
|
||||||
);
|
);
|
||||||
|
|
||||||
fn gep(&mut self, ty: Self::Type, ptr: Self::Value, indices: &[Self::Value]) -> Self::Value;
|
fn gep(&mut self, ty: Self::Type, ptr: Self::Value, indices: &[Self::Value]) -> Self::Value;
|
||||||
fn inbounds_gep(&mut self, ptr: Self::Value, indices: &[Self::Value]) -> Self::Value;
|
fn inbounds_gep(
|
||||||
|
&mut self,
|
||||||
|
ty: Self::Type,
|
||||||
|
ptr: Self::Value,
|
||||||
|
indices: &[Self::Value],
|
||||||
|
) -> Self::Value;
|
||||||
fn struct_gep(&mut self, ty: Self::Type, ptr: Self::Value, idx: u64) -> Self::Value;
|
fn struct_gep(&mut self, ty: Self::Type, ptr: Self::Value, idx: u64) -> Self::Value;
|
||||||
|
|
||||||
fn trunc(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value;
|
fn trunc(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue