if let Some(inner) = rust_ptr_attrs(ty, &mut data) {
data.attrs.set(ArgAttribute::NonNull);
if ccx.tcx().struct_tail(inner).is_trait() {
+ // vtables can be safely marked non-null, readonly
+ // and noalias.
info.attrs.set(ArgAttribute::NonNull);
+ info.attrs.set(ArgAttribute::ReadOnly);
+ info.attrs.set(ArgAttribute::NoAlias);
}
}
args.push(data);
b.load(ptr, alignment.to_align())
};
- // FIXME: emit metadata on `meta`.
- let meta = b.load(get_meta(b, src), alignment.to_align());
+ let meta = get_meta(b, src);
+ let meta_ty = val_ty(meta);
+ // If the 'meta' field is a pointer, it's a vtable, so use load_nonnull
+ // instead
+ let meta = if meta_ty.element_type().kind() == llvm::TypeKind::Pointer {
+ b.load_nonnull(meta, None)
+ } else {
+ b.load(meta, None)
+ };
(ptr, meta)
}
}
}
+ pub fn set_invariant_load(&self, load: ValueRef) {
+ unsafe {
+ llvm::LLVMSetMetadata(load, llvm::MD_invariant_load as c_uint,
+ llvm::LLVMMDNodeInContext(self.ccx.llcx(), ptr::null(), 0));
+ }
+ }
+
/// Returns the ptr value that should be used for storing `val`.
fn check_store<'b>(&self,
val: ValueRef,
let info = bcx.pointercast(info, Type::int(bcx.ccx).ptr_to());
let size_ptr = bcx.gepi(info, &[1]);
let align_ptr = bcx.gepi(info, &[2]);
- (bcx.load(size_ptr, None), bcx.load(align_ptr, None))
+
+ let size = bcx.load(size_ptr, None);
+ let align = bcx.load(align_ptr, None);
+
+ // Vtable loads are invariant
+ bcx.set_invariant_load(size);
+ bcx.set_invariant_load(align);
+
+ (size, align)
}
ty::TySlice(_) | ty::TyStr => {
let unit_ty = t.sequence_element_type(bcx.tcx());
/// Extracts a method from a trait object's vtable, at the specified index.
pub fn get_virtual_method<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
llvtable: ValueRef,
- vtable_index: usize)
- -> ValueRef {
+ vtable_index: usize) -> ValueRef {
// Load the data pointer from the object.
debug!("get_virtual_method(vtable_index={}, llvtable={:?})",
vtable_index, Value(llvtable));
- bcx.load(bcx.gepi(llvtable, &[vtable_index + VTABLE_OFFSET]), None)
+ let ptr = bcx.load_nonnull(bcx.gepi(llvtable, &[vtable_index + VTABLE_OFFSET]), None);
+ // Vtable loads are invariant
+ bcx.set_invariant_load(ptr);
+ ptr
}
/// Generate a shim function that allows an object type like `SomeTrait` to