authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-07-05 22:24:25+00:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2020-07-05 22:24:25+00:00
logdcca5cf1a9241e7274ae03a587b7e3313d673f3e
tree6b4ca8bd860d267f3c75ba37e78d0acd9bc49753
parent289eab9177443bdfadfe750afda8f7f32f43be0f
parentb8553b4813e971e50dcae7b8181e5f6771f3dbff
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #5797 from xackus/intcast-runtime-safety

stage1: `@intcast` runtime safety for unsigned -> signed of same bit count

5 files changed, 19 insertions(+), 7 deletions(-)

lib/std/special/compiler_rt/clzsi2_test.zig+1-1
...@@ -4,7 +4,7 @@ const testing = @import("std").testing;...@@ -4,7 +4,7 @@ const testing = @import("std").testing;
4fn test__clzsi2(a: u32, expected: i32) void {4fn test__clzsi2(a: u32, expected: i32) void {
5 var nakedClzsi2 = clzsi2.__clzsi2;5 var nakedClzsi2 = clzsi2.__clzsi2;
6 var actualClzsi2 = @ptrCast(fn (a: i32) callconv(.C) i32, nakedClzsi2);6 var actualClzsi2 = @ptrCast(fn (a: i32) callconv(.C) i32, nakedClzsi2);
7 var x = @intCast(i32, a);7 var x = @bitCast(i32, a);
8 var result = actualClzsi2(x);8 var result = actualClzsi2(x);
9 testing.expectEqual(expected, result);9 testing.expectEqual(expected, result);
10}10}
lib/std/special/compiler_rt/int.zig+1-1
...@@ -244,7 +244,7 @@ pub fn __udivsi3(n: u32, d: u32) callconv(.C) u32 {...@@ -244,7 +244,7 @@ pub fn __udivsi3(n: u32, d: u32) callconv(.C) u32 {
244 // r.all -= d.all;244 // r.all -= d.all;
245 // carry = 1;245 // carry = 1;
246 // }246 // }
247 const s = @intCast(i32, d -% r -% 1) >> @intCast(u5, n_uword_bits - 1);247 const s = @bitCast(i32, d -% r -% 1) >> @intCast(u5, n_uword_bits - 1);
248 carry = @intCast(u32, s & 1);248 carry = @intCast(u32, s & 1);
249 r -= d & @bitCast(u32, s);249 r -= d & @bitCast(u32, s);
250 }250 }
lib/std/special/compiler_rt/udivmod.zig+1-1
...@@ -184,7 +184,7 @@ pub fn udivmod(comptime DoubleInt: type, a: DoubleInt, b: DoubleInt, maybe_rem:...@@ -184,7 +184,7 @@ pub fn udivmod(comptime DoubleInt: type, a: DoubleInt, b: DoubleInt, maybe_rem:
184 // carry = 1;184 // carry = 1;
185 // }185 // }
186 r_all = @ptrCast(*align(@alignOf(SingleInt)) DoubleInt, &r[0]).*; // TODO issue #421186 r_all = @ptrCast(*align(@alignOf(SingleInt)) DoubleInt, &r[0]).*; // TODO issue #421
187 const s: SignedDoubleInt = @intCast(SignedDoubleInt, b -% r_all -% 1) >> (DoubleInt.bit_count - 1);187 const s: SignedDoubleInt = @bitCast(SignedDoubleInt, b -% r_all -% 1) >> (DoubleInt.bit_count - 1);
188 carry = @intCast(u32, s & 1);188 carry = @intCast(u32, s & 1);
189 r_all -= b & @bitCast(DoubleInt, s);189 r_all -= b & @bitCast(DoubleInt, s);
190 r = @ptrCast(*[2]SingleInt, &r_all).*; // TODO issue #421190 r = @ptrCast(*[2]SingleInt, &r_all).*; // TODO issue #421
src/codegen.cpp+6-4
...@@ -1535,9 +1535,11 @@ static LLVMValueRef gen_widen_or_shorten(CodeGen *g, bool want_runtime_safety, Z...@@ -1535,9 +1535,11 @@ static LLVMValueRef gen_widen_or_shorten(CodeGen *g, bool want_runtime_safety, Z
1535 zig_unreachable();1535 zig_unreachable();
1536 }1536 }
15371537
1538 if (actual_type->id == ZigTypeIdInt &&1538 if (actual_type->id == ZigTypeIdInt && want_runtime_safety && (
1539 !wanted_type->data.integral.is_signed && actual_type->data.integral.is_signed &&1539 // negative to unsigned
1540 want_runtime_safety)1540 (!wanted_type->data.integral.is_signed && actual_type->data.integral.is_signed) ||
1541 // unsigned would become negative
1542 (wanted_type->data.integral.is_signed && !actual_type->data.integral.is_signed && actual_bits == wanted_bits)))
1541 {1543 {
1542 LLVMValueRef zero = LLVMConstNull(get_llvm_type(g, actual_type));1544 LLVMValueRef zero = LLVMConstNull(get_llvm_type(g, actual_type));
1543 LLVMValueRef ok_bit = LLVMBuildICmp(g->builder, LLVMIntSGE, expr_val, zero, "");1545 LLVMValueRef ok_bit = LLVMBuildICmp(g->builder, LLVMIntSGE, expr_val, zero, "");
...@@ -1547,7 +1549,7 @@ static LLVMValueRef gen_widen_or_shorten(CodeGen *g, bool want_runtime_safety, Z...@@ -1547,7 +1549,7 @@ static LLVMValueRef gen_widen_or_shorten(CodeGen *g, bool want_runtime_safety, Z
1547 LLVMBuildCondBr(g->builder, ok_bit, ok_block, fail_block);1549 LLVMBuildCondBr(g->builder, ok_bit, ok_block, fail_block);
15481550
1549 LLVMPositionBuilderAtEnd(g->builder, fail_block);1551 LLVMPositionBuilderAtEnd(g->builder, fail_block);
1550 gen_safety_crash(g, PanicMsgIdCastNegativeToUnsigned);1552 gen_safety_crash(g, actual_type->data.integral.is_signed ? PanicMsgIdCastNegativeToUnsigned : PanicMsgIdCastTruncatedData);
15511553
1552 LLVMPositionBuilderAtEnd(g->builder, ok_block);1554 LLVMPositionBuilderAtEnd(g->builder, ok_block);
1553 }1555 }
test/runtime_safety.zig+10
...@@ -757,6 +757,16 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -757,6 +757,16 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
757 \\}757 \\}
758 );758 );
759759
760 cases.addRuntimeSafety("unsigned integer not fitting in cast to signed integer - same bit count",
761 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {
762 \\ @import("std").os.exit(126);
763 \\}
764 \\pub fn main() void {
765 \\ var value: u8 = 245;
766 \\ var casted = @intCast(i8, value);
767 \\}
768 );
769
760 cases.addRuntimeSafety("unwrap error",770 cases.addRuntimeSafety("unwrap error",
761 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {771 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {
762 \\ if (@import("std").mem.eql(u8, message, "attempt to unwrap error: Whatever")) {772 \\ if (@import("std").mem.eql(u8, message, "attempt to unwrap error: Whatever")) {