Don't use llvm intrinsic names in cg_ssa
This commit is contained in:
parent
8698f5c43d
commit
15a5009af0
9 changed files with 113 additions and 108 deletions
|
@ -470,8 +470,8 @@ impl MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
impl IntrinsicDeclarationMethods<'tcx> for CodegenCx<'b, 'tcx> {
|
||||
fn get_intrinsic(&self, key: &str) -> &'b Value {
|
||||
impl CodegenCx<'b, 'tcx> {
|
||||
crate fn get_intrinsic(&self, key: &str) -> &'b Value {
|
||||
if let Some(v) = self.intrinsics.borrow().get(key).cloned() {
|
||||
return v;
|
||||
}
|
||||
|
|
|
@ -763,6 +763,95 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn abort(&mut self) {
|
||||
let fnname = self.cx().get_intrinsic(&("llvm.trap"));
|
||||
self.call(fnname, &[], None);
|
||||
}
|
||||
|
||||
fn assume(&mut self, val: Self::Value) {
|
||||
let assume_intrinsic = self.cx().get_intrinsic("llvm.assume");
|
||||
self.call(assume_intrinsic, &[val], None);
|
||||
}
|
||||
|
||||
fn expect(&mut self, cond: Self::Value, expected: bool) -> Self::Value {
|
||||
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(
|
||||
|
|
|
@ -366,14 +366,6 @@ pub fn wants_msvc_seh(sess: &Session) -> bool {
|
|||
sess.target.target.options.is_like_msvc
|
||||
}
|
||||
|
||||
pub fn call_assume<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
|
||||
bx: &mut Bx,
|
||||
val: Bx::Value
|
||||
) {
|
||||
let assume_intrinsic = bx.cx().get_intrinsic("llvm.assume");
|
||||
bx.call(assume_intrinsic, &[val], None);
|
||||
}
|
||||
|
||||
pub fn from_immediate<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
|
||||
bx: &mut Bx,
|
||||
val: Bx::Value
|
||||
|
|
|
@ -195,9 +195,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
}
|
||||
|
||||
mir::TerminatorKind::Abort => {
|
||||
// Call core::intrinsics::abort()
|
||||
let fnname = bx.cx().get_intrinsic(&("llvm.trap"));
|
||||
bx.call(fnname, &[], None);
|
||||
bx.abort();
|
||||
bx.unreachable();
|
||||
}
|
||||
|
||||
|
@ -364,8 +362,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
}
|
||||
|
||||
// Pass the condition through llvm.expect for branch hinting.
|
||||
let expect = bx.cx().get_intrinsic(&"llvm.expect.i1");
|
||||
let cond = bx.call(expect, &[cond, bx.cx().const_bool(expected)], None);
|
||||
let cond = bx.expect(cond, expected);
|
||||
|
||||
// Create the failure block and the conditional branch to it.
|
||||
let lltarget = llblock(self, target);
|
||||
|
|
|
@ -484,8 +484,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
}
|
||||
// Allow RalfJ to sleep soundly knowing that even refactorings that remove
|
||||
// the above error (or silence it under some conditions) will not cause UB
|
||||
let fnname = bx.cx().get_intrinsic(&("llvm.trap"));
|
||||
bx.call(fnname, &[], None);
|
||||
bx.abort();
|
||||
// We've errored, so we don't have to produce working code.
|
||||
let layout = bx.cx().layout_of(ty);
|
||||
bx.load_operand(PlaceRef::new_sized(
|
||||
|
|
|
@ -413,8 +413,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
// and compile-time agree on values
|
||||
// With floats that won't always be true
|
||||
// so we generate an abort
|
||||
let fnname = bx.cx().get_intrinsic(&("llvm.trap"));
|
||||
bx.call(fnname, &[], None);
|
||||
bx.abort();
|
||||
let llval = bx.cx().const_undef(
|
||||
bx.cx().type_ptr_to(bx.cx().backend_type(layout))
|
||||
);
|
||||
|
|
|
@ -337,7 +337,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
llval,
|
||||
ll_t_in_const
|
||||
);
|
||||
base::call_assume(&mut bx, cmp);
|
||||
bx.assume(cmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -693,11 +693,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
mir::BinOp::Mul => OverflowOp::Mul,
|
||||
_ => unreachable!()
|
||||
};
|
||||
let intrinsic = get_overflow_intrinsic(oop, bx, input_ty);
|
||||
let res = bx.call(intrinsic, &[lhs, rhs], None);
|
||||
|
||||
(bx.extract_value(res, 0),
|
||||
bx.extract_value(res, 1))
|
||||
bx.call_overflow_intrinsic(oop, input_ty, lhs, rhs)
|
||||
}
|
||||
mir::BinOp::Shl | mir::BinOp::Shr => {
|
||||
let lhs_llty = bx.cx().val_ty(lhs);
|
||||
|
@ -744,80 +740,6 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
enum OverflowOp {
|
||||
Add, Sub, Mul
|
||||
}
|
||||
|
||||
fn get_overflow_intrinsic<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
|
||||
oop: OverflowOp,
|
||||
bx: &mut Bx,
|
||||
ty: Ty
|
||||
) -> Bx::Value {
|
||||
use syntax::ast::IntTy::*;
|
||||
use syntax::ast::UintTy::*;
|
||||
use rustc::ty::{Int, Uint};
|
||||
|
||||
let tcx = bx.tcx();
|
||||
|
||||
let new_sty = match ty.sty {
|
||||
Int(Isize) => Int(tcx.sess.target.isize_ty),
|
||||
Uint(Usize) => Uint(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!(),
|
||||
},
|
||||
};
|
||||
|
||||
bx.cx().get_intrinsic(&name)
|
||||
}
|
||||
|
||||
fn cast_int_to_float<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
|
||||
bx: &mut Bx,
|
||||
signed: bool,
|
||||
|
|
|
@ -8,13 +8,17 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use super::Backend;
|
||||
use super::HasCodegen;
|
||||
use mir::operand::OperandRef;
|
||||
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>: HasCodegen<'tcx> {
|
||||
/// 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,
|
||||
|
@ -27,11 +31,16 @@ pub trait IntrinsicCallMethods<'tcx>: HasCodegen<'tcx> {
|
|||
llresult: Self::Value,
|
||||
span: Span,
|
||||
);
|
||||
}
|
||||
|
||||
pub trait IntrinsicDeclarationMethods<'tcx>: Backend<'tcx> {
|
||||
fn get_intrinsic(&self, key: &str) -> Self::Value;
|
||||
fn abort(&mut self);
|
||||
fn assume(&mut self, val: Self::Value);
|
||||
fn expect(&mut self, cond: Self::Value, expected: bool) -> Self::Value;
|
||||
|
||||
/// Declare any llvm intrinsics that you might need
|
||||
fn declare_intrinsic(&self, key: &str) -> Option<Self::Value>;
|
||||
fn call_overflow_intrinsic(
|
||||
&mut self,
|
||||
oop: OverflowOp,
|
||||
ty: Ty,
|
||||
lhs: Self::Value,
|
||||
rhs: Self::Value,
|
||||
) -> (Self::Value, Self::Value);
|
||||
}
|
||||
|
|
|
@ -44,7 +44,7 @@ pub use self::builder::BuilderMethods;
|
|||
pub use self::consts::ConstMethods;
|
||||
pub use self::debuginfo::{DebugInfoBuilderMethods, DebugInfoMethods};
|
||||
pub use self::declare::{DeclareMethods, PreDefineMethods};
|
||||
pub use self::intrinsic::{IntrinsicCallMethods, IntrinsicDeclarationMethods};
|
||||
pub use self::intrinsic::{IntrinsicCallMethods, OverflowOp};
|
||||
pub use self::misc::MiscMethods;
|
||||
pub use self::statics::StaticMethods;
|
||||
pub use self::type_::{
|
||||
|
@ -65,7 +65,6 @@ pub trait CodegenMethods<'tcx>:
|
|||
+ StaticMethods
|
||||
+ DebugInfoMethods<'tcx>
|
||||
+ AbiMethods<'tcx>
|
||||
+ IntrinsicDeclarationMethods<'tcx>
|
||||
+ DeclareMethods<'tcx>
|
||||
+ AsmMethods<'tcx>
|
||||
+ PreDefineMethods<'tcx>
|
||||
|
@ -80,7 +79,6 @@ impl<'tcx, T> CodegenMethods<'tcx> for T where
|
|||
+ StaticMethods
|
||||
+ DebugInfoMethods<'tcx>
|
||||
+ AbiMethods<'tcx>
|
||||
+ IntrinsicDeclarationMethods<'tcx>
|
||||
+ DeclareMethods<'tcx>
|
||||
+ AsmMethods<'tcx>
|
||||
+ PreDefineMethods<'tcx>
|
||||
|
|
Loading…
Add table
Reference in a new issue