make small (<= size_of::<int>()) tuples immediate
fn foo() -> (u32, u8, u8, u8, u8) { (4, 5, 6, 7, 8) } Before: ; Function Attrs: nounwind uwtable define void @_ZN3foo18hbb616262f874f8daf4v0.0E({ i32, i8, i8, i8, i8 }* noalias nocapture sret, { i64, %tydesc*, i8*, i8*, i8 }* nocapture readnone) #0 { "function top level": %2 = getelementptr inbounds { i32, i8, i8, i8, i8 }* %0, i64 0, i32 0 store i32 4, i32* %2, align 4 %3 = getelementptr inbounds { i32, i8, i8, i8, i8 }* %0, i64 0, i32 1 store i8 5, i8* %3, align 4 %4 = getelementptr inbounds { i32, i8, i8, i8, i8 }* %0, i64 0, i32 2 store i8 6, i8* %4, align 1 %5 = getelementptr inbounds { i32, i8, i8, i8, i8 }* %0, i64 0, i32 3 store i8 7, i8* %5, align 2 %6 = getelementptr inbounds { i32, i8, i8, i8, i8 }* %0, i64 0, i32 4 store i8 8, i8* %6, align 1 ret void } After: ; Function Attrs: nounwind readnone uwtable define { i32, i8, i8, i8, i8 } @_ZN3foo18hbb616262f874f8daf4v0.0E({ i64, %tydesc*, i8*, i8*, i8 }* nocapture readnone) #0 { "function top level": ret { i32, i8, i8, i8, i8 } { i32 4, i8 5, i8 6, i8 7, i8 8 } }
This commit is contained in:
parent
1dbc467fd9
commit
5e4ae4f45f
@ -236,7 +236,7 @@ pub fn decl_rust_fn(ccx: &mut CrateContext, inputs: &[ty::t], output: ty::t,
|
||||
_ => ()
|
||||
}
|
||||
|
||||
let uses_outptr = type_of::return_uses_outptr(ccx.tcx, output);
|
||||
let uses_outptr = type_of::return_uses_outptr(ccx, output);
|
||||
let offset = if uses_outptr { 2 } else { 1 };
|
||||
|
||||
for (i, &arg_ty) in inputs.iter().enumerate() {
|
||||
@ -1121,13 +1121,13 @@ pub fn do_spill_noroot(cx: @mut Block, v: ValueRef) -> ValueRef {
|
||||
|
||||
pub fn spill_if_immediate(cx: @mut Block, v: ValueRef, t: ty::t) -> ValueRef {
|
||||
let _icx = push_ctxt("spill_if_immediate");
|
||||
if type_is_immediate(cx.tcx(), t) { return do_spill(cx, v, t); }
|
||||
if type_is_immediate(cx.ccx(), t) { return do_spill(cx, v, t); }
|
||||
return v;
|
||||
}
|
||||
|
||||
pub fn load_if_immediate(cx: @mut Block, v: ValueRef, t: ty::t) -> ValueRef {
|
||||
let _icx = push_ctxt("load_if_immediate");
|
||||
if type_is_immediate(cx.tcx(), t) { return Load(cx, v); }
|
||||
if type_is_immediate(cx.ccx(), t) { return Load(cx, v); }
|
||||
return v;
|
||||
}
|
||||
|
||||
@ -1660,7 +1660,7 @@ pub fn mk_return_basic_block(llfn: ValueRef) -> BasicBlockRef {
|
||||
// slot where the return value of the function must go.
|
||||
pub fn make_return_pointer(fcx: @mut FunctionContext, output_type: ty::t) -> ValueRef {
|
||||
unsafe {
|
||||
if type_of::return_uses_outptr(fcx.ccx.tcx, output_type) {
|
||||
if type_of::return_uses_outptr(fcx.ccx, output_type) {
|
||||
llvm::LLVMGetParam(fcx.llfn, 0)
|
||||
} else {
|
||||
let lloutputtype = type_of::type_of(fcx.ccx, output_type);
|
||||
@ -1700,7 +1700,7 @@ pub fn new_fn_ctxt_w_id(ccx: @mut CrateContext,
|
||||
ty::subst_tps(ccx.tcx, substs.tys, substs.self_ty, output_type)
|
||||
}
|
||||
};
|
||||
let uses_outptr = type_of::return_uses_outptr(ccx.tcx, substd_output_type);
|
||||
let uses_outptr = type_of::return_uses_outptr(ccx, substd_output_type);
|
||||
let debug_context = debuginfo::create_function_debug_context(ccx, id, param_substs, llfndecl);
|
||||
|
||||
let fcx = @mut FunctionContext {
|
||||
@ -1812,7 +1812,7 @@ pub fn copy_args_to_allocas(fcx: @mut FunctionContext,
|
||||
match fcx.llself {
|
||||
Some(slf) => {
|
||||
let self_val = if slf.is_copy
|
||||
&& datum::appropriate_mode(bcx.tcx(), slf.t).is_by_value() {
|
||||
&& datum::appropriate_mode(bcx.ccx(), slf.t).is_by_value() {
|
||||
let tmp = BitCast(bcx, slf.v, type_of(bcx.ccx(), slf.t));
|
||||
let alloc = alloc_ty(bcx, slf.t, "__self");
|
||||
Store(bcx, tmp, alloc);
|
||||
@ -1842,7 +1842,7 @@ pub fn copy_args_to_allocas(fcx: @mut FunctionContext,
|
||||
// This alloca should be optimized away by LLVM's mem-to-reg pass in
|
||||
// the event it's not truly needed.
|
||||
// only by value if immediate:
|
||||
let llarg = if datum::appropriate_mode(bcx.tcx(), arg_ty).is_by_value() {
|
||||
let llarg = if datum::appropriate_mode(bcx.ccx(), arg_ty).is_by_value() {
|
||||
let alloc = alloc_ty(bcx, arg_ty, "__arg");
|
||||
Store(bcx, raw_llarg, alloc);
|
||||
alloc
|
||||
|
@ -655,7 +655,7 @@ pub fn trans_call_inner(in_cx: @mut Block,
|
||||
// not care about the result, just make a stack slot.
|
||||
let opt_llretslot = match dest {
|
||||
None => {
|
||||
assert!(!type_of::return_uses_outptr(in_cx.tcx(), ret_ty));
|
||||
assert!(!type_of::return_uses_outptr(in_cx.ccx(), ret_ty));
|
||||
None
|
||||
}
|
||||
Some(expr::SaveIn(dst)) => Some(dst),
|
||||
@ -685,7 +685,7 @@ pub fn trans_call_inner(in_cx: @mut Block,
|
||||
|
||||
// Push the out-pointer if we use an out-pointer for this
|
||||
// return type, otherwise push "undef".
|
||||
if type_of::return_uses_outptr(in_cx.tcx(), ret_ty) {
|
||||
if type_of::return_uses_outptr(in_cx.ccx(), ret_ty) {
|
||||
llargs.push(opt_llretslot.unwrap());
|
||||
}
|
||||
|
||||
@ -711,7 +711,7 @@ pub fn trans_call_inner(in_cx: @mut Block,
|
||||
// any attributes with ABI implications directly to the call instruction. Right now, the
|
||||
// only attribute we need to worry about is `sret`.
|
||||
let mut attrs = ~[];
|
||||
if type_of::return_uses_outptr(in_cx.tcx(), ret_ty) {
|
||||
if type_of::return_uses_outptr(in_cx.ccx(), ret_ty) {
|
||||
attrs.push((1, StructRetAttribute));
|
||||
}
|
||||
|
||||
@ -734,7 +734,7 @@ pub fn trans_call_inner(in_cx: @mut Block,
|
||||
// the return value, copy it into llretslot.
|
||||
match opt_llretslot {
|
||||
Some(llretslot) => {
|
||||
if !type_of::return_uses_outptr(bcx.tcx(), ret_ty) &&
|
||||
if !type_of::return_uses_outptr(bcx.ccx(), ret_ty) &&
|
||||
!ty::type_is_voidish(ret_ty)
|
||||
{
|
||||
Store(bcx, llret, llretslot);
|
||||
@ -758,7 +758,7 @@ pub fn trans_call_inner(in_cx: @mut Block,
|
||||
// drop the temporary slot we made.
|
||||
match dest {
|
||||
None => {
|
||||
assert!(!type_of::return_uses_outptr(bcx.tcx(), ret_ty));
|
||||
assert!(!type_of::return_uses_outptr(bcx.ccx(), ret_ty));
|
||||
}
|
||||
Some(expr::Ignore) => {
|
||||
// drop the value if it is not being saved.
|
||||
@ -871,7 +871,7 @@ pub fn trans_arg_expr(bcx: @mut Block,
|
||||
DontAutorefArg => {
|
||||
let need_scratch = ty::type_needs_drop(bcx.tcx(), arg_datum.ty) ||
|
||||
(bcx.expr_is_lval(arg_expr) &&
|
||||
arg_datum.appropriate_mode(bcx.tcx()).is_by_ref());
|
||||
arg_datum.appropriate_mode(bcx.ccx()).is_by_ref());
|
||||
|
||||
let arg_datum = if need_scratch {
|
||||
let scratch = scratch_datum(bcx, arg_datum.ty, "__self", false);
|
||||
|
@ -46,23 +46,37 @@
|
||||
|
||||
pub use middle::trans::context::CrateContext;
|
||||
|
||||
fn type_is_newtype_immediate(cx: ty::ctxt, ty: ty::t) -> bool {
|
||||
fn type_is_newtype_immediate(ccx: &mut CrateContext, ty: ty::t) -> bool {
|
||||
match ty::get(ty).sty {
|
||||
ty::ty_struct(def_id, ref substs) => {
|
||||
let fields = ty::struct_fields(cx, def_id, substs);
|
||||
let fields = ty::struct_fields(ccx.tcx, def_id, substs);
|
||||
fields.len() == 1 &&
|
||||
fields[0].ident.name == token::special_idents::unnamed_field.name &&
|
||||
type_is_immediate(cx, fields[0].mt.ty)
|
||||
type_is_immediate(ccx, fields[0].mt.ty)
|
||||
}
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
|
||||
pub fn type_is_immediate(cx: ty::ctxt, ty: ty::t) -> bool {
|
||||
ty::type_is_scalar(ty) || ty::type_is_boxed(ty) ||
|
||||
pub fn type_is_immediate(ccx: &mut CrateContext, ty: ty::t) -> bool {
|
||||
use middle::trans::machine::llsize_of_alloc;
|
||||
use middle::trans::type_of::sizing_type_of;
|
||||
let tcx = ccx.tcx;
|
||||
let simple = ty::type_is_scalar(ty) || ty::type_is_boxed(ty) ||
|
||||
ty::type_is_unique(ty) || ty::type_is_region_ptr(ty) ||
|
||||
type_is_newtype_immediate(cx, ty) ||
|
||||
ty::type_is_simd(cx, ty)
|
||||
type_is_newtype_immediate(ccx, ty) ||
|
||||
ty::type_is_simd(tcx, ty);
|
||||
if simple {
|
||||
return true;
|
||||
}
|
||||
match ty::get(ty).sty {
|
||||
// FIXME: #9651: small `ty_struct` and `ty_enum` should also be immediate
|
||||
ty::ty_tup(*) => {
|
||||
let llty = sizing_type_of(ccx, ty);
|
||||
llsize_of_alloc(ccx, llty) <= llsize_of_alloc(ccx, ccx.int_type)
|
||||
}
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
|
||||
pub fn gensym_name(name: &str) -> (Ident, path_elt) {
|
||||
|
@ -188,7 +188,7 @@ pub fn scratch_datum(bcx: @mut Block, ty: ty::t, name: &str, zero: bool) -> Datu
|
||||
Datum { val: scratch, ty: ty, mode: ByRef(RevokeClean) }
|
||||
}
|
||||
|
||||
pub fn appropriate_mode(tcx: ty::ctxt, ty: ty::t) -> DatumMode {
|
||||
pub fn appropriate_mode(ccx: &mut CrateContext, ty: ty::t) -> DatumMode {
|
||||
/*!
|
||||
* Indicates the "appropriate" mode for this value,
|
||||
* which is either by ref or by value, depending
|
||||
@ -197,7 +197,7 @@ pub fn appropriate_mode(tcx: ty::ctxt, ty: ty::t) -> DatumMode {
|
||||
|
||||
if ty::type_is_voidish(ty) {
|
||||
ByValue
|
||||
} else if type_is_immediate(tcx, ty) {
|
||||
} else if type_is_immediate(ccx, ty) {
|
||||
ByValue
|
||||
} else {
|
||||
ByRef(RevokeClean)
|
||||
@ -505,10 +505,10 @@ pub fn to_zeroable_ref_llval(&self, bcx: @mut Block) -> ValueRef {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn appropriate_mode(&self, tcx: ty::ctxt) -> DatumMode {
|
||||
pub fn appropriate_mode(&self, ccx: &mut CrateContext) -> DatumMode {
|
||||
/*! See the `appropriate_mode()` function */
|
||||
|
||||
appropriate_mode(tcx, self.ty)
|
||||
appropriate_mode(ccx, self.ty)
|
||||
}
|
||||
|
||||
pub fn to_appropriate_llval(&self, bcx: @mut Block) -> ValueRef {
|
||||
@ -516,7 +516,7 @@ pub fn to_appropriate_llval(&self, bcx: @mut Block) -> ValueRef {
|
||||
*
|
||||
* Yields an llvalue with the `appropriate_mode()`. */
|
||||
|
||||
match self.appropriate_mode(bcx.tcx()) {
|
||||
match self.appropriate_mode(bcx.ccx()) {
|
||||
ByValue => self.to_value_llval(bcx),
|
||||
ByRef(_) => self.to_ref_llval(bcx)
|
||||
}
|
||||
@ -527,7 +527,7 @@ pub fn to_appropriate_datum(&self, bcx: @mut Block) -> Datum {
|
||||
*
|
||||
* Yields a datum with the `appropriate_mode()`. */
|
||||
|
||||
match self.appropriate_mode(bcx.tcx()) {
|
||||
match self.appropriate_mode(bcx.ccx()) {
|
||||
ByValue => self.to_value_datum(bcx),
|
||||
ByRef(_) => self.to_ref_datum(bcx)
|
||||
}
|
||||
@ -667,7 +667,7 @@ pub fn try_deref(&self,
|
||||
ByValue => {
|
||||
// Actually, this case cannot happen right
|
||||
// now, because enums are never immediate.
|
||||
assert!(type_is_immediate(bcx.tcx(), ty));
|
||||
assert!(type_is_immediate(bcx.ccx(), ty));
|
||||
(Some(Datum {ty: ty, ..*self}), bcx)
|
||||
}
|
||||
};
|
||||
@ -699,7 +699,7 @@ pub fn try_deref(&self,
|
||||
)
|
||||
}
|
||||
ByValue => {
|
||||
assert!(type_is_immediate(bcx.tcx(), ty));
|
||||
assert!(type_is_immediate(bcx.ccx(), ty));
|
||||
(
|
||||
Some(Datum {
|
||||
val: ExtractValue(bcx, self.val, 0),
|
||||
|
@ -290,7 +290,7 @@ fn add_env(bcx: @mut Block, expr: &ast::Expr, datum: Datum) -> DatumBlock {
|
||||
debug!("add_env(closure_ty=%s)", closure_ty.repr(tcx));
|
||||
let scratch = scratch_datum(bcx, closure_ty, "__adjust", false);
|
||||
let llfn = GEPi(bcx, scratch.val, [0u, abi::fn_field_code]);
|
||||
assert_eq!(datum.appropriate_mode(tcx), ByValue);
|
||||
assert_eq!(datum.appropriate_mode(bcx.ccx()), ByValue);
|
||||
Store(bcx, datum.to_appropriate_llval(bcx), llfn);
|
||||
let llenv = GEPi(bcx, scratch.val, [0u, abi::fn_field_box]);
|
||||
Store(bcx, base::null_env_ptr(bcx.ccx()), llenv);
|
||||
|
@ -492,7 +492,7 @@ unsafe fn build_wrap_fn(ccx: @mut CrateContext,
|
||||
|
||||
// Push Rust return pointer, using null if it will be unused.
|
||||
let rust_uses_outptr =
|
||||
type_of::return_uses_outptr(tcx, tys.fn_sig.output);
|
||||
type_of::return_uses_outptr(ccx, tys.fn_sig.output);
|
||||
let return_alloca: Option<ValueRef>;
|
||||
let llrust_ret_ty = tys.llsig.llret_ty;
|
||||
let llrust_retptr_ty = llrust_ret_ty.ptr_to();
|
||||
@ -702,7 +702,7 @@ fn foreign_signature(ccx: &mut CrateContext, fn_sig: &ty::FnSig)
|
||||
LlvmSignature {
|
||||
llarg_tys: llarg_tys,
|
||||
llret_ty: llret_ty,
|
||||
sret: type_of::return_uses_outptr(ccx.tcx, fn_sig.output),
|
||||
sret: type_of::return_uses_outptr(ccx, fn_sig.output),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -53,7 +53,7 @@ fn simple_llvm_intrinsic(bcx: @mut Block, name: &'static str, num_args: uint) {
|
||||
Ret(bcx, llcall);
|
||||
}
|
||||
|
||||
fn with_overflow_instrinsic(bcx: @mut Block, name: &'static str) {
|
||||
fn with_overflow_instrinsic(bcx: @mut Block, name: &'static str, t: ty::t) {
|
||||
let first_real_arg = bcx.fcx.arg_pos(0u);
|
||||
let a = get_param(bcx.fcx.llfn, first_real_arg);
|
||||
let b = get_param(bcx.fcx.llfn, first_real_arg + 1);
|
||||
@ -63,12 +63,17 @@ fn with_overflow_instrinsic(bcx: @mut Block, name: &'static str) {
|
||||
let val = Call(bcx, llfn, [a, b], []);
|
||||
let result = ExtractValue(bcx, val, 0);
|
||||
let overflow = ZExt(bcx, ExtractValue(bcx, val, 1), Type::bool());
|
||||
let retptr = get_param(bcx.fcx.llfn, bcx.fcx.out_arg_pos());
|
||||
let ret = Load(bcx, retptr);
|
||||
let ret = Load(bcx, Alloca(bcx, type_of::type_of(bcx.ccx(), t), ""));
|
||||
let ret = InsertValue(bcx, ret, result, 0);
|
||||
let ret = InsertValue(bcx, ret, overflow, 1);
|
||||
Store(bcx, ret, retptr);
|
||||
RetVoid(bcx)
|
||||
|
||||
if type_is_immediate(bcx.ccx(), t) {
|
||||
Ret(bcx, ret);
|
||||
} else {
|
||||
let retptr = get_param(bcx.fcx.llfn, bcx.fcx.out_arg_pos());
|
||||
Store(bcx, ret, retptr);
|
||||
RetVoid(bcx);
|
||||
}
|
||||
}
|
||||
|
||||
fn memcpy_intrinsic(bcx: @mut Block, name: &'static str, tp_ty: ty::t, sizebits: u8) {
|
||||
@ -227,7 +232,7 @@ fn count_zeros_intrinsic(bcx: @mut Block, name: &'static str) {
|
||||
// intrinsics, there are no argument cleanups to
|
||||
// concern ourselves with.
|
||||
let tp_ty = substs.tys[0];
|
||||
let mode = appropriate_mode(ccx.tcx, tp_ty);
|
||||
let mode = appropriate_mode(ccx, tp_ty);
|
||||
let src = Datum {val: get_param(decl, first_real_arg + 1u),
|
||||
ty: tp_ty, mode: mode};
|
||||
bcx = src.move_to(bcx, DROP_EXISTING,
|
||||
@ -237,7 +242,7 @@ fn count_zeros_intrinsic(bcx: @mut Block, name: &'static str) {
|
||||
"move_val_init" => {
|
||||
// See comments for `"move_val"`.
|
||||
let tp_ty = substs.tys[0];
|
||||
let mode = appropriate_mode(ccx.tcx, tp_ty);
|
||||
let mode = appropriate_mode(ccx, tp_ty);
|
||||
let src = Datum {val: get_param(decl, first_real_arg + 1u),
|
||||
ty: tp_ty, mode: mode};
|
||||
bcx = src.move_to(bcx, INIT, get_param(decl, first_real_arg));
|
||||
@ -278,7 +283,7 @@ fn count_zeros_intrinsic(bcx: @mut Block, name: &'static str) {
|
||||
"uninit" => {
|
||||
// Do nothing, this is effectively a no-op
|
||||
let retty = substs.tys[0];
|
||||
if type_is_immediate(ccx.tcx, retty) && !ty::type_is_nil(retty) {
|
||||
if type_is_immediate(ccx, retty) && !ty::type_is_nil(retty) {
|
||||
unsafe {
|
||||
Ret(bcx, lib::llvm::llvm::LLVMGetUndef(type_of(ccx, retty).to_ref()));
|
||||
}
|
||||
@ -316,7 +321,7 @@ fn count_zeros_intrinsic(bcx: @mut Block, name: &'static str) {
|
||||
|
||||
if !ty::type_is_voidish(out_type) {
|
||||
let llsrcval = get_param(decl, first_real_arg);
|
||||
if type_is_immediate(ccx.tcx, in_type) {
|
||||
if type_is_immediate(ccx, in_type) {
|
||||
match fcx.llretptr {
|
||||
Some(llretptr) => {
|
||||
Store(bcx, llsrcval, PointerCast(bcx, llretptr, llintype.ptr_to()));
|
||||
@ -335,7 +340,7 @@ fn count_zeros_intrinsic(bcx: @mut Block, name: &'static str) {
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if type_is_immediate(ccx.tcx, out_type) {
|
||||
} else if type_is_immediate(ccx, out_type) {
|
||||
let llsrcptr = PointerCast(bcx, llsrcval, llouttype.ptr_to());
|
||||
let ll_load = Load(bcx, llsrcptr);
|
||||
Ret(bcx, ll_load);
|
||||
@ -466,35 +471,59 @@ fn count_zeros_intrinsic(bcx: @mut Block, name: &'static str) {
|
||||
"bswap32" => simple_llvm_intrinsic(bcx, "llvm.bswap.i32", 1),
|
||||
"bswap64" => simple_llvm_intrinsic(bcx, "llvm.bswap.i64", 1),
|
||||
|
||||
"i8_add_with_overflow" => with_overflow_instrinsic(bcx, "llvm.sadd.with.overflow.i8"),
|
||||
"i16_add_with_overflow" => with_overflow_instrinsic(bcx, "llvm.sadd.with.overflow.i16"),
|
||||
"i32_add_with_overflow" => with_overflow_instrinsic(bcx, "llvm.sadd.with.overflow.i32"),
|
||||
"i64_add_with_overflow" => with_overflow_instrinsic(bcx, "llvm.sadd.with.overflow.i64"),
|
||||
"i8_add_with_overflow" =>
|
||||
with_overflow_instrinsic(bcx, "llvm.sadd.with.overflow.i8", output_type),
|
||||
"i16_add_with_overflow" =>
|
||||
with_overflow_instrinsic(bcx, "llvm.sadd.with.overflow.i16", output_type),
|
||||
"i32_add_with_overflow" =>
|
||||
with_overflow_instrinsic(bcx, "llvm.sadd.with.overflow.i32", output_type),
|
||||
"i64_add_with_overflow" =>
|
||||
with_overflow_instrinsic(bcx, "llvm.sadd.with.overflow.i64", output_type),
|
||||
|
||||
"u8_add_with_overflow" => with_overflow_instrinsic(bcx, "llvm.uadd.with.overflow.i8"),
|
||||
"u16_add_with_overflow" => with_overflow_instrinsic(bcx, "llvm.uadd.with.overflow.i16"),
|
||||
"u32_add_with_overflow" => with_overflow_instrinsic(bcx, "llvm.uadd.with.overflow.i32"),
|
||||
"u64_add_with_overflow" => with_overflow_instrinsic(bcx, "llvm.uadd.with.overflow.i64"),
|
||||
"u8_add_with_overflow" =>
|
||||
with_overflow_instrinsic(bcx, "llvm.uadd.with.overflow.i8", output_type),
|
||||
"u16_add_with_overflow" =>
|
||||
with_overflow_instrinsic(bcx, "llvm.uadd.with.overflow.i16", output_type),
|
||||
"u32_add_with_overflow" =>
|
||||
with_overflow_instrinsic(bcx, "llvm.uadd.with.overflow.i32", output_type),
|
||||
"u64_add_with_overflow" =>
|
||||
with_overflow_instrinsic(bcx, "llvm.uadd.with.overflow.i64", output_type),
|
||||
|
||||
"i8_sub_with_overflow" => with_overflow_instrinsic(bcx, "llvm.ssub.with.overflow.i8"),
|
||||
"i16_sub_with_overflow" => with_overflow_instrinsic(bcx, "llvm.ssub.with.overflow.i16"),
|
||||
"i32_sub_with_overflow" => with_overflow_instrinsic(bcx, "llvm.ssub.with.overflow.i32"),
|
||||
"i64_sub_with_overflow" => with_overflow_instrinsic(bcx, "llvm.ssub.with.overflow.i64"),
|
||||
"i8_sub_with_overflow" =>
|
||||
with_overflow_instrinsic(bcx, "llvm.ssub.with.overflow.i8", output_type),
|
||||
"i16_sub_with_overflow" =>
|
||||
with_overflow_instrinsic(bcx, "llvm.ssub.with.overflow.i16", output_type),
|
||||
"i32_sub_with_overflow" =>
|
||||
with_overflow_instrinsic(bcx, "llvm.ssub.with.overflow.i32", output_type),
|
||||
"i64_sub_with_overflow" =>
|
||||
with_overflow_instrinsic(bcx, "llvm.ssub.with.overflow.i64", output_type),
|
||||
|
||||
"u8_sub_with_overflow" => with_overflow_instrinsic(bcx, "llvm.usub.with.overflow.i8"),
|
||||
"u16_sub_with_overflow" => with_overflow_instrinsic(bcx, "llvm.usub.with.overflow.i16"),
|
||||
"u32_sub_with_overflow" => with_overflow_instrinsic(bcx, "llvm.usub.with.overflow.i32"),
|
||||
"u64_sub_with_overflow" => with_overflow_instrinsic(bcx, "llvm.usub.with.overflow.i64"),
|
||||
"u8_sub_with_overflow" =>
|
||||
with_overflow_instrinsic(bcx, "llvm.usub.with.overflow.i8", output_type),
|
||||
"u16_sub_with_overflow" =>
|
||||
with_overflow_instrinsic(bcx, "llvm.usub.with.overflow.i16", output_type),
|
||||
"u32_sub_with_overflow" =>
|
||||
with_overflow_instrinsic(bcx, "llvm.usub.with.overflow.i32", output_type),
|
||||
"u64_sub_with_overflow" =>
|
||||
with_overflow_instrinsic(bcx, "llvm.usub.with.overflow.i64", output_type),
|
||||
|
||||
"i8_mul_with_overflow" => with_overflow_instrinsic(bcx, "llvm.smul.with.overflow.i8"),
|
||||
"i16_mul_with_overflow" => with_overflow_instrinsic(bcx, "llvm.smul.with.overflow.i16"),
|
||||
"i32_mul_with_overflow" => with_overflow_instrinsic(bcx, "llvm.smul.with.overflow.i32"),
|
||||
"i64_mul_with_overflow" => with_overflow_instrinsic(bcx, "llvm.smul.with.overflow.i64"),
|
||||
"i8_mul_with_overflow" =>
|
||||
with_overflow_instrinsic(bcx, "llvm.smul.with.overflow.i8", output_type),
|
||||
"i16_mul_with_overflow" =>
|
||||
with_overflow_instrinsic(bcx, "llvm.smul.with.overflow.i16", output_type),
|
||||
"i32_mul_with_overflow" =>
|
||||
with_overflow_instrinsic(bcx, "llvm.smul.with.overflow.i32", output_type),
|
||||
"i64_mul_with_overflow" =>
|
||||
with_overflow_instrinsic(bcx, "llvm.smul.with.overflow.i64", output_type),
|
||||
|
||||
"u8_mul_with_overflow" => with_overflow_instrinsic(bcx, "llvm.umul.with.overflow.i8"),
|
||||
"u16_mul_with_overflow" => with_overflow_instrinsic(bcx, "llvm.umul.with.overflow.i16"),
|
||||
"u32_mul_with_overflow" => with_overflow_instrinsic(bcx, "llvm.umul.with.overflow.i32"),
|
||||
"u64_mul_with_overflow" => with_overflow_instrinsic(bcx, "llvm.umul.with.overflow.i64"),
|
||||
"u8_mul_with_overflow" =>
|
||||
with_overflow_instrinsic(bcx, "llvm.umul.with.overflow.i8", output_type),
|
||||
"u16_mul_with_overflow" =>
|
||||
with_overflow_instrinsic(bcx, "llvm.umul.with.overflow.i16", output_type),
|
||||
"u32_mul_with_overflow" =>
|
||||
with_overflow_instrinsic(bcx, "llvm.umul.with.overflow.i32", output_type),
|
||||
"u64_mul_with_overflow" =>
|
||||
with_overflow_instrinsic(bcx, "llvm.umul.with.overflow.i64", output_type),
|
||||
|
||||
_ => {
|
||||
// Could we make this an enum rather than a string? does it get
|
||||
|
@ -20,12 +20,12 @@
|
||||
use syntax::ast;
|
||||
use syntax::opt_vec;
|
||||
|
||||
pub fn arg_is_indirect(ccx: &CrateContext, arg_ty: ty::t) -> bool {
|
||||
!type_is_immediate(ccx.tcx, arg_ty)
|
||||
pub fn arg_is_indirect(ccx: &mut CrateContext, arg_ty: ty::t) -> bool {
|
||||
!type_is_immediate(ccx, arg_ty)
|
||||
}
|
||||
|
||||
pub fn return_uses_outptr(tcx: ty::ctxt, ty: ty::t) -> bool {
|
||||
!type_is_immediate(tcx, ty)
|
||||
pub fn return_uses_outptr(ccx: &mut CrateContext, ty: ty::t) -> bool {
|
||||
!type_is_immediate(ccx, ty)
|
||||
}
|
||||
|
||||
pub fn type_of_explicit_arg(ccx: &mut CrateContext, arg_ty: ty::t) -> Type {
|
||||
@ -49,7 +49,7 @@ pub fn type_of_rust_fn(cx: &mut CrateContext,
|
||||
|
||||
// Arg 0: Output pointer.
|
||||
// (if the output type is non-immediate)
|
||||
let use_out_pointer = return_uses_outptr(cx.tcx, output);
|
||||
let use_out_pointer = return_uses_outptr(cx, output);
|
||||
let lloutputtype = type_of(cx, output);
|
||||
if use_out_pointer {
|
||||
atys.push(lloutputtype.ptr_to());
|
||||
|
Loading…
Reference in New Issue
Block a user