Further simplify intrinsic matching

This commit is contained in:
Mark Simulacrum 2016-12-17 18:25:32 -07:00
parent 611e90b118
commit 99816a6743

View File

@ -211,44 +211,20 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(bcx: &BlockAndBuilder<'blk, 'tcx>,
}
"copy_nonoverlapping" => {
copy_intrinsic(bcx,
false,
false,
substs.type_at(0),
llargs[1],
llargs[0],
llargs[2])
copy_intrinsic(bcx, false, false, substs.type_at(0), llargs[1], llargs[0], llargs[2])
}
"copy" => {
copy_intrinsic(bcx,
true,
false,
substs.type_at(0),
llargs[1],
llargs[0],
llargs[2])
copy_intrinsic(bcx, true, false, substs.type_at(0), llargs[1], llargs[0], llargs[2])
}
"write_bytes" => {
memset_intrinsic(bcx, false, substs.type_at(0), llargs[0], llargs[1], llargs[2])
}
"volatile_copy_nonoverlapping_memory" => {
copy_intrinsic(bcx,
false,
true,
substs.type_at(0),
llargs[0],
llargs[1],
llargs[2])
copy_intrinsic(bcx, false, true, substs.type_at(0), llargs[0], llargs[1], llargs[2])
}
"volatile_copy_memory" => {
copy_intrinsic(bcx,
true,
true,
substs.type_at(0),
llargs[0],
llargs[1],
llargs[2])
copy_intrinsic(bcx, true, true, substs.type_at(0), llargs[0], llargs[1], llargs[2])
}
"volatile_set_memory" => {
memset_intrinsic(bcx, true, substs.type_at(0), llargs[0], llargs[1], llargs[2])
@ -293,10 +269,11 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(bcx: &BlockAndBuilder<'blk, 'tcx>,
match int_type_width_signed(sty, ccx) {
Some((width, signed)) =>
match name {
"ctlz" => count_zeros_intrinsic(bcx, &format!("llvm.ctlz.i{}", width),
llargs[0]),
"cttz" => count_zeros_intrinsic(bcx, &format!("llvm.cttz.i{}", width),
llargs[0]),
"ctlz" | "cttz" => {
let y = C_bool(bcx.ccx(), false);
let llfn = ccx.get_intrinsic(&format!("llvm.{}.i{}", name, width));
bcx.call(llfn, &[llargs[0], y], None)
}
"ctpop" => bcx.call(ccx.get_intrinsic(&format!("llvm.ctpop.i{}", width)),
&llargs, None),
"bswap" => {
@ -311,7 +288,16 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(bcx: &BlockAndBuilder<'blk, 'tcx>,
let intrinsic = format!("llvm.{}{}.with.overflow.i{}",
if signed { 's' } else { 'u' },
&name[..3], width);
with_overflow_intrinsic(bcx, &intrinsic, llargs[0], llargs[1], llresult)
let llfn = bcx.ccx().get_intrinsic(&intrinsic);
// Convert `i1` to a `bool`, and write it to the out parameter
let val = bcx.call(llfn, &[llargs[0], llargs[1]], None);
let result = bcx.extract_value(val, 0);
let overflow = bcx.zext(bcx.extract_value(val, 1), Type::bool(ccx));
bcx.store(result, bcx.struct_gep(llresult, 0));
bcx.store(overflow, bcx.struct_gep(llresult, 1));
C_nil(bcx.ccx())
},
"overflowing_add" => bcx.add(llargs[0], llargs[1]),
"overflowing_sub" => bcx.sub(llargs[0], llargs[1]),
@ -412,6 +398,12 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(bcx: &BlockAndBuilder<'blk, 'tcx>,
_ => ccx.sess().fatal("Atomic intrinsic not in correct format"),
};
let invalid_monomorphization = |sty| {
span_invalid_monomorphization_error(tcx.sess, span,
&format!("invalid monomorphization of `{}` intrinsic: \
expected basic integer type, found `{}`", name, sty));
};
match split[1] {
"cxchg" | "cxchgweak" => {
let sty = &substs.type_at(0).sty;
@ -424,10 +416,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(bcx: &BlockAndBuilder<'blk, 'tcx>,
bcx.store(result, bcx.struct_gep(llresult, 0));
bcx.store(success, bcx.struct_gep(llresult, 1));
} else {
span_invalid_monomorphization_error(
tcx.sess, span,
&format!("invalid monomorphization of `{}` intrinsic: \
expected basic integer type, found `{}`", name, sty));
invalid_monomorphization(sty);
}
C_nil(ccx)
}
@ -437,10 +426,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(bcx: &BlockAndBuilder<'blk, 'tcx>,
if int_type_width_signed(sty, ccx).is_some() {
bcx.atomic_load(llargs[0], order)
} else {
span_invalid_monomorphization_error(
tcx.sess, span,
&format!("invalid monomorphization of `{}` intrinsic: \
expected basic integer type, found `{}`", name, sty));
invalid_monomorphization(sty);
C_nil(ccx)
}
}
@ -450,10 +436,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(bcx: &BlockAndBuilder<'blk, 'tcx>,
if int_type_width_signed(sty, ccx).is_some() {
bcx.atomic_store(llargs[1], llargs[0], order);
} else {
span_invalid_monomorphization_error(
tcx.sess, span,
&format!("invalid monomorphization of `{}` intrinsic: \
expected basic integer type, found `{}`", name, sty));
invalid_monomorphization(sty);
}
C_nil(ccx)
}
@ -489,15 +472,11 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(bcx: &BlockAndBuilder<'blk, 'tcx>,
if int_type_width_signed(sty, ccx).is_some() {
bcx.atomic_rmw(atom_op, llargs[0], llargs[1], order)
} else {
span_invalid_monomorphization_error(
tcx.sess, span,
&format!("invalid monomorphization of `{}` intrinsic: \
expected basic integer type, found `{}`", name, sty));
invalid_monomorphization(sty);
C_nil(ccx)
}
}
}
}
_ => {
@ -529,18 +508,15 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(bcx: &BlockAndBuilder<'blk, 'tcx>,
*any_changes_needed |= llvm_elem.is_some();
let t = llvm_elem.as_ref().unwrap_or(t);
let elem = one(ty_to_type(ccx, t,
any_changes_needed));
let elem = one(ty_to_type(ccx, t, any_changes_needed));
vec![elem.ptr_to()]
}
Vector(ref t, ref llvm_elem, length) => {
*any_changes_needed |= llvm_elem.is_some();
let t = llvm_elem.as_ref().unwrap_or(t);
let elem = one(ty_to_type(ccx, t,
any_changes_needed));
vec![Type::vector(&elem,
length as u64)]
let elem = one(ty_to_type(ccx, t, any_changes_needed));
vec![Type::vector(&elem, length as u64)]
}
Aggregate(false, ref contents) => {
let elems = contents.iter()
@ -585,8 +561,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(bcx: &BlockAndBuilder<'blk, 'tcx>,
}
intrinsics::Type::Pointer(_, Some(ref llvm_elem), _) => {
let llvm_elem = one(ty_to_type(bcx.ccx(), llvm_elem, &mut false));
vec![bcx.pointercast(llarg,
llvm_elem.ptr_to())]
vec![bcx.pointercast(llarg, llvm_elem.ptr_to())]
}
intrinsics::Type::Vector(_, Some(ref llvm_elem), length) => {
let llvm_elem = one(ty_to_type(bcx.ccx(), llvm_elem, &mut false));
@ -718,33 +693,6 @@ fn memset_intrinsic<'blk, 'tcx>(
call_memset(bcx, dst, val, bcx.mul(size, count), align, volatile)
}
fn count_zeros_intrinsic(bcx: &BlockAndBuilder,
name: &str,
val: ValueRef)
-> ValueRef {
let y = C_bool(bcx.ccx(), false);
let llfn = bcx.ccx().get_intrinsic(&name);
bcx.call(llfn, &[val, y], None)
}
fn with_overflow_intrinsic<'blk, 'tcx>(bcx: &BlockAndBuilder<'blk, 'tcx>,
name: &str,
a: ValueRef,
b: ValueRef,
out: ValueRef)
-> ValueRef {
let llfn = bcx.ccx().get_intrinsic(&name);
// Convert `i1` to a `bool`, and write it to the out parameter
let val = bcx.call(llfn, &[a, b], None);
let result = bcx.extract_value(val, 0);
let overflow = bcx.zext(bcx.extract_value(val, 1), Type::bool(bcx.ccx()));
bcx.store(result, bcx.struct_gep(out, 0));
bcx.store(overflow, bcx.struct_gep(out, 1));
C_nil(bcx.ccx())
}
fn try_intrinsic<'blk, 'tcx>(
bcx: &BlockAndBuilder<'blk, 'tcx>,
func: ValueRef,