From 2d4c96d1b1bfcad05607172c6626b73c9c266084 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Sat, 24 Nov 2018 16:44:17 +0100 Subject: [PATCH] Move IntrinsicCallMethods::call_overflow_intrinsics to BuilderMethods::checked_binop --- src/librustc_codegen_llvm/builder.rs | 74 ++++++++++++++++++++ src/librustc_codegen_llvm/intrinsic.rs | 74 -------------------- src/librustc_codegen_ssa/mir/rvalue.rs | 2 +- src/librustc_codegen_ssa/traits/builder.rs | 16 +++++ src/librustc_codegen_ssa/traits/intrinsic.rs | 15 ---- src/librustc_codegen_ssa/traits/mod.rs | 4 +- 6 files changed, 93 insertions(+), 92 deletions(-) diff --git a/src/librustc_codegen_llvm/builder.rs b/src/librustc_codegen_llvm/builder.rs index fd0649e78964f..06e52fbe76ce4 100644 --- a/src/librustc_codegen_llvm/builder.rs +++ b/src/librustc_codegen_llvm/builder.rs @@ -456,6 +456,80 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { } } + fn checked_binop( + &mut self, + oop: OverflowOp, + ty: Ty, + lhs: Self::Value, + rhs: Self::Value, + ) -> (Self::Value, Self::Value) { + use syntax::ast::IntTy::*; + use syntax::ast::UintTy::*; + use rustc::ty::{Int, Uint}; + + let new_sty = match ty.sty { + Int(Isize) => Int(self.cx().tcx.sess.target.isize_ty), + Uint(Usize) => Uint(self.cx().tcx.sess.target.usize_ty), + ref t @ Uint(_) | ref t @ Int(_) => t.clone(), + _ => panic!("tried to get overflow intrinsic for op applied to non-int type") + }; + + let name = match oop { + OverflowOp::Add => match new_sty { + Int(I8) => "llvm.sadd.with.overflow.i8", + Int(I16) => "llvm.sadd.with.overflow.i16", + Int(I32) => "llvm.sadd.with.overflow.i32", + Int(I64) => "llvm.sadd.with.overflow.i64", + Int(I128) => "llvm.sadd.with.overflow.i128", + + Uint(U8) => "llvm.uadd.with.overflow.i8", + Uint(U16) => "llvm.uadd.with.overflow.i16", + Uint(U32) => "llvm.uadd.with.overflow.i32", + Uint(U64) => "llvm.uadd.with.overflow.i64", + Uint(U128) => "llvm.uadd.with.overflow.i128", + + _ => unreachable!(), + }, + OverflowOp::Sub => match new_sty { + Int(I8) => "llvm.ssub.with.overflow.i8", + Int(I16) => "llvm.ssub.with.overflow.i16", + Int(I32) => "llvm.ssub.with.overflow.i32", + Int(I64) => "llvm.ssub.with.overflow.i64", + Int(I128) => "llvm.ssub.with.overflow.i128", + + Uint(U8) => "llvm.usub.with.overflow.i8", + Uint(U16) => "llvm.usub.with.overflow.i16", + Uint(U32) => "llvm.usub.with.overflow.i32", + Uint(U64) => "llvm.usub.with.overflow.i64", + Uint(U128) => "llvm.usub.with.overflow.i128", + + _ => unreachable!(), + }, + OverflowOp::Mul => match new_sty { + Int(I8) => "llvm.smul.with.overflow.i8", + Int(I16) => "llvm.smul.with.overflow.i16", + Int(I32) => "llvm.smul.with.overflow.i32", + Int(I64) => "llvm.smul.with.overflow.i64", + Int(I128) => "llvm.smul.with.overflow.i128", + + Uint(U8) => "llvm.umul.with.overflow.i8", + Uint(U16) => "llvm.umul.with.overflow.i16", + Uint(U32) => "llvm.umul.with.overflow.i32", + Uint(U64) => "llvm.umul.with.overflow.i64", + Uint(U128) => "llvm.umul.with.overflow.i128", + + _ => unreachable!(), + }, + }; + + let intrinsic = self.cx().get_intrinsic(&name); + let res = self.call(intrinsic, &[lhs, rhs], None); + ( + self.extract_value(res, 0), + self.extract_value(res, 1), + ) + } + fn alloca(&mut self, ty: &'ll Type, name: &str, align: Align) -> &'ll Value { let mut bx = Builder::with_cx(self.cx); bx.position_at_start(unsafe { diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs index c495a0d92d110..54a2684b63ff7 100644 --- a/src/librustc_codegen_llvm/intrinsic.rs +++ b/src/librustc_codegen_llvm/intrinsic.rs @@ -778,80 +778,6 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { let expect = self.cx().get_intrinsic(&"llvm.expect.i1"); self.call(expect, &[cond, self.cx().const_bool(expected)], None) } - - fn call_overflow_intrinsic( - &mut self, - oop: OverflowOp, - ty: Ty, - lhs: Self::Value, - rhs: Self::Value, - ) -> (Self::Value, Self::Value) { - use syntax::ast::IntTy::*; - use syntax::ast::UintTy::*; - use rustc::ty::{Int, Uint}; - - let new_sty = match ty.sty { - Int(Isize) => Int(self.tcx().sess.target.isize_ty), - Uint(Usize) => Uint(self.tcx().sess.target.usize_ty), - ref t @ Uint(_) | ref t @ Int(_) => t.clone(), - _ => panic!("tried to get overflow intrinsic for op applied to non-int type") - }; - - let name = match oop { - OverflowOp::Add => match new_sty { - Int(I8) => "llvm.sadd.with.overflow.i8", - Int(I16) => "llvm.sadd.with.overflow.i16", - Int(I32) => "llvm.sadd.with.overflow.i32", - Int(I64) => "llvm.sadd.with.overflow.i64", - Int(I128) => "llvm.sadd.with.overflow.i128", - - Uint(U8) => "llvm.uadd.with.overflow.i8", - Uint(U16) => "llvm.uadd.with.overflow.i16", - Uint(U32) => "llvm.uadd.with.overflow.i32", - Uint(U64) => "llvm.uadd.with.overflow.i64", - Uint(U128) => "llvm.uadd.with.overflow.i128", - - _ => unreachable!(), - }, - OverflowOp::Sub => match new_sty { - Int(I8) => "llvm.ssub.with.overflow.i8", - Int(I16) => "llvm.ssub.with.overflow.i16", - Int(I32) => "llvm.ssub.with.overflow.i32", - Int(I64) => "llvm.ssub.with.overflow.i64", - Int(I128) => "llvm.ssub.with.overflow.i128", - - Uint(U8) => "llvm.usub.with.overflow.i8", - Uint(U16) => "llvm.usub.with.overflow.i16", - Uint(U32) => "llvm.usub.with.overflow.i32", - Uint(U64) => "llvm.usub.with.overflow.i64", - Uint(U128) => "llvm.usub.with.overflow.i128", - - _ => unreachable!(), - }, - OverflowOp::Mul => match new_sty { - Int(I8) => "llvm.smul.with.overflow.i8", - Int(I16) => "llvm.smul.with.overflow.i16", - Int(I32) => "llvm.smul.with.overflow.i32", - Int(I64) => "llvm.smul.with.overflow.i64", - Int(I128) => "llvm.smul.with.overflow.i128", - - Uint(U8) => "llvm.umul.with.overflow.i8", - Uint(U16) => "llvm.umul.with.overflow.i16", - Uint(U32) => "llvm.umul.with.overflow.i32", - Uint(U64) => "llvm.umul.with.overflow.i64", - Uint(U128) => "llvm.umul.with.overflow.i128", - - _ => unreachable!(), - }, - }; - - let intrinsic = self.cx().get_intrinsic(&name); - let res = self.call(intrinsic, &[lhs, rhs], None); - ( - self.extract_value(res, 0), - self.extract_value(res, 1), - ) - } } fn copy_intrinsic( diff --git a/src/librustc_codegen_ssa/mir/rvalue.rs b/src/librustc_codegen_ssa/mir/rvalue.rs index 7c794c053ecd0..dc7b1ec37b23a 100644 --- a/src/librustc_codegen_ssa/mir/rvalue.rs +++ b/src/librustc_codegen_ssa/mir/rvalue.rs @@ -693,7 +693,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { mir::BinOp::Mul => OverflowOp::Mul, _ => unreachable!() }; - bx.call_overflow_intrinsic(oop, input_ty, lhs, rhs) + bx.checked_binop(oop, input_ty, lhs, rhs) } mir::BinOp::Shl | mir::BinOp::Shr => { let lhs_llty = bx.cx().val_ty(lhs); diff --git a/src/librustc_codegen_ssa/traits/builder.rs b/src/librustc_codegen_ssa/traits/builder.rs index 071bd8ad67bc8..063e7ba8ba2df 100644 --- a/src/librustc_codegen_ssa/traits/builder.rs +++ b/src/librustc_codegen_ssa/traits/builder.rs @@ -17,6 +17,7 @@ use super::HasCodegen; use common::{AtomicOrdering, AtomicRmwBinOp, IntPredicate, RealPredicate, SynchronizationScope}; use mir::operand::OperandRef; use mir::place::PlaceRef; +use rustc::ty::Ty; use rustc::ty::layout::{Align, Size}; use std::ffi::CStr; use MemFlags; @@ -25,6 +26,13 @@ use std::borrow::Cow; use std::ops::Range; use syntax::ast::AsmDialect; +#[derive(Copy, Clone)] +pub enum OverflowOp { + Add, + Sub, + Mul, +} + pub trait BuilderMethods<'a, 'tcx: 'a>: HasCodegen<'tcx> + DebugInfoBuilderMethods<'tcx> @@ -97,6 +105,14 @@ pub trait BuilderMethods<'a, 'tcx: 'a>: fn fneg(&mut self, v: Self::Value) -> Self::Value; fn not(&mut self, v: Self::Value) -> Self::Value; + fn checked_binop( + &mut self, + oop: OverflowOp, + ty: Ty, + lhs: Self::Value, + rhs: Self::Value, + ) -> (Self::Value, Self::Value); + fn alloca(&mut self, ty: Self::Type, name: &str, align: Align) -> Self::Value; fn dynamic_alloca(&mut self, ty: Self::Type, name: &str, align: Align) -> Self::Value; fn array_alloca( diff --git a/src/librustc_codegen_ssa/traits/intrinsic.rs b/src/librustc_codegen_ssa/traits/intrinsic.rs index 539c781e283d8..abc118e770852 100644 --- a/src/librustc_codegen_ssa/traits/intrinsic.rs +++ b/src/librustc_codegen_ssa/traits/intrinsic.rs @@ -14,13 +14,6 @@ use rustc::ty::Ty; use rustc_target::abi::call::FnType; use syntax_pos::Span; -#[derive(Copy, Clone)] -pub enum OverflowOp { - Add, - Sub, - Mul, -} - pub trait IntrinsicCallMethods<'tcx>: BackendTypes { /// Remember to add all intrinsics here, in librustc_typeck/check/mod.rs, /// and in libcore/intrinsics.rs; if you need access to any llvm intrinsics, @@ -37,12 +30,4 @@ pub trait IntrinsicCallMethods<'tcx>: BackendTypes { fn abort(&mut self); fn assume(&mut self, val: Self::Value); fn expect(&mut self, cond: Self::Value, expected: bool) -> Self::Value; - - fn call_overflow_intrinsic( - &mut self, - oop: OverflowOp, - ty: Ty, - lhs: Self::Value, - rhs: Self::Value, - ) -> (Self::Value, Self::Value); } diff --git a/src/librustc_codegen_ssa/traits/mod.rs b/src/librustc_codegen_ssa/traits/mod.rs index 0f1fc11fd0d0e..83ce28b6f8aa3 100644 --- a/src/librustc_codegen_ssa/traits/mod.rs +++ b/src/librustc_codegen_ssa/traits/mod.rs @@ -40,11 +40,11 @@ mod write; pub use self::abi::{AbiBuilderMethods, AbiMethods}; pub use self::asm::{AsmBuilderMethods, AsmMethods}; pub use self::backend::{Backend, BackendTypes, ExtraBackendMethods}; -pub use self::builder::BuilderMethods; +pub use self::builder::{BuilderMethods, OverflowOp}; pub use self::consts::ConstMethods; pub use self::debuginfo::{DebugInfoBuilderMethods, DebugInfoMethods}; pub use self::declare::{DeclareMethods, PreDefineMethods}; -pub use self::intrinsic::{IntrinsicCallMethods, OverflowOp}; +pub use self::intrinsic::IntrinsicCallMethods; pub use self::misc::MiscMethods; pub use self::statics::StaticMethods; pub use self::type_::{