Skip to content

Commit cac9aff

Browse files
committed
auto merge of #8408 : thestinger/rust/checked, r=Aatch
2 parents eebcff1 + 7db605c commit cac9aff

File tree

10 files changed

+665
-8
lines changed

10 files changed

+665
-8
lines changed

src/librustc/middle/trans/base.rs

+54
Original file line numberDiff line numberDiff line change
@@ -2740,6 +2740,60 @@ pub fn declare_intrinsics(llmod: ModuleRef) -> HashMap<&'static str, ValueRef> {
27402740
ifn!("llvm.bswap.i32",[Type::i32()], Type::i32());
27412741
ifn!("llvm.bswap.i64",[Type::i64()], Type::i64());
27422742

2743+
ifn!("llvm.sadd.with.overflow.i8",
2744+
[Type::i8(), Type::i8()], Type::struct_([Type::i8(), Type::i1()], false));
2745+
ifn!("llvm.sadd.with.overflow.i16",
2746+
[Type::i16(), Type::i16()], Type::struct_([Type::i16(), Type::i1()], false));
2747+
ifn!("llvm.sadd.with.overflow.i32",
2748+
[Type::i32(), Type::i32()], Type::struct_([Type::i32(), Type::i1()], false));
2749+
ifn!("llvm.sadd.with.overflow.i64",
2750+
[Type::i64(), Type::i64()], Type::struct_([Type::i64(), Type::i1()], false));
2751+
2752+
ifn!("llvm.uadd.with.overflow.i8",
2753+
[Type::i8(), Type::i8()], Type::struct_([Type::i8(), Type::i1()], false));
2754+
ifn!("llvm.uadd.with.overflow.i16",
2755+
[Type::i16(), Type::i16()], Type::struct_([Type::i16(), Type::i1()], false));
2756+
ifn!("llvm.uadd.with.overflow.i32",
2757+
[Type::i32(), Type::i32()], Type::struct_([Type::i32(), Type::i1()], false));
2758+
ifn!("llvm.uadd.with.overflow.i64",
2759+
[Type::i64(), Type::i64()], Type::struct_([Type::i64(), Type::i1()], false));
2760+
2761+
ifn!("llvm.ssub.with.overflow.i8",
2762+
[Type::i8(), Type::i8()], Type::struct_([Type::i8(), Type::i1()], false));
2763+
ifn!("llvm.ssub.with.overflow.i16",
2764+
[Type::i16(), Type::i16()], Type::struct_([Type::i16(), Type::i1()], false));
2765+
ifn!("llvm.ssub.with.overflow.i32",
2766+
[Type::i32(), Type::i32()], Type::struct_([Type::i32(), Type::i1()], false));
2767+
ifn!("llvm.ssub.with.overflow.i64",
2768+
[Type::i64(), Type::i64()], Type::struct_([Type::i64(), Type::i1()], false));
2769+
2770+
ifn!("llvm.usub.with.overflow.i8",
2771+
[Type::i8(), Type::i8()], Type::struct_([Type::i8(), Type::i1()], false));
2772+
ifn!("llvm.usub.with.overflow.i16",
2773+
[Type::i16(), Type::i16()], Type::struct_([Type::i16(), Type::i1()], false));
2774+
ifn!("llvm.usub.with.overflow.i32",
2775+
[Type::i32(), Type::i32()], Type::struct_([Type::i32(), Type::i1()], false));
2776+
ifn!("llvm.usub.with.overflow.i64",
2777+
[Type::i64(), Type::i64()], Type::struct_([Type::i64(), Type::i1()], false));
2778+
2779+
ifn!("llvm.smul.with.overflow.i8",
2780+
[Type::i8(), Type::i8()], Type::struct_([Type::i8(), Type::i1()], false));
2781+
ifn!("llvm.smul.with.overflow.i16",
2782+
[Type::i16(), Type::i16()], Type::struct_([Type::i16(), Type::i1()], false));
2783+
ifn!("llvm.smul.with.overflow.i32",
2784+
[Type::i32(), Type::i32()], Type::struct_([Type::i32(), Type::i1()], false));
2785+
ifn!("llvm.smul.with.overflow.i64",
2786+
[Type::i64(), Type::i64()], Type::struct_([Type::i64(), Type::i1()], false));
2787+
2788+
ifn!("llvm.umul.with.overflow.i8",
2789+
[Type::i8(), Type::i8()], Type::struct_([Type::i8(), Type::i1()], false));
2790+
ifn!("llvm.umul.with.overflow.i16",
2791+
[Type::i16(), Type::i16()], Type::struct_([Type::i16(), Type::i1()], false));
2792+
ifn!("llvm.umul.with.overflow.i32",
2793+
[Type::i32(), Type::i32()], Type::struct_([Type::i32(), Type::i1()], false));
2794+
ifn!("llvm.umul.with.overflow.i64",
2795+
[Type::i64(), Type::i64()], Type::struct_([Type::i64(), Type::i1()], false));
2796+
27432797
return intrinsics;
27442798
}
27452799

src/librustc/middle/trans/build.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -714,9 +714,11 @@ pub fn ExtractValue(cx: @mut Block, AggVal: ValueRef, Index: uint) -> ValueRef {
714714
}
715715
}
716716

717-
pub fn InsertValue(cx: @mut Block, AggVal: ValueRef, EltVal: ValueRef, Index: uint) {
718-
if cx.unreachable { return; }
719-
B(cx).insert_value(AggVal, EltVal, Index)
717+
pub fn InsertValue(cx: @mut Block, AggVal: ValueRef, EltVal: ValueRef, Index: uint) -> ValueRef {
718+
unsafe {
719+
if cx.unreachable { return llvm::LLVMGetUndef(Type::nil().to_ref()); }
720+
B(cx).insert_value(AggVal, EltVal, Index)
721+
}
720722
}
721723

722724
pub fn IsNull(cx: @mut Block, Val: ValueRef) -> ValueRef {

src/librustc/middle/trans/builder.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -861,11 +861,11 @@ impl Builder {
861861
}
862862

863863
pub fn insert_value(&self, agg_val: ValueRef, elt: ValueRef,
864-
idx: uint) {
864+
idx: uint) -> ValueRef {
865865
self.count_insn("insertvalue");
866866
unsafe {
867867
llvm::LLVMBuildInsertValue(self.llbuilder, agg_val, elt, idx as c_uint,
868-
noname());
868+
noname())
869869
}
870870
}
871871

src/librustc/middle/trans/common.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ impl FunctionContext {
238238
}
239239

240240
pub fn out_arg_pos(&self) -> uint {
241-
assert!(self.has_immediate_return_value);
241+
assert!(!self.has_immediate_return_value);
242242
0u
243243
}
244244

src/librustc/middle/trans/foreign.rs

+49
Original file line numberDiff line numberDiff line change
@@ -550,6 +550,24 @@ pub fn trans_intrinsic(ccx: @mut CrateContext,
550550
Ret(bcx, Call(bcx, llfn, args.slice(0, num_args)));
551551
}
552552

553+
fn with_overflow_instrinsic(bcx: @mut Block, name: &'static str) {
554+
let first_real_arg = bcx.fcx.arg_pos(0u);
555+
let a = get_param(bcx.fcx.llfn, first_real_arg);
556+
let b = get_param(bcx.fcx.llfn, first_real_arg + 1);
557+
let llfn = bcx.ccx().intrinsics.get_copy(&name);
558+
559+
// convert `i1` to a `bool`, and write to the out parameter
560+
let val = Call(bcx, llfn, [a, b]);
561+
let result = ExtractValue(bcx, val, 0);
562+
let overflow = ZExt(bcx, ExtractValue(bcx, val, 1), Type::bool());
563+
let retptr = get_param(bcx.fcx.llfn, bcx.fcx.out_arg_pos());
564+
let ret = Load(bcx, retptr);
565+
let ret = InsertValue(bcx, ret, result, 0);
566+
let ret = InsertValue(bcx, ret, overflow, 1);
567+
Store(bcx, ret, retptr);
568+
RetVoid(bcx)
569+
}
570+
553571
fn memcpy_intrinsic(bcx: @mut Block, name: &'static str, tp_ty: ty::t, sizebits: u8) {
554572
let ccx = bcx.ccx();
555573
let lltp_ty = type_of::type_of(ccx, tp_ty);
@@ -944,6 +962,37 @@ pub fn trans_intrinsic(ccx: @mut CrateContext,
944962
"bswap16" => simple_llvm_intrinsic(bcx, "llvm.bswap.i16", 1),
945963
"bswap32" => simple_llvm_intrinsic(bcx, "llvm.bswap.i32", 1),
946964
"bswap64" => simple_llvm_intrinsic(bcx, "llvm.bswap.i64", 1),
965+
966+
"i8_add_with_overflow" => with_overflow_instrinsic(bcx, "llvm.sadd.with.overflow.i8"),
967+
"i16_add_with_overflow" => with_overflow_instrinsic(bcx, "llvm.sadd.with.overflow.i16"),
968+
"i32_add_with_overflow" => with_overflow_instrinsic(bcx, "llvm.sadd.with.overflow.i32"),
969+
"i64_add_with_overflow" => with_overflow_instrinsic(bcx, "llvm.sadd.with.overflow.i64"),
970+
971+
"u8_add_with_overflow" => with_overflow_instrinsic(bcx, "llvm.uadd.with.overflow.i8"),
972+
"u16_add_with_overflow" => with_overflow_instrinsic(bcx, "llvm.uadd.with.overflow.i16"),
973+
"u32_add_with_overflow" => with_overflow_instrinsic(bcx, "llvm.uadd.with.overflow.i32"),
974+
"u64_add_with_overflow" => with_overflow_instrinsic(bcx, "llvm.uadd.with.overflow.i64"),
975+
976+
"i8_sub_with_overflow" => with_overflow_instrinsic(bcx, "llvm.ssub.with.overflow.i8"),
977+
"i16_sub_with_overflow" => with_overflow_instrinsic(bcx, "llvm.ssub.with.overflow.i16"),
978+
"i32_sub_with_overflow" => with_overflow_instrinsic(bcx, "llvm.ssub.with.overflow.i32"),
979+
"i64_sub_with_overflow" => with_overflow_instrinsic(bcx, "llvm.ssub.with.overflow.i64"),
980+
981+
"u8_sub_with_overflow" => with_overflow_instrinsic(bcx, "llvm.usub.with.overflow.i8"),
982+
"u16_sub_with_overflow" => with_overflow_instrinsic(bcx, "llvm.usub.with.overflow.i16"),
983+
"u32_sub_with_overflow" => with_overflow_instrinsic(bcx, "llvm.usub.with.overflow.i32"),
984+
"u64_sub_with_overflow" => with_overflow_instrinsic(bcx, "llvm.usub.with.overflow.i64"),
985+
986+
"i8_mul_with_overflow" => with_overflow_instrinsic(bcx, "llvm.smul.with.overflow.i8"),
987+
"i16_mul_with_overflow" => with_overflow_instrinsic(bcx, "llvm.smul.with.overflow.i16"),
988+
"i32_mul_with_overflow" => with_overflow_instrinsic(bcx, "llvm.smul.with.overflow.i32"),
989+
"i64_mul_with_overflow" => with_overflow_instrinsic(bcx, "llvm.smul.with.overflow.i64"),
990+
991+
"u8_mul_with_overflow" => with_overflow_instrinsic(bcx, "llvm.umul.with.overflow.i8"),
992+
"u16_mul_with_overflow" => with_overflow_instrinsic(bcx, "llvm.umul.with.overflow.i16"),
993+
"u32_mul_with_overflow" => with_overflow_instrinsic(bcx, "llvm.umul.with.overflow.i32"),
994+
"u64_mul_with_overflow" => with_overflow_instrinsic(bcx, "llvm.umul.with.overflow.i64"),
995+
947996
_ => {
948997
// Could we make this an enum rather than a string? does it get
949998
// checked earlier?

src/librustc/middle/trans/type_use.rs

+16
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,22 @@ pub fn type_uses_for(ccx: @mut CrateContext, fn_id: def_id, n_tps: uint)
168168

169169
"bswap16" | "bswap32" | "bswap64" => 0,
170170

171+
172+
"i8_add_with_overflow" | "u8_add_with_overflow" |
173+
"i16_add_with_overflow" | "u16_add_with_overflow" |
174+
"i32_add_with_overflow" | "u32_add_with_overflow" |
175+
"i64_add_with_overflow" | "u64_add_with_overflow" => 0,
176+
177+
"i8_sub_with_overflow" | "u8_sub_with_overflow" |
178+
"i16_sub_with_overflow" | "u16_sub_with_overflow" |
179+
"i32_sub_with_overflow" | "u32_sub_with_overflow" |
180+
"i64_sub_with_overflow" | "u64_sub_with_overflow" => 0,
181+
182+
"i8_mul_with_overflow" | "u8_mul_with_overflow" |
183+
"i16_mul_with_overflow" | "u16_mul_with_overflow" |
184+
"i32_mul_with_overflow" | "u32_mul_with_overflow" |
185+
"i64_mul_with_overflow" | "u64_mul_with_overflow" => 0,
186+
171187
// would be cool to make these an enum instead of
172188
// strings!
173189
_ => fail!("unknown intrinsic in type_use")

src/librustc/middle/typeck/check/mod.rs

+33
Original file line numberDiff line numberDiff line change
@@ -3647,6 +3647,39 @@ pub fn check_intrinsic_type(ccx: @mut CrateCtxt, it: @ast::foreign_item) {
36473647
"bswap16" => (0, ~[ ty::mk_i16() ], ty::mk_i16()),
36483648
"bswap32" => (0, ~[ ty::mk_i32() ], ty::mk_i32()),
36493649
"bswap64" => (0, ~[ ty::mk_i64() ], ty::mk_i64()),
3650+
3651+
"i8_add_with_overflow" | "i8_sub_with_overflow" | "i8_mul_with_overflow" =>
3652+
(0, ~[ty::mk_i8(), ty::mk_i8()],
3653+
ty::mk_tup(tcx, ~[ty::mk_i8(), ty::mk_bool()])),
3654+
3655+
"i16_add_with_overflow" | "i16_sub_with_overflow" | "i16_mul_with_overflow" =>
3656+
(0, ~[ty::mk_i16(), ty::mk_i16()],
3657+
ty::mk_tup(tcx, ~[ty::mk_i16(), ty::mk_bool()])),
3658+
3659+
"i32_add_with_overflow" | "i32_sub_with_overflow" | "i32_mul_with_overflow" =>
3660+
(0, ~[ty::mk_i32(), ty::mk_i32()],
3661+
ty::mk_tup(tcx, ~[ty::mk_i32(), ty::mk_bool()])),
3662+
3663+
"i64_add_with_overflow" | "i64_sub_with_overflow" | "i64_mul_with_overflow" =>
3664+
(0, ~[ty::mk_i64(), ty::mk_i64()],
3665+
ty::mk_tup(tcx, ~[ty::mk_i64(), ty::mk_bool()])),
3666+
3667+
"u8_add_with_overflow" | "u8_sub_with_overflow" | "u8_mul_with_overflow" =>
3668+
(0, ~[ty::mk_u8(), ty::mk_u8()],
3669+
ty::mk_tup(tcx, ~[ty::mk_u8(), ty::mk_bool()])),
3670+
3671+
"u16_add_with_overflow" | "u16_sub_with_overflow" | "u16_mul_with_overflow" =>
3672+
(0, ~[ty::mk_u16(), ty::mk_u16()],
3673+
ty::mk_tup(tcx, ~[ty::mk_u16(), ty::mk_bool()])),
3674+
3675+
"u32_add_with_overflow" | "u32_sub_with_overflow" | "u32_mul_with_overflow"=>
3676+
(0, ~[ty::mk_u32(), ty::mk_u32()],
3677+
ty::mk_tup(tcx, ~[ty::mk_u32(), ty::mk_bool()])),
3678+
3679+
"u64_add_with_overflow" | "u64_sub_with_overflow" | "u64_mul_with_overflow" =>
3680+
(0, ~[ty::mk_u64(), ty::mk_u64()],
3681+
ty::mk_tup(tcx, ~[ty::mk_u64(), ty::mk_bool()])),
3682+
36503683
ref other => {
36513684
tcx.sess.span_err(it.span,
36523685
fmt!("unrecognized intrinsic function: `%s`",

0 commit comments

Comments
 (0)