Move IntrinsicCallMethods::call_overflow_intrinsics to BuilderMethods::checked_binop
This commit is contained in:
parent
9a9045573f
commit
2d4c96d1b1
@ -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 {
|
||||
|
@ -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(
|
||||
|
@ -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);
|
||||
|
@ -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(
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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_::{
|
||||
|
Loading…
x
Reference in New Issue
Block a user