Fail unimplemented intrinsics instead of incorrect behavior (#114)

This commit is contained in:
Ashley Hauck 2020-10-23 13:18:31 +02:00 committed by GitHub
parent 3f5244dd3e
commit 9dc6c61c4c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 67 additions and 50 deletions

View File

@ -547,9 +547,12 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
simple_op! {fmul, f_mul}
simple_op! {fmul_fast, f_mul} // fast=normal
simple_op! {udiv, u_div}
simple_op! {exactudiv, u_div} // ignore
// Note: exactudiv is UB when there's a remainder, so it's valid to implement as a normal div.
// TODO: Can we take advantage of the UB and emit something else?
simple_op! {exactudiv, u_div}
simple_op! {sdiv, s_div}
simple_op! {exactsdiv, s_div} // ignore
// Same note and TODO as exactudiv
simple_op! {exactsdiv, s_div}
simple_op! {fdiv, f_div}
simple_op! {fdiv_fast, f_div} // fast=normal
simple_op! {urem, u_mod}
@ -636,11 +639,20 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
rhs: Self::Value,
) -> (Self::Value, Self::Value) {
let fals = self.constant_bool(false);
match oop {
let result = match oop {
OverflowOp::Add => (self.add(lhs, rhs), fals),
OverflowOp::Sub => (self.sub(lhs, rhs), fals),
OverflowOp::Mul => (self.mul(lhs, rhs), fals),
}
};
self.zombie(
result.1.def,
match oop {
OverflowOp::Add => "checked add is not supported yet",
OverflowOp::Sub => "checked sub is not supported yet",
OverflowOp::Mul => "checked mul is not supported yet",
},
);
result
}
fn from_immediate(&mut self, val: Self::Value) -> Self::Value {
@ -698,11 +710,13 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
}
fn dynamic_alloca(&mut self, ty: Self::Type, align: Align) -> Self::Value {
self.alloca(ty, align)
let result = self.alloca(ty, align);
self.err("dynamic alloca is not supported yet");
result
}
fn array_alloca(&mut self, _ty: Self::Type, _len: Self::Value, _align: Align) -> Self::Value {
self.fatal("TODO: array_alloca not supported yet")
self.fatal("array alloca not supported yet")
}
fn load(&mut self, ptr: Self::Value, _align: Align) -> Self::Value {
@ -727,8 +741,10 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
}
fn volatile_load(&mut self, ptr: Self::Value) -> Self::Value {
// TODO: Can we do something here?
self.load(ptr, Align::from_bytes(0).unwrap())
// TODO: Implement this
let result = self.load(ptr, Align::from_bytes(0).unwrap());
self.zombie(result.def, "volatile load is not supported yet");
result
}
fn atomic_load(&mut self, ptr: Self::Value, order: AtomicOrdering, _size: Size) -> Self::Value {
@ -818,36 +834,6 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
}
self
/*
let zero = self.const_usize(0);
let count = self.const_usize(count);
let start = dest.project_index(&mut self, zero).llval;
let end = dest.project_index(&mut self, count).llval;
let mut header_bx = self.build_sibling_block("repeat_loop_header");
let mut body_bx = self.build_sibling_block("repeat_loop_body");
let next_bx = self.build_sibling_block("repeat_loop_next");
self.br(header_bx.llbb());
let current = header_bx.phi(start.ty, &[start], &[self.llbb()]);
let keep_going = header_bx.icmp(IntPredicate::IntNE, current, end);
header_bx.cond_br(keep_going, body_bx.llbb(), next_bx.llbb());
let align = dest
.align
.restrict_for_offset(dest.layout.field(self.cx(), 0).size);
cg_elem.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)]);
body_bx.br(header_bx.llbb());
header_bx.add_incoming_to_phi(current, next, body_bx.llbb());
next_bx
*/
}
fn range_metadata(&mut self, _load: Self::Value, _range: Range<u128>) {
@ -879,8 +865,14 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
val: Self::Value,
ptr: Self::Value,
align: Align,
_flags: MemFlags,
flags: MemFlags,
) -> Self::Value {
if flags != MemFlags::empty() {
self.err(&format!(
"store_with_flags is not supported yet: {:?}",
flags
));
}
self.store(val, ptr, align)
}
@ -1369,8 +1361,14 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
src: Self::Value,
_src_align: Align,
size: Self::Value,
_flags: MemFlags,
flags: MemFlags,
) {
if flags != MemFlags::empty() {
self.err(&format!(
"memcpy with mem flags is not supported yet: {:?}",
flags
));
}
let const_size = self.builder.lookup_const_u64(size);
if const_size == Some(0) {
// Nothing to do!
@ -1417,8 +1415,14 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
fill_byte: Self::Value,
size: Self::Value,
_align: Align,
_flags: MemFlags,
flags: MemFlags,
) {
if flags != MemFlags::empty() {
self.err(&format!(
"memset with mem flags is not supported yet: {:?}",
flags
));
}
let elem_ty = match self.lookup_type(ptr.ty) {
SpirvType::Pointer { pointee, .. } => pointee,
_ => self.fatal(&format!(

View File

@ -87,23 +87,35 @@ impl<'a, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'tcx> {
sym::saturating_add => {
assert_eq!(arg_tys[0], arg_tys[1]);
match &arg_tys[0].kind() {
let result = match &arg_tys[0].kind() {
TyKind::Int(_) | TyKind::Uint(_) => {
self.add(args[0].immediate(), args[1].immediate())
}
TyKind::Float(_) => self.fadd(args[0].immediate(), args[1].immediate()),
other => self.fatal(&format!("Unimplemented intrinsic type: {:#?}", other)),
}
other => self.fatal(&format!(
"Unimplemented saturating_add intrinsic type: {:#?}",
other
)),
};
// TODO: Implement this
self.zombie(result.def, "saturating_add is not implemented yet");
result
}
sym::saturating_sub => {
assert_eq!(arg_tys[0], arg_tys[1]);
match &arg_tys[0].kind() {
let result = match &arg_tys[0].kind() {
TyKind::Int(_) | TyKind::Uint(_) => {
self.sub(args[0].immediate(), args[1].immediate())
}
TyKind::Float(_) => self.fsub(args[0].immediate(), args[1].immediate()),
other => self.fatal(&format!("Unimplemented intrinsic type: {:#?}", other)),
}
other => self.fatal(&format!(
"Unimplemented saturating_sub intrinsic type: {:#?}",
other
)),
};
// TODO: Implement this
self.zombie(result.def, "saturating_sub is not implemented yet");
result
}
// TODO: Configure these to be ocl vs. gl ext instructions, etc.

View File

@ -71,6 +71,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
self.tcx.sess.struct_err(msg)
}
}
*/
pub fn err(&self, msg: &str) {
if let Some(current_span) = self.current_span {
@ -79,7 +80,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
self.tcx.sess.err(msg)
}
}
*/
pub fn fatal(&self, msg: &str) -> ! {
if let Some(current_span) = self.current_span {
@ -347,7 +347,8 @@ impl<'a, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'tcx> {
_inputs: Vec<Self::Value>,
_span: Span,
) -> bool {
todo!()
self.err("LLVM asm not supported");
true
}
fn codegen_inline_asm(
@ -357,7 +358,7 @@ impl<'a, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'tcx> {
_options: InlineAsmOptions,
_line_spans: &[Span],
) {
todo!()
self.err("asm not supported")
}
}
impl<'a, 'tcx> StaticBuilderMethods for Builder<'a, 'tcx> {