}
}
-impl abi::LayoutOf for Builder<'_, '_, 'tcx> {
+impl abi::LayoutOf<'tcx> for Builder<'_, '_, 'tcx> {
type Ty = Ty<'tcx>;
type TyAndLayout = TyAndLayout<'tcx>;
fn invoke(
&mut self,
+ llty: &'ll Type,
llfn: &'ll Value,
args: &[&'ll Value],
then: &'ll BasicBlock,
) -> &'ll Value {
debug!("invoke {:?} with args ({:?})", llfn, args);
- let args = self.check_call("invoke", llfn, args);
+ let args = self.check_call("invoke", llty, llfn, args);
let bundle = funclet.map(|funclet| funclet.bundle());
let bundle = bundle.as_ref().map(|b| &*b.raw);
unsafe {
llvm::LLVMRustBuildInvoke(
self.llbuilder,
+ llty,
llfn,
args.as_ptr(),
args.len() as c_uint,
},
};
- let intrinsic = self.get_intrinsic(&name);
- let res = self.call(intrinsic, &[lhs, rhs], None);
+ let res = self.call_intrinsic(name, &[lhs, rhs]);
(self.extract_value(res, 0), self.extract_value(res, 1))
}
load: &'ll Value,
scalar: &abi::Scalar,
) {
- let vr = scalar.valid_range.clone();
match scalar.value {
abi::Int(..) => {
let range = scalar.valid_range_exclusive(bx);
bx.range_metadata(load, range);
}
}
- abi::Pointer if vr.start() < vr.end() && !vr.contains(&0) => {
+ abi::Pointer if !scalar.valid_range.contains_zero() => {
bx.nonnull_metadata(load);
}
_ => {}
OperandValue::Immediate(self.to_immediate(llval, place.layout))
} else if let abi::Abi::ScalarPair(ref a, ref b) = place.layout.abi {
let b_offset = a.value.size(self).align_to(b.value.align(self).abi);
+ let pair_ty = place.layout.llvm_type(self);
let mut load = |i, scalar: &abi::Scalar, align| {
- let llptr = self.struct_gep(place.llval, i as u64);
+ let llptr = self.struct_gep(pair_ty, place.llval, i as u64);
let llty = place.layout.scalar_pair_element_llvm_type(self, i, false);
let load = self.load(llty, llptr, align);
scalar_load_metadata(self, load, scalar);
.val
.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());
header_bx.add_incoming_to_phi(current, next, body_bx.llbb());
fn range_metadata(&mut self, load: &'ll Value, range: Range<u128>) {
if self.sess().target.arch == "amdgpu" {
- // amdgpu/LLVM does something weird and thinks a i64 value is
+ // amdgpu/LLVM does something weird and thinks an i64 value is
// split into a v2i32, halving the bitwidth LLVM expects,
// tripping an assertion. So, for now, just disable this
// optimization.
}
}
- fn gep(&mut self, ptr: &'ll Value, indices: &[&'ll Value]) -> &'ll Value {
+ fn gep(&mut self, ty: &'ll Type, ptr: &'ll Value, indices: &[&'ll Value]) -> &'ll Value {
unsafe {
- llvm::LLVMBuildGEP(
+ llvm::LLVMBuildGEP2(
self.llbuilder,
+ ty,
ptr,
indices.as_ptr(),
indices.len() as c_uint,
}
}
- 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 {
- llvm::LLVMBuildInBoundsGEP(
+ llvm::LLVMBuildInBoundsGEP2(
self.llbuilder,
+ ty,
ptr,
indices.as_ptr(),
indices.len() as c_uint,
}
}
- fn struct_gep(&mut self, ptr: &'ll Value, idx: u64) -> &'ll Value {
+ fn struct_gep(&mut self, ty: &'ll Type, ptr: &'ll Value, idx: u64) -> &'ll Value {
assert_eq!(idx as c_uint as u64, idx);
- unsafe { llvm::LLVMBuildStructGEP(self.llbuilder, ptr, idx as c_uint, UNNAMED) }
+ unsafe { llvm::LLVMBuildStructGEP2(self.llbuilder, ty, ptr, idx as c_uint, UNNAMED) }
}
/* Casts */
let float_width = self.cx.float_width(src_ty);
let int_width = self.cx.int_width(dest_ty);
let name = format!("llvm.fptoui.sat.i{}.f{}", int_width, float_width);
- let intrinsic = self.get_intrinsic(&name);
- return Some(self.call(intrinsic, &[val], None));
+ return Some(self.call_intrinsic(&name, &[val]));
}
None
let float_width = self.cx.float_width(src_ty);
let int_width = self.cx.int_width(dest_ty);
let name = format!("llvm.fptosi.sat.i{}.f{}", int_width, float_width);
- let intrinsic = self.get_intrinsic(&name);
- return Some(self.call(intrinsic, &[val], None));
+ return Some(self.call_intrinsic(&name, &[val]));
}
None
_ => None,
};
if let Some(name) = name {
- let intrinsic = self.get_intrinsic(name);
- return self.call(intrinsic, &[val], None);
+ return self.call_intrinsic(name, &[val]);
}
}
}
_ => None,
};
if let Some(name) = name {
- let intrinsic = self.get_intrinsic(name);
- return self.call(intrinsic, &[val], None);
+ return self.call_intrinsic(name, &[val]);
}
}
}
);
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_void(),
+ );
let args = &[fn_name, hash, num_counters, index];
- let args = self.check_call("call", llfn, args);
+ let args = self.check_call("call", llty, llfn, args);
unsafe {
let _ = llvm::LLVMRustBuildCall(
self.llbuilder,
+ llty,
llfn,
args.as_ptr() as *const &llvm::Value,
args.len() as c_uint,
fn call(
&mut self,
+ llty: &'ll Type,
llfn: &'ll Value,
args: &[&'ll Value],
funclet: Option<&Funclet<'ll>>,
) -> &'ll Value {
debug!("call {:?} with args ({:?})", llfn, args);
- let args = self.check_call("call", llfn, args);
+ let args = self.check_call("call", llty, llfn, args);
let bundle = funclet.map(|funclet| funclet.bundle());
let bundle = bundle.as_ref().map(|b| &*b.raw);
unsafe {
llvm::LLVMRustBuildCall(
self.llbuilder,
+ llty,
llfn,
args.as_ptr() as *const &llvm::Value,
args.len() as c_uint,
fn check_call<'b>(
&mut self,
typ: &str,
+ fn_ty: &'ll Type,
llfn: &'ll Value,
args: &'b [&'ll Value],
) -> Cow<'b, [&'ll Value]> {
- let mut fn_ty = self.cx.val_ty(llfn);
- // Strip off pointers
- while self.cx.type_kind(fn_ty) == TypeKind::Pointer {
- fn_ty = self.cx.element_type(fn_ty);
- }
-
assert!(
self.cx.type_kind(fn_ty) == TypeKind::Function,
"builder::{} not passed a function, but {:?}",
unsafe { llvm::LLVMBuildVAArg(self.llbuilder, list, ty, UNNAMED) }
}
+ crate fn call_intrinsic(&mut self, intrinsic: &str, args: &[&'ll Value]) -> &'ll Value {
+ let (ty, f) = self.cx.get_intrinsic(intrinsic);
+ self.call(ty, f, args, None)
+ }
+
fn call_lifetime_intrinsic(&mut self, intrinsic: &str, ptr: &'ll Value, size: Size) {
let size = size.bytes();
if size == 0 {
return;
}
- let lifetime_intrinsic = self.cx.get_intrinsic(intrinsic);
-
let ptr = self.pointercast(ptr, self.cx.type_i8p());
- self.call(lifetime_intrinsic, &[self.cx.const_u64(size), ptr], None);
+ self.call_intrinsic(intrinsic, &[self.cx.const_u64(size), ptr]);
}
pub(crate) fn phi(